Skip to content

Commit

Permalink
feat(key-manager): add generic signing capabilities (#529)
Browse files Browse the repository at this point in the history
* test(key-manager): add tests using testvectors for `keyManagerSign*`

* feat(key-manager): add generic signing capabilities

* feat(did-provider-ethr): use generic signer in did:ethr provider

* fix(did-provider-ethr): fix web3 provider and transaction data for did:ethr CRUD

fixes #522

* feat(key-manager): add default implementation to legacy sign methods that leverage the unified signer

* test(key-manager): add extra tests using testvectors for `keyManagerSign()`

* chore(kms-local): rename parameters of `sign()` method & separate signing code into methods
  • Loading branch information
mirceanis authored Jun 3, 2021
1 parent ae0661f commit 5f10a1b
Show file tree
Hide file tree
Showing 26 changed files with 817 additions and 338 deletions.
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
"typescript.tsdk": "node_modules/typescript/lib",
"cSpell.words": [
"arrayify",
"ethersproject"
]
}
119 changes: 117 additions & 2 deletions __tests__/shared/keyManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { TKeyType } from '@veramo/core'
import { TAgent, IDIDManager, IKeyManager, IAgentOptions } from '../../packages/core/src'
import { ICredentialIssuer } from '@veramo/credential-w3c/src'
import { serialize } from '@ethersproject/transactions'

type ConfiguredAgent = TAgent<IDIDManager & IKeyManager>

Expand Down Expand Up @@ -179,8 +182,8 @@ export default (testContext: {
transaction: {
to: '0xce31a19193d4b23f4e9d6163d7247243bAF801c3',
value: 300000,
gas: 43092000,
gasPrice: '20000000000',
gasLimit: 43092000,
gasPrice: 20000000000,
nonce: 1,
},
})
Expand Down Expand Up @@ -218,5 +221,117 @@ export default (testContext: {
// expect(decrypted).toEqual(message)

// })

describe('using Secp256k1 testvectors', () => {
const importedKey = {
kid:
'04155ee0cbefeecd80de63a62b4ed8f0f97ac22a58f76a265903b9acab79bf018c7037e2bd897812170c92a4c978d6a10481491a37299d74c4bd412a111a4ac875',
kms: 'local',
type: <TKeyType>'Secp256k1',
publicKeyHex:
'04155ee0cbefeecd80de63a62b4ed8f0f97ac22a58f76a265903b9acab79bf018c7037e2bd897812170c92a4c978d6a10481491a37299d74c4bd412a111a4ac875',
privateKeyHex: '31d1ec15ff8110442012fef0d1af918c0e09b2e2ab821bba52ecc85f8655ec63',
}

beforeAll(async () => {
const imported = await agent.keyManagerImport(importedKey)
})

it('should sign JWT using legacy method', async () => {
const signature = await agent.keyManagerSignJWT({
kid: importedKey.kid,
data: 'bla.bla',
})
expect(signature).toEqual(
'pNAFkgmuKhqMbb_6Km--ZmY7UCkWunWUuNajSfF6rv5lEa5nNXCU7cnZBZVptU7u8h150qetqkqUaahAf-Cepw',
)
})

it('should sign EthTX using legacy method', async () => {
const rawTx = await agent.keyManagerSignEthTX({
kid: importedKey.kid,
transaction: {
to: '0xce31a19193d4b23f4e9d6163d7247243bAF801c3',
value: 300000,
gasLimit: 43092000,
gasPrice: 20000000000,
nonce: 1,
},
})
expect(rawTx).toEqual(
'0xf869018504a817c800840291882094ce31a19193d4b23f4e9d6163d7247243baf801c3830493e0801ba0f16e2206290181c3feaa04051dad19089105c24339dbdf0d80147b48a59fa152a0770e8751ec77ccc78e8b207023f168444f7cfb67055c55c70ef75234458a3d51',
)
})

it('should sign JWT using generic signer', async () => {
const signature = await agent.keyManagerSign({
algorithm: 'ES256K',
data: 'bla.bla',
encoding: 'utf-8',
keyRef: importedKey.kid,
})
expect(signature).toEqual(
'pNAFkgmuKhqMbb_6Km--ZmY7UCkWunWUuNajSfF6rv5lEa5nNXCU7cnZBZVptU7u8h150qetqkqUaahAf-Cepw',
)
})

it('should sign EthTX using generic signer', async () => {
const txData = serialize({
to: '0xce31a19193d4b23f4e9d6163d7247243bAF801c3',
value: 300000,
gasLimit: 43092000,
gasPrice: 20000000000,
nonce: 1,
})

const rawTx = await agent.keyManagerSign({
algorithm: 'eth_signTransaction',
data: txData,
encoding: 'hex',
keyRef: importedKey.kid,
})

expect(rawTx).toEqual(
'0xf869018504a817c800840291882094ce31a19193d4b23f4e9d6163d7247243baf801c3830493e0801ba0f16e2206290181c3feaa04051dad19089105c24339dbdf0d80147b48a59fa152a0770e8751ec77ccc78e8b207023f168444f7cfb67055c55c70ef75234458a3d51',
)
})
})

describe('using Ed25519 testvectors', () => {
const importedKey = {
kid: 'ea75250531f6834328ac210618253288e4c54632962a9708ca82e4a399f79000',
kms: 'local',
type: <TKeyType>'Ed25519',
publicKeyHex: 'ea75250531f6834328ac210618253288e4c54632962a9708ca82e4a399f79000',
privateKeyHex:
'65f341541643070564bb48d9fc10556f2dec246fa056e436a8ec1cdef8c74766ea75250531f6834328ac210618253288e4c54632962a9708ca82e4a399f79000',
}

beforeAll(async () => {
const imported = await agent.keyManagerImport(importedKey)
})

it('should sign JWT using legacy method', async () => {
const signature = await agent.keyManagerSignJWT({
kid: importedKey.kid,
data: 'bla.bla',
})
expect(signature).toEqual(
'_2P0iukN2CPH1nQ6LeBm1zQHHp3U4wSYDrpeWTWkp7yuzJex6O60Z4OhdfD5I9WPHV734US8n5vyD2VDbT1UCg',
)
})

it('should sign JWT using generic signer', async () => {
const signature = await agent.keyManagerSign({
keyRef: importedKey.kid,
data: 'bla.bla',
algorithm: 'EdDSA',
encoding: 'utf-8',
})
expect(signature).toEqual(
'_2P0iukN2CPH1nQ6LeBm1zQHHp3U4wSYDrpeWTWkp7yuzJex6O60Z4OhdfD5I9WPHV734US8n5vyD2VDbT1UCg',
)
})
})
})
}
47 changes: 47 additions & 0 deletions __tests__/shared/verifiableData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { TAgent, IDIDManager, IIdentifier, IDataStore } from '../../packages/cor
import { IDataStoreORM } from '../../packages/data-store/src'
import { ICredentialIssuer } from '../../packages/credential-w3c/src'
import { decodeJWT } from 'did-jwt'
import { TKeyType } from '@veramo/core'

type ConfiguredAgent = TAgent<IDIDManager & ICredentialIssuer & IDataStore & IDataStoreORM>

Expand Down Expand Up @@ -239,5 +240,51 @@ export default (testContext: {
}),
).rejects.toThrow('Verifiable presentation not found')
})

describe('using testvectors', () => {
const importedDID = {
did: 'did:ethr:rinkeby:0x03155ee0cbefeecd80de63a62b4ed8f0f97ac22a58f76a265903b9acab79bf018c',
provider: 'did:ethr:rinkeby',
controllerKeyId:
'04155ee0cbefeecd80de63a62b4ed8f0f97ac22a58f76a265903b9acab79bf018c7037e2bd897812170c92a4c978d6a10481491a37299d74c4bd412a111a4ac875',
keys: [
{
kid:
'04155ee0cbefeecd80de63a62b4ed8f0f97ac22a58f76a265903b9acab79bf018c7037e2bd897812170c92a4c978d6a10481491a37299d74c4bd412a111a4ac875',
kms: 'local',
type: <TKeyType>'Secp256k1',
publicKeyHex:
'04155ee0cbefeecd80de63a62b4ed8f0f97ac22a58f76a265903b9acab79bf018c7037e2bd897812170c92a4c978d6a10481491a37299d74c4bd412a111a4ac875',
privateKeyHex: '31d1ec15ff8110442012fef0d1af918c0e09b2e2ab821bba52ecc85f8655ec63',
},
],
services: [],
}

beforeAll(async () => {
const imported = await agent.didManagerImport(importedDID)
})

it('signs JWT with ES256K', async () => {
const credentialInput = {
credentialSubject: { id: 'did:example:subject', name: 'Alice' },
issuer: { id: importedDID.did },
}
const { proof, issuanceDate, ...comparableOutput } = await agent.createVerifiableCredential({
credential: credentialInput,
proofFormat: 'jwt',
save: false,
removeOriginalFields: true,
})
expect(comparableOutput).toEqual({
credentialSubject: { name: 'Alice', id: 'did:example:subject' },
issuer: {
id: 'did:ethr:rinkeby:0x03155ee0cbefeecd80de63a62b4ed8f0f97ac22a58f76a265903b9acab79bf018c',
},
type: ['VerifiableCredential'],
'@context': ['https://www.w3.org/2018/credentials/v1'],
})
})
})
})
}
1 change: 1 addition & 0 deletions packages/cli/default/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ constants:
- keyManagerImport
- keyManagerEncryptJWE
- keyManagerDecryptJWE
- keyManagerSign
- keyManagerSignJWT
- keyManagerSignEthTX
- didManagerGetProviders
Expand Down
Loading

0 comments on commit 5f10a1b

Please sign in to comment.