Skip to content

Commit

Permalink
fix: Fix key usages for jwks when importing keys
Browse files Browse the repository at this point in the history
nklomp committed Jul 30, 2024
1 parent 1adc1fe commit c473572
Showing 9 changed files with 48 additions and 18 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-test-on-pr.yml
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: '18.x'
node-version: '20.x'
cache: 'pnpm'
- run: pnpm install
- run: pnpm build
2 changes: 1 addition & 1 deletion .github/workflows/build-test-publish-on-push.yml
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: '18.x'
node-version: '20.x'
cache: 'pnpm'
- run: pnpm install
- run: pnpm build
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@
"name": "@sphereon/ssi-sdk-ext.workspace",
"private": true,
"version": "0.11.0",
"description": "Sphereon Crypto Extensions (BBS+/EBSI) signature support (Workspace)",
"repository": "[email protected]:Sphereon-Opensource/veramo-BBS.git",
"description": "Sphereon Crypto Extensions and DID support (Workspace)",
"repository": "[email protected]:Sphereon-Opensource/SSI-SDK-crypto-extensions.git",
"author": "Sphereon <[email protected]>",
"license": "Apache-2.0",
"scripts": {
Original file line number Diff line number Diff line change
@@ -266,7 +266,7 @@ describe('@sphereon/did-provider-jwk comparison ES256', () => {
})
})

it('Creation DID Document from testvector JWK', async () => {
/*it('Creation DID Document from testvector JWK', async () => {
const jwk = {
kid: 'urn:ietf:params:oauth:jwk-thumbprint:sha-256:T9XxxVUPtvL7tgGL9Y8jTxXCOT1LF7nSesZytwqi5S8',
kty: 'EC',
@@ -276,9 +276,9 @@ describe('@sphereon/did-provider-jwk comparison ES256', () => {
y: 's4xcAXRuhCVta6bh_Uss7xNv4gyRDUAnRKcsFRB32oY',
d: 'DW08IHT19g2-I3UeTKquzq10dZucrNETLkgaXdmHsgE',
}
console.log(jwk)
// console.log(jwk)
})

*/
it('Creation from privateKeyHex', async () => {
/*const privateKeyHex = await generatePrivateKeyHex('Secp256r1')
console.log(privateKeyHex)*/
@@ -291,12 +291,12 @@ describe('@sphereon/did-provider-jwk comparison ES256', () => {
type: Key.Secp256r1,
}
const identifier: IIdentifier = await agent.didManagerCreate({ options })
console.log('=============================================================')
/*console.log('=============================================================')
console.log(
'test against: did:jwk:eyJhbGciOiJFUzI1NiIsInVzZSI6InNpZyIsImt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoiOWdnczRDbTRWWGNLT2VQcGprTDlpU3lNQ2EyMnlPamJvLW9VWHB5LWF3MCIsInkiOiJsRVhXN2JfSjdsY2VpVkV0cmZwdHZ1UGVFTnNPSmwtZmh6bXU2NTRHUFI4In0'
)
console.log(JSON.stringify(identifier, null, 2))
console.log('=============================================================')
console.log('=============================================================')*/
const did =
'did:jwk:eyJhbGciOiJFUzI1NiIsInVzZSI6InNpZyIsImt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoiOWdnczRDbTRWWGNLT2VQcGprTDlpU3lNQ2EyMnlPamJvLW9VWHB5LWF3MCIsInkiOiJsRVhXN2JfSjdsY2VpVkV0cmZwdHZ1UGVFTnNPSmwtZmh6bXU2NTRHUFI4In0'
expect(identifier.did).toBe(did)
10 changes: 5 additions & 5 deletions packages/did-provider-key/__tests__/key-did-provider.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SphereonKeyManager } from '@sphereon/ssi-sdk-ext.key-manager'

import { Key, toJwk } from '@sphereon/ssi-sdk-ext.key-utils'
import { Key } from '@sphereon/ssi-sdk-ext.key-utils'
import { SphereonKeyManagementSystem } from '@sphereon/ssi-sdk-ext.kms-local'
import { createAgent, IIdentifier, IKeyManager } from '@veramo/core'
import { DIDManager, MemoryDIDStore } from '@veramo/did-manager'
@@ -11,8 +11,8 @@ import { SphereonKeyDidProvider } from '../src'
const DID_METHOD = 'did:key'
const PRIVATE_KEY_HEX = '7dd923e40f4615ac496119f7e793cc2899e99b64b88ca8603db986700089532b'

const jwk = toJwk(PRIVATE_KEY_HEX, 'Secp256k1', { isPrivateKey: true })
console.log(JSON.stringify(jwk, null, 2))
// const jwk = toJwk(PRIVATE_KEY_HEX, 'Secp256k1', { isPrivateKey: true })
// console.log(JSON.stringify(jwk, null, 2))
const keyDIDProvider = new SphereonKeyDidProvider({
defaultKms: 'mem',
})
@@ -96,7 +96,7 @@ describe('@sphereon/did-provider-key', () => {
expect(identifier.keys.length).toBe(1)
expect(identifier.keys[0].type).toBe(Key.Secp256k1)

console.log(identifier.did)
// console.log(identifier.did)
})

it('should create EBSI identifier with Secp256r1 key', async () => {
@@ -113,6 +113,6 @@ describe('@sphereon/did-provider-key', () => {
expect(identifier.keys.length).toBe(1)
expect(identifier.keys[0].type).toBe(Key.Secp256r1)

console.log(identifier.did)
// console.log(identifier.did)
})
})
4 changes: 2 additions & 2 deletions packages/did-provider-key/src/SphereonKeyDidProvider.ts
Original file line number Diff line number Diff line change
@@ -57,13 +57,13 @@ export class SphereonKeyDidProvider extends AbstractIdentifierProvider {
| CodeNameType
| undefined
const keyType: TKeyType = options?.type ?? (codecName === JWK_JCS_PUB_NAME ? 'Secp256r1' : 'Secp256k1')
console.log(`keytype: ${keyType}, codecName: ${codecName}`)
// console.log(`keytype: ${keyType}, codecName: ${codecName}`)
const privateKeyHex = options?.key?.privateKeyHex ?? (await generatePrivateKeyHex(keyType))
const key = await context.agent.keyManagerImport({ type: keyType, privateKeyHex, kms: kms ?? this.kms })
let methodSpecificId: string | undefined
if (codecName === JWK_JCS_PUB_NAME) {
const jwk = toJwk(key.publicKeyHex, keyType, { use: JwkKeyUse.Signature, key, noKidThumbprint: true })
console.log(`FIXME JWK: ${JSON.stringify(toJwk(privateKeyHex, keyType, { use: JwkKeyUse.Signature, key, isPrivateKey: true }), null, 2)}`)
// console.log(`FIXME JWK: ${JSON.stringify(toJwk(privateKeyHex, keyType, { use: JwkKeyUse.Signature, key, isPrivateKey: true }), null, 2)}`)
methodSpecificId = u8a.toString(
Multibase.encode('base58btc', Multicodec.addPrefix(u8a.fromString(JWK_JCS_PUB_PREFIX.valueOf().toString(16), 'hex'), jwkJcsEncode(jwk)))
)
22 changes: 21 additions & 1 deletion packages/key-utils/src/x509/rsa-key.ts
Original file line number Diff line number Diff line change
@@ -8,8 +8,28 @@ export type RSASignatureSchemes = 'RSASSA-PKCS1-V1_5' | 'RSA-PSS'
export type RSAEncryptionSchemes = 'RSAES-PKCS-v1_5 ' | 'RSAES-OAEP'

const usage = (jwk: JWK): KeyUsage[] => {
if (jwk.key_ops && jwk.key_ops.length > 0) {
return jwk.key_ops as KeyUsage[]
}
if (jwk.use) {
const usages: KeyUsage[] = []
if (jwk.use.includes('sig')) {
usages.push('sign', 'verify')
} else if (jwk.use.includes('enc')) {
usages.push('encrypt', 'decrypt')
}
if (usages.length > 0) {
return usages
}
}
if (jwk.kty === 'RSA') {
if (jwk.d) {
return jwk.alg?.toUpperCase()?.includes('QAEP') ? ['encrypt'] : ['sign']
}
return jwk.alg?.toUpperCase()?.includes('QAEP') ? ['decrypt'] : ['verify']
}
// "decrypt" | "deriveBits" | "deriveKey" | "encrypt" | "sign" | "unwrapKey" | "verify" | "wrapKey";
return jwk.d ? ['sign', 'decrypt', 'verify', 'encrypt'] : ['verify', 'encrypt']
return jwk.d && jwk.kty !== 'RSA' ? ['sign', 'decrypt', 'verify', 'encrypt'] : ['verify']
}

export const signAlgorithmToSchemeAndHashAlg = (signingAlg: string) => {
11 changes: 10 additions & 1 deletion packages/key-utils/src/x509/rsa-signer.ts
Original file line number Diff line number Diff line change
@@ -66,7 +66,16 @@ export class RSASigner {
const jws = signature.includes('.') ? signature.split('.')[2] : signature

const input = typeof data == 'string' ? u8a.fromString(data, 'utf-8') : data
const verificationResult = await crypto.subtle.verify(this.getImportParams(), await this.getKey(), u8a.fromString(jws, 'base64url'), input)

let key = await this.getKey()
if (!key.usages.includes('verify')) {
const verifyJwk = { ...this.jwk }
delete verifyJwk.d
delete verifyJwk.use
delete verifyJwk.key_ops
key = await cryptoSubtleImportRSAKey(verifyJwk, this.scheme, this.hashAlgorithm)
}
const verificationResult = await crypto.subtle.verify(this.getImportParams(), key, u8a.fromString(jws, 'base64url'), input)
return verificationResult
}
}
1 change: 1 addition & 0 deletions packages/kms-local/src/__tests__/rsa.test.ts
Original file line number Diff line number Diff line change
@@ -150,6 +150,7 @@ describe('RSA Signer', () => {
})
const signature = await signer.sign(u8a.fromString('test123', 'utf-8'))
expect(signature).toBeDefined()

const result = await signer.verify('test123', signature)
expect(result).toBeTruthy()
})

0 comments on commit c473572

Please sign in to comment.