diff --git a/.github/workflows/roundtrip/Tiltfile b/.github/workflows/roundtrip/Tiltfile index 367247f4..cdc95d44 100644 --- a/.github/workflows/roundtrip/Tiltfile +++ b/.github/workflows/roundtrip/Tiltfile @@ -1,7 +1,7 @@ load("ext://helm_remote", "helm_remote") load("ext://helm_resource", "helm_resource", "helm_repo") -BACKEND_CHART_TAG = "1.6.0" +BACKEND_CHART_TAG = "0.0.0-sha-dbfcea7" EXTERNAL_URL = os.getenv("OPENTDF_EXTERNAL_URL", "http://localhost:65432") INGRESS_HOST_PORT = os.getenv("OPENTDF_INGRESS_HOST_PORT", "65432") diff --git a/README.md b/README.md index 4dc3fde4..44324f55 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,6 @@ Start a local, blank cluster. See [Integrate](https://github.com/opentdf/opentdf const cipherText = await client.encrypt(plainText); const clearText = await client.decrypt(cipherText); ``` -### Examples - -Review examples to see how to integrate. See [Examples](https://github.com/opentdf/opentdf/tree/main/examples) ## Distribute @@ -58,3 +55,4 @@ nvm use make test make start ``` + diff --git a/lib/src/auth/oidc.ts b/lib/src/auth/oidc.ts index bfc16bb3..0786c5d2 100644 --- a/lib/src/auth/oidc.ts +++ b/lib/src/auth/oidc.ts @@ -1,5 +1,6 @@ import { default as dpopFn } from 'dpop'; import { HttpRequest, withHeaders } from './auth.js'; +import { base64 } from '../encodings/index.js'; import { IllegalArgumentError } from '../errors.js'; import { cryptoPublicToPem, rstrip } from '../utils.js'; @@ -149,7 +150,7 @@ export class AccessToken { throw new IllegalArgumentError('No signature configured'); } const clientPubKey = await cryptoPublicToPem(this.signingKey.publicKey); - headers['X-VirtruPubKey'] = clientPubKey; + headers['X-VirtruPubKey'] = base64.encode(clientPubKey); headers.DPoP = await dpopFn(this.signingKey, url, 'POST'); return (this.request || fetch)(url, { method: 'POST', diff --git a/lib/tdf3/src/client/index.ts b/lib/tdf3/src/client/index.ts index 92ac8baa..367b3114 100644 --- a/lib/tdf3/src/client/index.ts +++ b/lib/tdf3/src/client/index.ts @@ -165,7 +165,7 @@ export async function createSessionKeys({ if (dpopKeys) { signingKeys = await dpopKeys; } else { - const keys = await cryptoService.generateKeyPair(); + const keys = await cryptoService.generateSigningKeyPair(); // signingKeys = await crypto.subtle.generateKey(rsaPkcs1Sha256(), true, ['sign']); signingKeys = await toCryptoKeyPair(keys); } diff --git a/lib/tdf3/src/crypto/declarations.ts b/lib/tdf3/src/crypto/declarations.ts index d8b6e99c..5d894cfc 100644 --- a/lib/tdf3/src/crypto/declarations.ts +++ b/lib/tdf3/src/crypto/declarations.ts @@ -75,6 +75,8 @@ export type CryptoService = { */ generateKeyPair: (size?: number) => Promise; + generateSigningKeyPair: () => Promise; + /** * Create an HMAC SHA256 hash */ diff --git a/lib/tdf3/src/crypto/index.ts b/lib/tdf3/src/crypto/index.ts index a975c856..5b50fa81 100644 --- a/lib/tdf3/src/crypto/index.ts +++ b/lib/tdf3/src/crypto/index.ts @@ -83,6 +83,23 @@ export async function generateKeyPair(size?: number): Promise { return crypto.subtle.generateKey(algoDomString, true, METHODS); } +/** + * Generate an RSA key pair suitable for signatures + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey} + */ +export async function generateSigningKeyPair(): Promise { + return crypto.subtle.generateKey( + { + name: 'RSASSA-PKCS1-v1_5', + hash: 'SHA-256', + modulusLength: 2048, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + }, + true, + ['sign', 'verify'] + ); +} + export async function cryptoToPemPair(keysMaybe: unknown): Promise { const keys = keysMaybe as CryptoKeyPair; if (!keys.privateKey || !keys.publicKey) { @@ -374,6 +391,7 @@ export const DefaultCryptoService: CryptoService = { generateInitializationVector, generateKey, generateKeyPair, + generateSigningKeyPair, hmac, randomBytes, sha256, diff --git a/lib/tests/mocha/unit/crypto-di.spec.ts b/lib/tests/mocha/unit/crypto-di.spec.ts index 7a8ac11f..5138b3a1 100644 --- a/lib/tests/mocha/unit/crypto-di.spec.ts +++ b/lib/tests/mocha/unit/crypto-di.spec.ts @@ -52,6 +52,9 @@ describe('CryptoService DI', () => { generateKeyPair: function (size?: number | undefined): Promise { throw new Error('Function not implemented.'); }, + generateSigningKeyPair: function (): Promise { + throw new Error('Function not implemented.'); + }, hmac: function (key: string, content: string): Promise { throw new Error('Function not implemented.'); }, diff --git a/remote-store/package-lock.json b/remote-store/package-lock.json index 2a106c74..f9843628 100644 --- a/remote-store/package-lock.json +++ b/remote-store/package-lock.json @@ -1365,9 +1365,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz", - "integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", + "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -1649,7 +1649,7 @@ "node_modules/@opentdf/client": { "version": "2.0.0", "resolved": "file:../lib/opentdf-client-2.0.0.tgz", - "integrity": "sha512-uHQ/wEL64Fbd+Zy6iLhka9kz0yUbbBMGCxZuPZxhliIy+KaNytZCpqs/uDuLxEk7/TKz54kY1TjOlWm1a0SbBw==", + "integrity": "sha512-10yZrGA4LQBNjUX52+qLld2fTjq2OLxfEmR6kkrlLo6dpuN4p+qUI+i1ducMEcr/4fruKxfj2vMr+0Tg97oolg==", "dependencies": { "ajv": "^8.12.0", "axios": "^1.6.1", @@ -2925,14 +2925,14 @@ } }, "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "uri-js": "^4.4.1" }, "funding": { "type": "github", diff --git a/web-app/package-lock.json b/web-app/package-lock.json index 491db44a..be4c9267 100644 --- a/web-app/package-lock.json +++ b/web-app/package-lock.json @@ -346,9 +346,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz", - "integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", + "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -602,7 +602,7 @@ "node_modules/@opentdf/client": { "version": "2.0.0", "resolved": "file:../lib/opentdf-client-2.0.0.tgz", - "integrity": "sha512-uHQ/wEL64Fbd+Zy6iLhka9kz0yUbbBMGCxZuPZxhliIy+KaNytZCpqs/uDuLxEk7/TKz54kY1TjOlWm1a0SbBw==", + "integrity": "sha512-10yZrGA4LQBNjUX52+qLld2fTjq2OLxfEmR6kkrlLo6dpuN4p+qUI+i1ducMEcr/4fruKxfj2vMr+0Tg97oolg==", "dependencies": { "ajv": "^8.12.0", "axios": "^1.6.1", @@ -619,14 +619,14 @@ } }, "node_modules/@opentdf/client/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "uri-js": "^4.4.1" }, "funding": { "type": "github", @@ -3937,9 +3937,9 @@ } }, "@babel/runtime": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz", - "integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", + "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", "requires": { "regenerator-runtime": "^0.14.0" } @@ -4097,7 +4097,7 @@ }, "@opentdf/client": { "version": "file:../lib/opentdf-client-2.0.0.tgz", - "integrity": "sha512-uHQ/wEL64Fbd+Zy6iLhka9kz0yUbbBMGCxZuPZxhliIy+KaNytZCpqs/uDuLxEk7/TKz54kY1TjOlWm1a0SbBw==", + "integrity": "sha512-10yZrGA4LQBNjUX52+qLld2fTjq2OLxfEmR6kkrlLo6dpuN4p+qUI+i1ducMEcr/4fruKxfj2vMr+0Tg97oolg==", "requires": { "ajv": "^8.12.0", "axios": "^1.6.1", @@ -4114,14 +4114,14 @@ }, "dependencies": { "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", "requires": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "uri-js": "^4.4.1" } }, "json-schema-traverse": {