diff --git a/packages/askar/src/wallet/AskarBaseWallet.ts b/packages/askar/src/wallet/AskarBaseWallet.ts index 64755bb951..5ae967425b 100644 --- a/packages/askar/src/wallet/AskarBaseWallet.ts +++ b/packages/askar/src/wallet/AskarBaseWallet.ts @@ -483,12 +483,13 @@ export abstract class AskarBaseWallet implements Wallet { data, header, }: WalletDirectEncryptCompactJwtEcdhEsOptions) { - if (encryptionAlgorithm !== 'A256GCM') { - throw new WalletError(`Encryption algorithm ${encryptionAlgorithm} is not supported. Only A256GCM is supported`) + if (encryptionAlgorithm !== 'A256GCM' && encryptionAlgorithm !== 'A128CBC-HS256') { + throw new WalletError( + `Encryption algorithm ${encryptionAlgorithm} is not supported. Only A256GCM and A128CBC-HS256 are supported` + ) } - // Only one supported for now - const encAlg = KeyAlgs.AesA256Gcm + const encAlg = encryptionAlgorithm === 'A256GCM' ? KeyAlgs.AesA256Gcm : KeyAlgs.AesA128CbcHs256 // Create ephemeral key const ephemeralKey = AskarKey.generate(keyAlgFromString(recipientKey.keyType)) @@ -497,7 +498,7 @@ export abstract class AskarBaseWallet implements Wallet { ...header, apv, apu, - enc: 'A256GCM', + enc: encryptionAlgorithm, alg: 'ECDH-ES', epk: ephemeralKey.jwkPublic, } @@ -548,8 +549,8 @@ export abstract class AskarBaseWallet implements Wallet { if (header.alg !== 'ECDH-ES') { throw new WalletError('Only ECDH-ES alg value is supported') } - if (header.enc !== 'A256GCM') { - throw new WalletError('Only A256GCM enc value is supported') + if (header.enc !== 'A256GCM' && header.enc !== 'A128CBC-HS256') { + throw new WalletError('Only A256GCM and A128CBC-HS256 enc values are supported') } if (!header.epk || typeof header.epk !== 'object') { throw new WalletError('header epk value must contain a JWK') @@ -566,9 +567,7 @@ export abstract class AskarBaseWallet implements Wallet { throw new WalletError('Key entry not found') } - // Only one supported for now - const encAlg = KeyAlgs.AesA256Gcm - + const encAlg = header.enc === 'A256GCM' ? KeyAlgs.AesA256Gcm : KeyAlgs.AesA128CbcHs256 const ecdh = new EcdhEs({ algId: Uint8Array.from(Buffer.from(header.enc)), apu: header.apu ? Uint8Array.from(TypedArrayEncoder.fromBase64(header.apu)) : Uint8Array.from([]), diff --git a/packages/askar/src/wallet/__tests__/AskarWallet.test.ts b/packages/askar/src/wallet/__tests__/AskarWallet.test.ts index 106d371dfc..687a48d59a 100644 --- a/packages/askar/src/wallet/__tests__/AskarWallet.test.ts +++ b/packages/askar/src/wallet/__tests__/AskarWallet.test.ts @@ -176,7 +176,7 @@ describe('AskarWallet basic operations', () => { await expect(askarWallet.verify({ key: k256Key, data: message, signature })).resolves.toStrictEqual(true) }) - test('Encrypt and decrypt using JWE ECDH-ES', async () => { + test('Encrypt and decrypt using JWE ECDH-ES A256GCM', async () => { const recipientKey = await askarWallet.createKey({ keyType: KeyType.P256, }) @@ -216,6 +216,46 @@ describe('AskarWallet basic operations', () => { expect(JsonEncoder.fromBuffer(data)).toEqual({ vp_token: ['something'] }) }) + test('Encrypt and decrypt using JWE ECDH-ES A128CBC-HS256', async () => { + const recipientKey = await askarWallet.createKey({ + keyType: KeyType.P256, + }) + + const apv = TypedArrayEncoder.toBase64URL(TypedArrayEncoder.fromString('nonce-from-auth-request')) + const apu = TypedArrayEncoder.toBase64URL(TypedArrayEncoder.fromString(await askarWallet.generateNonce())) + + const compactJwe = await askarWallet.directEncryptCompactJweEcdhEs({ + data: JsonEncoder.toBuffer({ vp_token: ['something'] }), + apu, + apv, + encryptionAlgorithm: 'A128CBC-HS256', + header: { + kid: 'some-kid', + }, + recipientKey, + }) + + const { data, header } = await askarWallet.directDecryptCompactJweEcdhEs({ + compactJwe, + recipientKey, + }) + + expect(header).toEqual({ + kid: 'some-kid', + apv, + apu, + enc: 'A128CBC-HS256', + alg: 'ECDH-ES', + epk: { + kty: 'EC', + crv: 'P-256', + x: expect.any(String), + y: expect.any(String), + }, + }) + expect(JsonEncoder.fromBuffer(data)).toEqual({ vp_token: ['something'] }) + }) + test('decrypt using JWE ECDH-ES based on test vector from OpenID Conformance test', async () => { const { compactJwe, diff --git a/packages/core/src/wallet/Wallet.ts b/packages/core/src/wallet/Wallet.ts index aebe9c592b..dcd2a46863 100644 --- a/packages/core/src/wallet/Wallet.ts +++ b/packages/core/src/wallet/Wallet.ts @@ -122,7 +122,7 @@ export interface UnpackedMessageContext { export interface WalletDirectEncryptCompactJwtEcdhEsOptions { recipientKey: Key - encryptionAlgorithm: 'A256GCM' + encryptionAlgorithm: 'A256GCM' | 'A128CBC-HS256' apu?: string apv?: string data: Buffer