Skip to content

Commit

Permalink
feat support A128CBC-HS256 encryption algorithm for JWE
Browse files Browse the repository at this point in the history
Signed-off-by: Timo Glastra <[email protected]>
  • Loading branch information
TimoGlastra committed Feb 4, 2025
1 parent 3a2b741 commit ee77823
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 12 deletions.
19 changes: 9 additions & 10 deletions packages/askar/src/wallet/AskarBaseWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -497,7 +498,7 @@ export abstract class AskarBaseWallet implements Wallet {
...header,
apv,
apu,
enc: 'A256GCM',
enc: encryptionAlgorithm,
alg: 'ECDH-ES',
epk: ephemeralKey.jwkPublic,
}
Expand Down Expand Up @@ -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')
Expand All @@ -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([]),
Expand Down
42 changes: 41 additions & 1 deletion packages/askar/src/wallet/__tests__/AskarWallet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/wallet/Wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export interface UnpackedMessageContext {

export interface WalletDirectEncryptCompactJwtEcdhEsOptions {
recipientKey: Key
encryptionAlgorithm: 'A256GCM'
encryptionAlgorithm: 'A256GCM' | 'A128CBC-HS256'
apu?: string
apv?: string
data: Buffer
Expand Down

0 comments on commit ee77823

Please sign in to comment.