Skip to content

Commit

Permalink
feat(askar): create keys in the secure element (#1938)
Browse files Browse the repository at this point in the history
Signed-off-by: Berend Sliedrecht <[email protected]>
  • Loading branch information
berendsliedrecht committed Jul 4, 2024
1 parent 352383f commit 9989ea7
Show file tree
Hide file tree
Showing 14 changed files with 106 additions and 58 deletions.
2 changes: 1 addition & 1 deletion demo-openid/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
"dependencies": {
"@hyperledger/anoncreds-nodejs": "^0.2.2",
"@hyperledger/aries-askar-nodejs": "^0.2.1",
"@hyperledger/aries-askar-nodejs": "^0.2.3",
"@hyperledger/indy-vdr-nodejs": "^0.2.2",
"express": "^4.18.1",
"inquirer": "^8.2.5"
Expand Down
2 changes: 1 addition & 1 deletion demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"dependencies": {
"@hyperledger/indy-vdr-nodejs": "^0.2.2",
"@hyperledger/anoncreds-nodejs": "^0.2.2",
"@hyperledger/aries-askar-nodejs": "^0.2.1",
"@hyperledger/aries-askar-nodejs": "^0.2.3",
"inquirer": "^8.2.5"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
},
"devDependencies": {
"@changesets/cli": "^2.27.5",
"@hyperledger/aries-askar-nodejs": "^0.2.1",
"@hyperledger/aries-askar-nodejs": "^0.2.3",
"@jest/types": "^29.6.3",
"@types/bn.js": "^5.1.5",
"@types/cors": "^2.8.10",
Expand Down
6 changes: 3 additions & 3 deletions packages/askar/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
"tsyringe": "^4.8.0"
},
"devDependencies": {
"@hyperledger/aries-askar-nodejs": "^0.2.1",
"@hyperledger/aries-askar-shared": "^0.2.1",
"@hyperledger/aries-askar-nodejs": "^0.2.3",
"@hyperledger/aries-askar-shared": "^0.2.3",
"@types/bn.js": "^5.1.0",
"@types/ref-array-di": "^1.2.6",
"@types/ref-struct-di": "^1.1.10",
Expand All @@ -44,6 +44,6 @@
"typescript": "~5.5.2"
},
"peerDependencies": {
"@hyperledger/aries-askar-shared": "^0.2.1"
"@hyperledger/aries-askar-shared": "^0.2.3"
}
}
11 changes: 11 additions & 0 deletions packages/askar/src/utils/askarKeyBackend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { KeyBackend as CredoKeyBackend } from '@credo-ts/core'
import { KeyBackend as AskarKeyBackend } from '@hyperledger/aries-askar-shared'

export const convertToAskarKeyBackend = (credoKeyBackend: CredoKeyBackend) => {
switch (credoKeyBackend) {
case CredoKeyBackend.Software:
return AskarKeyBackend.Software
case CredoKeyBackend.SecureElement:
return AskarKeyBackend.SecureElement
}
}
11 changes: 9 additions & 2 deletions packages/askar/src/wallet/AskarBaseWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
WalletError,
Key,
TypedArrayEncoder,
KeyBackend,
} from '@credo-ts/core'
import { CryptoBox, Store, Key as AskarKey, keyAlgFromString } from '@hyperledger/aries-askar-shared'
import BigNumber from 'bn.js'
Expand All @@ -35,6 +36,7 @@ import {
isKeyTypeSupportedByAskarForPurpose,
keyTypesSupportedByAskar,
} from '../utils'
import { convertToAskarKeyBackend } from '../utils/askarKeyBackend'

import { didcommV1Pack, didcommV1Unpack } from './didcommV1'

Expand Down Expand Up @@ -125,7 +127,12 @@ export abstract class AskarBaseWallet implements Wallet {
* Create a key with an optional seed and keyType.
* The keypair is also automatically stored in the wallet afterwards
*/
public async createKey({ seed, privateKey, keyType }: WalletCreateKeyOptions): Promise<Key> {
public async createKey({
seed,
privateKey,
keyType,
keyBackend = KeyBackend.Software,
}: WalletCreateKeyOptions): Promise<Key> {
try {
if (seed && privateKey) {
throw new WalletError('Only one of seed and privateKey can be set')
Expand All @@ -149,7 +156,7 @@ export abstract class AskarBaseWallet implements Wallet {
? AskarKey.fromSecretBytes({ secretKey: privateKey, algorithm })
: seed
? AskarKey.fromSeed({ seed, algorithm })
: AskarKey.generate(algorithm)
: AskarKey.generate(algorithm, convertToAskarKeyBackend(keyBackend))

// FIXME: we need to create a separate const '_key' so TS definitely knows _key is defined in the session callback.
// This will be fixed once we use the new 'using' syntax
Expand Down
27 changes: 16 additions & 11 deletions packages/askar/src/wallet/__tests__/AskarWallet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
} from '@credo-ts/core'
import { Store } from '@hyperledger/aries-askar-shared'

import { KeyBackend } from '../../../../core/src/crypto/KeyBackend'
import { encodeToBase58 } from '../../../../core/src/utils/base58'
import { agentDependencies } from '../../../../core/tests/helpers'
import testLogger from '../../../../core/tests/logger'
Expand Down Expand Up @@ -102,7 +103,7 @@ describe('AskarWallet basic operations', () => {
seed,
keyType: KeyType.Ed25519,
})
).rejects.toThrowError()
).rejects.toThrow()
})

test('Create x25519 keypair', async () => {
Expand All @@ -122,13 +123,17 @@ describe('AskarWallet basic operations', () => {
test('throws WalletKeyExistsError when a key already exists', async () => {
const privateKey = TypedArrayEncoder.fromString('2103de41b4ae37e8e28586d84a342b68')
await expect(askarWallet.createKey({ privateKey, keyType: KeyType.Ed25519 })).resolves.toEqual(expect.any(Key))
await expect(askarWallet.createKey({ privateKey, keyType: KeyType.Ed25519 })).rejects.toThrowError(
WalletKeyExistsError
)
await expect(askarWallet.createKey({ privateKey, keyType: KeyType.Ed25519 })).rejects.toThrow(WalletKeyExistsError)
})

test('Fail to create a P384 keypair', async () => {
await expect(askarWallet.createKey({ seed, keyType: KeyType.P384 })).rejects.toThrowError(WalletError)
await expect(askarWallet.createKey({ seed, keyType: KeyType.P384 })).rejects.toThrow(WalletError)
})

test('Fail to create a P256 keypair in hardware', async () => {
await expect(
askarWallet.createKey({ keyType: KeyType.P256, keyBackend: KeyBackend.SecureElement })
).rejects.toThrow(WalletError)
})

test('Create a signature with a ed25519 keypair', async () => {
Expand Down Expand Up @@ -186,12 +191,12 @@ describe.skip('Currently, all KeyTypes are supported by Askar natively', () => {
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
public async sign(options: SignOptions): Promise<Buffer> {
public async sign(_options: SignOptions): Promise<Buffer> {
return new Buffer('signed')
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
public async verify(options: VerifyOptions): Promise<boolean> {
public async verify(_options: VerifyOptions): Promise<boolean> {
return true
}
}
Expand Down Expand Up @@ -268,7 +273,7 @@ describe('AskarWallet management', () => {
await askarWallet.close()
await expect(
askarWallet.createAndOpen({ ...walletConfig, id: 'AskarWallet Create', key: anotherKey })
).rejects.toThrowError(WalletDuplicateError)
).rejects.toThrow(WalletDuplicateError)
})

test('Open', async () => {
Expand All @@ -282,14 +287,14 @@ describe('AskarWallet management', () => {

// Close and try to re-opening it with a wrong key
await askarWallet.close()
await expect(askarWallet.open({ ...walletConfig, id: 'AskarWallet Open', key: wrongKey })).rejects.toThrowError(
await expect(askarWallet.open({ ...walletConfig, id: 'AskarWallet Open', key: wrongKey })).rejects.toThrow(
WalletInvalidKeyError
)

// Try to open a non existent wallet
await expect(
askarWallet.open({ ...walletConfig, id: 'AskarWallet Open - Non existent', key: initialKey })
).rejects.toThrowError(WalletNotFoundError)
).rejects.toThrow(WalletNotFoundError)
})

test('Rotate key', async () => {
Expand All @@ -313,7 +318,7 @@ describe('AskarWallet management', () => {

await expect(
askarWallet.open({ ...walletConfig, id: 'AskarWallet Key Rotation', key: initialKey })
).rejects.toThrowError(WalletInvalidKeyError)
).rejects.toThrow(WalletInvalidKeyError)

await askarWallet.open({ ...walletConfig, id: 'AskarWallet Key Rotation', key: newKey })

Expand Down
20 changes: 20 additions & 0 deletions packages/core/src/crypto/KeyBackend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export enum KeyBackend {
/**
*
* Generate a key using common software-based implementations.
* Key material will be instantiated in memory.
*
* Supported for almost all, if not all, key types.
*
*/
Software = 'Software',

/**
*
* Generate a key within the secure element of the device.
*
* For now, this is only supported using Aries Askar in iOS or Android for `KeyType.P256`.
*
*/
SecureElement = 'SecureElement',
}
1 change: 1 addition & 0 deletions packages/core/src/crypto/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export { JwsService } from './JwsService'
export { JwsDetachedFormat } from './JwsTypes'
export * from './keyUtils'

export { KeyBackend } from './KeyBackend'
export { KeyType } from './KeyType'
export { Key } from './Key'

Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/wallet/Wallet.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Key, KeyType } from '../crypto'
import type { KeyBackend } from '../crypto/KeyBackend'
import type { Disposable } from '../plugins'
import type {
EncryptedMessage,
Expand Down Expand Up @@ -70,6 +71,7 @@ export interface WalletCreateKeyOptions {
keyType: KeyType
seed?: Buffer
privateKey?: Buffer
keyBackend?: KeyBackend
}

export interface WalletSignOptions {
Expand Down
6 changes: 3 additions & 3 deletions packages/indy-sdk-to-askar-migration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@
"@credo-ts/node": "workspace:*"
},
"devDependencies": {
"@hyperledger/aries-askar-nodejs": "^0.2.1",
"@hyperledger/aries-askar-shared": "^0.2.1",
"@hyperledger/aries-askar-nodejs": "^0.2.3",
"@hyperledger/aries-askar-shared": "^0.2.3",
"rimraf": "^4.4.0",
"typescript": "~5.5.2"
},
"peerDependencies": {
"@hyperledger/aries-askar-shared": "^0.2.1"
"@hyperledger/aries-askar-shared": "^0.2.3"
}
}
58 changes: 25 additions & 33 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 9989ea7

Please sign in to comment.