Skip to content

Commit

Permalink
fix: jwe encryption/decryption issues (openwallet-foundation#2053)
Browse files Browse the repository at this point in the history
Signed-off-by: Timo Glastra <[email protected]>
Signed-off-by: Martin Auer <[email protected]>
  • Loading branch information
TimoGlastra authored and auer-martin committed Oct 15, 2024
1 parent 0afd97b commit 4732f53
Show file tree
Hide file tree
Showing 4 changed files with 7,878 additions and 5,282 deletions.
18 changes: 10 additions & 8 deletions packages/askar/src/wallet/AskarBaseWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -502,10 +502,10 @@ export abstract class AskarBaseWallet implements Wallet {
epk: ephemeralKey.jwkPublic,
}

const encodedHeader = JsonEncoder.toBuffer(_header)
const encodedHeader = JsonEncoder.toBase64URL(_header)

const ecdh = new EcdhEs({
algId: Uint8Array.from(Buffer.from(encAlg)),
algId: Uint8Array.from(Buffer.from(encryptionAlgorithm)),
apu: apu ? Uint8Array.from(TypedArrayEncoder.fromBase64(apu)) : Uint8Array.from([]),
apv: apv ? Uint8Array.from(TypedArrayEncoder.fromBase64(apv)) : Uint8Array.from([]),
})
Expand All @@ -518,12 +518,13 @@ export abstract class AskarBaseWallet implements Wallet {
algorithm: keyAlgFromString(recipientKey.keyType),
publicKey: recipientKey.publicKey,
}),
aad: Uint8Array.from(encodedHeader),
// NOTE: aad is bytes of base64url encoded string. It SHOULD NOT be decoded as base64
aad: Uint8Array.from(Buffer.from(encodedHeader)),
})

const compactJwe = `${TypedArrayEncoder.toBase64URL(encodedHeader)}..${TypedArrayEncoder.toBase64URL(
nonce
)}.${TypedArrayEncoder.toBase64URL(ciphertext)}.${TypedArrayEncoder.toBase64URL(tag)}`
const compactJwe = `${encodedHeader}..${TypedArrayEncoder.toBase64URL(nonce)}.${TypedArrayEncoder.toBase64URL(
ciphertext
)}.${TypedArrayEncoder.toBase64URL(tag)}`
return compactJwe
}

Expand Down Expand Up @@ -569,7 +570,7 @@ export abstract class AskarBaseWallet implements Wallet {
const encAlg = KeyAlgs.AesA256Gcm

const ecdh = new EcdhEs({
algId: Uint8Array.from(Buffer.from(encAlg)),
algId: Uint8Array.from(Buffer.from(header.enc)),
apu: header.apu ? Uint8Array.from(TypedArrayEncoder.fromBase64(header.apu)) : Uint8Array.from([]),
apv: header.apv ? Uint8Array.from(TypedArrayEncoder.fromBase64(header.apv)) : Uint8Array.from([]),
})
Expand All @@ -581,7 +582,8 @@ export abstract class AskarBaseWallet implements Wallet {
ephemeralKey: Jwk.fromJson(header.epk),
recipientKey: askarKey,
tag: TypedArrayEncoder.fromBase64(encodedTag),
aad: TypedArrayEncoder.fromBase64(encodedHeader),
// NOTE: aad is bytes of base64url encoded string. It SHOULD NOT be decoded as base64
aad: TypedArrayEncoder.fromString(encodedHeader),
})

return { data: Buffer.from(plaintext), header }
Expand Down
36 changes: 35 additions & 1 deletion packages/askar/src/wallet/__tests__/AskarWallet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
SignOptions,
VerifyOptions,
} from '@credo-ts/core'
import type { JwkProps } from '@hyperledger/aries-askar-shared'

import {
WalletKeyExistsError,
Expand All @@ -21,7 +22,10 @@ import {
Buffer,
JsonEncoder,
} from '@credo-ts/core'
import { Store } from '@hyperledger/aries-askar-shared'
import { Key as AskarKey } from '@hyperledger/aries-askar-nodejs'
import { Jwk, Store } from '@hyperledger/aries-askar-shared'
import { readFileSync } from 'fs'
import path from 'path'

import { KeyBackend } from '../../../../core/src/crypto/KeyBackend'
import { encodeToBase58 } from '../../../../core/src/utils/base58'
Expand Down Expand Up @@ -211,6 +215,36 @@ describe('AskarWallet basic operations', () => {
})
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,
decodedPayload,
privateKeyJwk,
header: expectedHeader,
} = JSON.parse(
readFileSync(path.join(__dirname, '__fixtures__/jarm-jwe-encrypted-response.json')).toString('utf-8')
) as {
compactJwe: string
decodedPayload: Record<string, unknown>
privateKeyJwk: JwkProps
header: string
}

const key = AskarKey.fromJwk({ jwk: Jwk.fromJson(privateKeyJwk) })
const recipientKey = await askarWallet.createKey({
keyType: KeyType.P256,
privateKey: Buffer.from(key.secretBytes),
})

const { data, header } = await askarWallet.directDecryptCompactJweEcdhEs({
compactJwe,
recipientKey,
})

expect(header).toEqual(expectedHeader)
expect(JsonEncoder.fromBuffer(data)).toEqual(decodedPayload)
})
})

describe.skip('Currently, all KeyTypes are supported by Askar natively', () => {
Expand Down

Large diffs are not rendered by default.

Loading

0 comments on commit 4732f53

Please sign in to comment.