Skip to content

Commit

Permalink
update: Remove crypto, buffer, base64url and secp256k references. Upd…
Browse files Browse the repository at this point in the history
…ate to latest ion-sdk to make it browser compatible
  • Loading branch information
nklomp committed Nov 29, 2022
1 parent 2a2c039 commit 8075ba7
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 152 deletions.
19 changes: 13 additions & 6 deletions packages/did-provider-ion/__tests__/ion-did-provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,25 @@ describe('@veramo/did-provider-ion', () => {
did: identifier.did,
key: newKey,
kid: 'test-add-key-' + Date.now(),
options: { purposes: [IonPublicKeyPurpose.AssertionMethod, IonPublicKeyPurpose.Authentication], anchor: false },
options: { purposes: [IonPublicKeyPurpose.AssertionMethod, IonPublicKeyPurpose.Authentication], anchor: true },
})
try {
expect(await resultPromise).toMatchObject({})
} catch (error) {
if (error.message.includes("discovery_service.not_found")) {
// MS node is not entirely stable. Sometimes the above error is thrown
return
}
await expect(error.message).toMatch('An operation request already exists in queue for DID')
}
})

it('should add service', async () => {
// This DID is known in ION, hence no anchoring
const identifier: IIdentifier = await agent.didManagerCreate(existingDidConfig(false, 'test-kid2', PRIVATE_DID2_KEY_HEX))
expect(identifier.alias).toEqual('did:ion:EiADHIE9lE5oyd1XAx4xI_WvUaQBr0oYSCUJTGO1czkLKg')
const identifier: IIdentifier = await agent.didManagerCreate(existingDidConfig(false, 'test2-kid2', PRIVATE_DID2_KEY_HEX))
expect(identifier.alias).toEqual('did:ion:EiAxehS9OQs5bL00wmnZj6AupzvO5rB5KIobbi3oRtCmiw')
expect(identifier.did).toEqual(
'did:ion:EiADHIE9lE5oyd1XAx4xI_WvUaQBr0oYSCUJTGO1czkLKg:eyJkZWx0YSI6eyJwYXRjaGVzIjpbeyJhY3Rpb24iOiJyZXBsYWNlIiwiZG9jdW1lbnQiOnsicHVibGljS2V5cyI6W3siaWQiOiJ0ZXN0LWtpZDIiLCJwdWJsaWNLZXlKd2siOnsiY3J2Ijoic2VjcDI1NmsxIiwia3R5IjoiRUMiLCJ4IjoiZFdxTzVyYWRQNXJGdVV6ZnY0T204a1Bnem11MThLVEJ4eEpaRnlJNHhlNCIsInkiOiJYYjl6b1Y5aG9FM2puc2ZXR05iOEZKaWpyNTVZQ0dqYUpsa3FUYnpJZ1ZJIn0sInB1cnBvc2VzIjpbImF1dGhlbnRpY2F0aW9uIiwiYXNzZXJ0aW9uTWV0aG9kIl0sInR5cGUiOiJFY2RzYVNlY3AyNTZrMVZlcmlmaWNhdGlvbktleTIwMTkifV19fV0sInVwZGF0ZUNvbW1pdG1lbnQiOiJFaUJ6cDdZaE45bWhVY1pzRmR4bmYtbHdrUlUtaFZiQnRaV3NWb0pIVjZqa3dBIn0sInN1ZmZpeERhdGEiOnsiZGVsdGFIYXNoIjoiRWlBeXhSSHdvWndTbnAtSTllNVZHTmJMcWNxVi15eGtGaTVZMllEc1B1UmhXUSIsInJlY292ZXJ5Q29tbWl0bWVudCI6IkVpREFRWFNpN0hjakpWQllBS2RPMnpyTTRIZnlibUJCQ1dzbDZQUVBKX2prbEEifX0'
'did:ion:EiAxehS9OQs5bL00wmnZj6AupzvO5rB5KIobbi3oRtCmiw:eyJkZWx0YSI6eyJwYXRjaGVzIjpbeyJhY3Rpb24iOiJyZXBsYWNlIiwiZG9jdW1lbnQiOnsicHVibGljS2V5cyI6W3siaWQiOiJ0ZXN0Mi1raWQyIiwicHVibGljS2V5SndrIjp7ImNydiI6InNlY3AyNTZrMSIsImt0eSI6IkVDIiwieCI6ImRXcU81cmFkUDVyRnVVemZ2NE9tOGtQZ3ptdTE4S1RCeHhKWkZ5STR4ZTQiLCJ5IjoiWGI5em9WOWhvRTNqbnNmV0dOYjhGSmlqcjU1WUNHamFKbGtxVGJ6SWdWSSJ9LCJwdXJwb3NlcyI6WyJhdXRoZW50aWNhdGlvbiIsImFzc2VydGlvbk1ldGhvZCJdLCJ0eXBlIjoiRWNkc2FTZWNwMjU2azFWZXJpZmljYXRpb25LZXkyMDE5In1dfX1dLCJ1cGRhdGVDb21taXRtZW50IjoiRWlCenA3WWhOOW1oVWNac0ZkeG5mLWx3a1JVLWhWYkJ0WldzVm9KSFY2amt3QSJ9LCJzdWZmaXhEYXRhIjp7ImRlbHRhSGFzaCI6IkVpQXota1h2SVdsSjFfRElCVGlUSkpWRWo0R0U2eHQyTTZHcnVvRFIxcTNHU2ciLCJyZWNvdmVyeUNvbW1pdG1lbnQiOiJFaURBUVhTaTdIY2pKVkJZQUtkTzJ6ck00SGZ5Ym1CQkNXc2w2UFFQSl9qa2xBIn19'
)

const service: IService = {
Expand All @@ -97,6 +101,10 @@ describe('@veramo/did-provider-ion', () => {
try {
expect(await resultPromise).toMatchObject({})
} catch (error) {
if (error.message.includes("discovery_service.not_found")) {
// MS node is not entirely stable. Sometimes the above error is thrown
return
}
await expect(error.message).toMatch('An operation request already exists in queue for DID')
}
})
Expand Down Expand Up @@ -159,8 +167,7 @@ describe('@veramo/did-provider-ion', () => {
})

it('should remove identifier', async () => {
const options = existingDidConfig(false, 'remove-test', PRIVATE_DID4_KEY_HEX)
const identifier: IIdentifier = await agent.didManagerCreate({ options })
const identifier: IIdentifier = await agent.didManagerCreate(existingDidConfig(false, 'remove-test', PRIVATE_DID4_KEY_HEX))

expect(identifier).toBeDefined()

Expand Down
7 changes: 3 additions & 4 deletions packages/did-provider-ion/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,17 @@
"extract-api": "yarn veramo dev extract-api"
},
"dependencies": {
"@decentralized-identity/ion-sdk": "^0.5.0",
"@decentralized-identity/ion-sdk": "^0.6.0",
"@ethersproject/random": "^5.7.0",
"@ethersproject/signing-key": "^5.7.0",
"canonicalize": "^1.0.8",
"@sphereon/ion-pow": "^0.2.0",
"@trust/keyto": "^1.0.1",
"@stablelib/ed25519": "^1.0.2",
"secp256k1": "^4.0.1",
"@veramo/core": "^4.1.1",
"@veramo/did-manager": "^4.1.1",
"@veramo/key-manager": "^4.1.1",
"@veramo/kms-local": "^4.1.1",
"base64url": "^3.0.1",
"canonicalize": "^1.0.8",
"debug": "^4.3.3",
"uint8arrays": "^3.0.0"
},
Expand Down
44 changes: 18 additions & 26 deletions packages/did-provider-ion/src/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@ import {
KeyType,
} from './types/ion-provider-types'
import { IonDid, IonDocumentModel, IonPublicKeyModel, IonPublicKeyPurpose, JwkEs256k } from '@decentralized-identity/ion-sdk'
import { computePublicKey } from '@ethersproject/signing-key'
import { IKey, ManagedKeyInfo } from '@veramo/core'
import keyto from '@trust/keyto';
import { randomBytes } from '@ethersproject/random'
import * as u8a from 'uint8arrays'
import { generateKeyPair as generateSigningKeyPair } from '@stablelib/ed25519'
import Debug from 'debug'
import { JsonCanonicalizer } from './json-canonicalizer'
import crypto from 'crypto'
import base64url from 'base64url'
import { MemoryPrivateKeyStore } from '@veramo/key-manager'
import { KeyManagementSystem } from '@veramo/kms-local'
import * as secp256k1 from 'secp256k1'
import canonicalize from 'canonicalize'
import { hash } from '@stablelib/sha256'

const multihashes = require('multihashes')

Expand Down Expand Up @@ -79,16 +77,12 @@ export const getKid = (
delete copy.d;
delete copy.kid;
delete copy.alg;
const digest = crypto
.createHash('sha256')
.update(canonicalize(copy)!, 'utf-8')
.digest();

const digest = hash(u8a.fromString(JsonCanonicalizer.asString(copy), 'utf-8'));
return u8a.toString(digest, 'base64url')
};

/** convert compressed hex encoded private key to jwk */
export const privateKeyJwkFromPrivateKeyHex = (privateKeyHex: string) => {
const privateKeyJwkFromPrivateKeyHex = (privateKeyHex: string) => {
const jwk = {
...keyto.from(privateKeyHex, 'blk').toJwk('private'),
crv: 'secp256k1',
Expand All @@ -101,15 +95,12 @@ export const privateKeyJwkFromPrivateKeyHex = (privateKeyHex: string) => {
};

/** convert compressed hex encoded public key to jwk */
export const publicKeyJwkFromPublicKeyHex = (publicKeyHex: string) => {
const publicKeyJwkFromPublicKeyHex = (publicKeyHex: string) => {
let key = publicKeyHex;
const compressedHexEncodedPublicKeyLength = 66;
if (publicKeyHex.length === compressedHexEncodedPublicKeyLength) {
const keyBin = secp256k1.publicKeyConvert(
Buffer.from(publicKeyHex, 'hex'),
false
);
key = Buffer.from(keyBin).toString('hex');
const publicBytes = u8a.fromString(publicKeyHex, 'base16')
key = computePublicKey(publicBytes, true).substring(2)
}
const jwk = {
...keyto.from(key, 'blk').toJwk('public'),
Expand Down Expand Up @@ -142,12 +133,13 @@ export const computeCommitmentFromIonPublicKey = (ionKey: IonPublicKeyModel): st
export const computeCommitmentFromJwk = (jwk: JwkEs256k): string => {
const data = JsonCanonicalizer.asString(jwk)
debug(`canonicalized JWK: ${data}`)
const singleHash = crypto.createHash('sha256').update(data).digest()
const doubleHash = crypto.createHash('sha256').update(singleHash).digest()
const singleHash = hash(u8a.fromString(data))
const doubleHash = hash(singleHash)

const multiHash = multihashes.encode(Buffer.from(doubleHash), MULTI_HASH_SHA256_LITERAL)
debug(`commitment: ${base64url.encode(multiHash)}`)
return base64url.encode(multiHash)
const multiHash = multihashes.encode(doubleHash, MULTI_HASH_SHA256_LITERAL)
const commitment = u8a.toString(multiHash, 'base64url')
debug(`commitment: ${commitment}`)
return commitment
}

/**
Expand Down Expand Up @@ -308,8 +300,8 @@ export const tempMemoryKey = async (
* @param input The creation keys
* @return The Ion Long form DID
*/
export const ionLongFormDidFromCreation = (input: { recoveryKey: JwkEs256k; updateKey: JwkEs256k; document: IonDocumentModel }): string => {
return IonDid.createLongFormDid(input)
export const ionLongFormDidFromCreation = async (input: { recoveryKey: JwkEs256k; updateKey: JwkEs256k; document: IonDocumentModel }): Promise<string> => {
return await IonDid.createLongFormDid(input)
}

/**
Expand All @@ -318,12 +310,12 @@ export const ionLongFormDidFromCreation = (input: { recoveryKey: JwkEs256k; upda
* @param input The creation keys
* @return The Ion Short form DID
*/
export const ionShortFormDidFromCreation = (input: { recoveryKey: JwkEs256k; updateKey: JwkEs256k; document: IonDocumentModel }): string => {
return ionShortFormDidFromLong(ionLongFormDidFromCreation(input))
export const ionShortFormDidFromCreation = async (input: { recoveryKey: JwkEs256k; updateKey: JwkEs256k; document: IonDocumentModel }): Promise<string> => {
return ionShortFormDidFromLong(await ionLongFormDidFromCreation(input))
}

/**
* Convert an Ion Long form DID into a short form DID. Be awaer that the input really needs to be a long Form DID!
* Convert an Ion Long form DID into a short form DID. Be aware that the input really needs to be a long Form DID!
* @param longFormDid The Ion Long form DID
* @return An Ion Short form DID
*/
Expand Down
4 changes: 2 additions & 2 deletions packages/did-provider-ion/src/ion-did-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,10 @@ export class IonDIDProvider extends AbstractIdentifierProvider {
services,
},
}
const longFormDid = ionLongFormDidFromCreation(createRequest)
const longFormDid = await ionLongFormDidFromCreation(createRequest)
const shortFormDid = ionShortFormDidFromLong(longFormDid)

const request = IonRequest.createCreateRequest(createRequest)
const request = await IonRequest.createCreateRequest(createRequest)
await this.anchorRequest(request, options?.anchor)

const identifier: Omit<IIdentifier, 'provider'> = {
Expand Down
13 changes: 6 additions & 7 deletions packages/did-provider-ion/src/ion-signer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import crypto from 'crypto'
import { IContext } from './types/ion-provider-types'
import * as u8a from 'uint8arrays'
import base64url from 'base64url'
import { hash } from '@stablelib/sha256'

/**
* This class is responsible for signing the JWT when sending in Anchor requests to an ION node. It is using the update or recovery key denoted by 'kid'
Expand Down Expand Up @@ -31,18 +30,18 @@ export class IonSigner {
alg: 'ES256K',
}
}
const encodedHeader = base64url.encode(JSON.stringify(header))
const encodedPayload = base64url.encode(JSON.stringify(payload))
const toBeSigned = encodedHeader + '.' + encodedPayload
const encodedHeader = u8a.toString(u8a.fromString(JSON.stringify(header)), 'base64url')
const encodedPayload = u8a.toString(u8a.fromString(JSON.stringify(payload)), 'base64url')
const toBeSigned = `${encodedHeader}.${encodedPayload}`
const message = u8a.fromString(toBeSigned)
const digest = crypto.createHash('sha256').update(message).digest('hex')
const digest = u8a.toString(hash(message), 'base16')
const sigObj = await this.context.agent.keyManagerSign({
keyRef: this.kid,
algorithm: header.alg,
data: digest,
encoding: 'hex',
})
const encodedSignature = sigObj // The keyManagerSign already performs base64Url encoding
return encodedHeader + '.' + encodedPayload + '.' + encodedSignature
return `${encodedHeader}.${encodedPayload}.${encodedSignature}`
}
}

This file was deleted.

1 change: 0 additions & 1 deletion packages/did-provider-ion/src/types/secp256k1/index.d.ts

This file was deleted.

Loading

0 comments on commit 8075ba7

Please sign in to comment.