Skip to content

Commit

Permalink
did from mnemonic (#57)
Browse files Browse the repository at this point in the history
* remove helper.createEcdsaFromMnemonic function, instead to use keys.fromMnemonic.
  • Loading branch information
zzcwoshizz committed Feb 23, 2023
1 parent 7a4b2e3 commit 579c000
Show file tree
Hide file tree
Showing 16 changed files with 231 additions and 226 deletions.
5 changes: 5 additions & 0 deletions .changeset/odd-bobcats-nail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@zcloak/did': minor
---

remove helper.createEcdsaFromMnemonic function, instead to use keys.fromMnemonic.
90 changes: 1 addition & 89 deletions packages/did/src/did/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
import type { DidResolver } from '@zcloak/did-resolver';
import type { DidDocument, DidUrl } from '@zcloak/did-resolver/types';
import type { KeyringInstance } from '@zcloak/keyring/types';
import type { KeyGen } from './types';

import { base58Encode, decodeMultibase, ethereumEncode } from '@zcloak/crypto';
import { decodeMultibase } from '@zcloak/crypto';
import { defaultResolver } from '@zcloak/did-resolver/defaults';
import { Keyring } from '@zcloak/keyring';

import { IDidDetails } from '../types';
import { Did } from '.';
Expand Down Expand Up @@ -130,89 +128,3 @@ export function create(details: IDidDetails, keyring?: KeyringInstance): Did {

return did;
}

/**
* pass `mnemonic`, and create [[Did]] from a [[IDidDetails]] object
* @returns instance of [[Did]]
* @example
* <BR>
* ```typescript
* import { helpers, Did } from '@zcloak/did'
* import { Keyring } from '@zcloak/keyring'
* import type { IDidDetails } from '@zcloak/did/types';
*
* const mnemonic = 'health correct setup usage father decorate curious copper sorry recycle skin equal';
* const keyring: Keyring = new Keyring();
* const did: Did = helpers.createEcdsaFromMnemonic(mnemonic, keyring);
* ```
*/
export function createEcdsaFromMnemonic(
mnemonic: string,
keyring: KeyringInstance = new Keyring()
): Did {
const {
identifier,
keys: [key0, key1]
} = keyFromMnemonic(keyring, mnemonic, 'ecdsa');

const didUri: DidUrl = `did:zk:${ethereumEncode(identifier)}`;
const document: DidDocument = {
'@context': ['https://www.w3.org/ns/did/v1'],
id: didUri,
controller: [didUri],
verificationMethod: [
{
id: `${didUri}#key-0`,
controller: [didUri],
type: 'EcdsaSecp256k1VerificationKey2019',
publicKeyMultibase: base58Encode(key0)
},
{
id: `${didUri}#key-1`,
controller: [didUri],
type: 'X25519KeyAgreementKey2019',
publicKeyMultibase: base58Encode(key1)
}
],
authentication: [`${didUri}#key-0`],
assertionMethod: [`${didUri}#key-0`],
keyAgreement: [`${didUri}#key-1`],
capabilityInvocation: [`${didUri}#key-0`],
capabilityDelegation: [`${didUri}#key-0`],
service: []
};

const did = create(parseDidDocument(document), keyring);

return did;
}

export function keyFromMnemonic(keyring: KeyringInstance, mnemonic: string, type: 'ecdsa'): KeyGen;
export function keyFromMnemonic(
keyring: KeyringInstance,
mnemonic: string,
type: 'ed25519'
): KeyGen;

export function keyFromMnemonic(
keyring: KeyringInstance,
mnemonic: string,
type: 'ecdsa' | 'ed25519'
): KeyGen {
const identifier = keyring.addFromMnemonic(
mnemonic,
type === 'ecdsa' ? "/m/44'/60'/0'/0/0" : undefined,
type
);
const pair1 = keyring.addFromMnemonic(
mnemonic,
type === 'ecdsa' ? "/m/44'/60'/0'/0/0/0" : '//0',
type
);
const pair2 = keyring.addFromMnemonic(mnemonic, '//1', 'x25519');

return {
identifier: identifier.publicKey,
keys: [pair1.publicKey, pair2.publicKey]
};
}
15 changes: 6 additions & 9 deletions packages/did/src/did/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@ import {
import { Keyring } from '@zcloak/keyring';

import { hashDidDocument, signedDidDocumentMessage } from '../hasher';
import { createEcdsaFromMnemonic } from './helpers';
import { fromMnemonic } from '../keys';

describe('Did', (): void => {
let keyring: Keyring;

beforeAll(async () => {
await initCrypto();
keyring = new Keyring();
});

describe('create', (): void => {
let keyring: Keyring;

const controllerKey = new Uint8Array([
2, 68, 184, 160, 24, 144, 34, 70, 58, 237, 53, 113, 14, 220, 94, 35, 175, 119, 18, 97, 44,
234, 243, 237, 184, 253, 96, 196, 125, 196, 127, 56, 220
Expand All @@ -37,14 +38,10 @@ describe('Did', (): void => {
192, 33, 128, 145, 213, 119, 16, 125, 214, 227, 70, 3
]);

beforeEach((): void => {
keyring = new Keyring();
});

it('create ecdsa did from mnemonic', (): void => {
const mnemonic =
'health correct setup usage father decorate curious copper sorry recycle skin equal';
const did = createEcdsaFromMnemonic(mnemonic, keyring);
const did = fromMnemonic(keyring, mnemonic);

expect(did.get([...(did.authentication ?? [])][0]).publicKey).toEqual(key0);
expect(did.get([...(did.keyAgreement ?? [])][0]).publicKey).toEqual(key1);
Expand All @@ -56,7 +53,7 @@ describe('Did', (): void => {
it('create ecdsa did from mnemonic and get document', (): void => {
const mnemonic =
'health correct setup usage father decorate curious copper sorry recycle skin equal';
const did = createEcdsaFromMnemonic(mnemonic);
const did = fromMnemonic(keyring, mnemonic);

const document = did.getDocument();

Expand Down
12 changes: 0 additions & 12 deletions packages/did/src/did/types.ts

This file was deleted.

17 changes: 8 additions & 9 deletions packages/did/src/keys/backup.spec.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
// Copyright 2021-2023 zcloak authors & contributors
// SPDX-License-Identifier: Apache-2.0

import { testKeyring } from 'test-support';

import { initCrypto, mnemonicGenerate } from '@zcloak/crypto';
import { Keyring } from '@zcloak/keyring';

import { createEcdsaFromMnemonic } from '../did/helpers';
import { backup, getEcdsaIdentifierPair } from './backup';
import { DEFAULT_DID_KEYS_JSON_VERSION } from './defaults';
import { fromMnemonic } from './from';

describe('Backup did', (): void => {
const keyring = new Keyring();

beforeAll(async () => {
await initCrypto();
});

it('get ecdsa identifier pair', () => {
const mnemonic = mnemonicGenerate(12);
const did = createEcdsaFromMnemonic(mnemonic, keyring);
const did = fromMnemonic(testKeyring, mnemonic);

expect(getEcdsaIdentifierPair(keyring, did)?.publicKey).toEqual(
keyring.createFromMnemonic(mnemonic, undefined, 'ecdsa').publicKey
expect(getEcdsaIdentifierPair(testKeyring, did)?.publicKey).toEqual(
testKeyring.createFromMnemonic(mnemonic, undefined, 'ecdsa').publicKey
);
});

it('backup did', () => {
const mnemonic = mnemonicGenerate(12);
const did = createEcdsaFromMnemonic(mnemonic, keyring);
const did = fromMnemonic(testKeyring, mnemonic);

expect(backup(keyring, did, '1234')).toMatchObject({
expect(backup(testKeyring, did, '1234')).toMatchObject({
didUrl: did.id,
version: DEFAULT_DID_KEYS_JSON_VERSION,
authentication: Array.from(did.authentication ?? []),
Expand Down
37 changes: 37 additions & 0 deletions packages/did/src/keys/from.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2021-2023 zcloak authors & contributors
// SPDX-License-Identifier: Apache-2.0

import { DOCUMENTS, testKeyring } from 'test-support';

import { ethereumEncode, initCrypto } from '@zcloak/crypto';

import { fromMnemonic } from './from';

describe('create did use keys', (): void => {
beforeAll(async () => {
await initCrypto();
});

it('fromMnemonic with index 0 and type ecdsa', () => {
const mnemonic =
'health correct setup usage father decorate curious copper sorry recycle skin equal';
const did = fromMnemonic(testKeyring, mnemonic, 'ecdsa', 0);

expect(did.getDocument()).toMatchObject(DOCUMENTS.alice);
});

it.each(Array.from({ length: 10 }).map((_, index) => index))(
'fromMnemonic with index: %p',
(index) => {
const mnemonic =
'health correct setup usage father decorate curious copper sorry recycle skin equal';
const did = fromMnemonic(testKeyring, mnemonic, 'ecdsa', index);

expect(did.identifier).toBe(
ethereumEncode(
testKeyring.createFromMnemonic(mnemonic, `/m/44'/60'/0'/0/${index}`, 'ecdsa').publicKey
)
);
}
);
});
85 changes: 85 additions & 0 deletions packages/did/src/keys/from.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2021-2023 zcloak authors & contributors
// SPDX-License-Identifier: Apache-2.0

import type { DidDocument, DidUrl } from '@zcloak/did-resolver/types';
import type { KeyringInstance } from '@zcloak/keyring/types';
import type { Did } from '../did';

import { base58Encode, ethereumEncode } from '@zcloak/crypto';

import { fromDidDocument } from '../did/helpers';

/**
* @name fromMnemonic
* @summary create Did from mnemonic.
* @description
* create Did like `did:zk:` from `mnemonic`. generate signing key by `signingKeyType`. Returns [[Did]] instance.
*
* @param index
* controller path is `/m/44'/60'/0'/0/index`
*
* ecdsa path is `/m/44'/60'/0'/0/index/0`
*
* ed25519 path is `//index`
*
* x25519 path is `//index * 2`
* @example
* ```javascript
* import { keys } from '@zcloak/did';
*
* const mnemonic = '...';
*
* const did = keys.fromMnemonic(keyring, mnemonic, 'ecdsa')
* ```
*/
export function fromMnemonic(
keyring: KeyringInstance,
mnemonic: string,
signingKeyType: 'ecdsa' | 'ed25519' = 'ecdsa',
index = 0
): Did {
const controllerPath = `/m/44'/60'/0'/0/${index}`;
const ecdsaPath = `${controllerPath}/0`;
const edPath = `//${index * 2}`;
const xPath = `//${index * 2 + 1}`;

const controller = keyring.addFromMnemonic(mnemonic, controllerPath, 'ecdsa');
const singingKey = keyring.addFromMnemonic(
mnemonic,
signingKeyType === 'ecdsa' ? ecdsaPath : edPath,
signingKeyType
);
const encryptionKey = keyring.addFromMnemonic(mnemonic, xPath, 'x25519');

const didUri: DidUrl = `did:zk:${ethereumEncode(controller.publicKey)}`;
const document: DidDocument = {
'@context': ['https://www.w3.org/ns/did/v1'],
id: didUri,
controller: [didUri],
verificationMethod: [
{
id: `${didUri}#key-0`,
controller: [didUri],
type:
signingKeyType === 'ecdsa'
? 'EcdsaSecp256k1VerificationKey2019'
: 'Ed25519VerificationKey2020',
publicKeyMultibase: base58Encode(singingKey.publicKey)
},
{
id: `${didUri}#key-1`,
controller: [didUri],
type: 'X25519KeyAgreementKey2019',
publicKeyMultibase: base58Encode(encryptionKey.publicKey)
}
],
authentication: [`${didUri}#key-0`],
assertionMethod: [`${didUri}#key-0`],
keyAgreement: [`${didUri}#key-1`],
capabilityInvocation: [`${didUri}#key-0`],
capabilityDelegation: [`${didUri}#key-0`],
service: []
};

return fromDidDocument(document, keyring);
}
1 change: 1 addition & 0 deletions packages/did/src/keys/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
// SPDX-License-Identifier: Apache-2.0

export * from './backup';
export * from './from';
export * from './restore';
14 changes: 6 additions & 8 deletions packages/did/src/keys/restore.spec.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
// Copyright 2021-2023 zcloak authors & contributors
// SPDX-License-Identifier: Apache-2.0

import { testKeyring } from 'test-support';

import { initCrypto, mnemonicGenerate } from '@zcloak/crypto';
import { Keyring } from '@zcloak/keyring';

import { createEcdsaFromMnemonic } from '../did/helpers';
import { backup } from './backup';
import { fromMnemonic } from './from';
import { restore } from './restore';

describe('Restore did', (): void => {
const keyring = new Keyring();

beforeAll(async () => {
await initCrypto();
});

it('backup did and restore', () => {
const mnemonic = mnemonicGenerate(12);
const did = createEcdsaFromMnemonic(mnemonic, keyring);

const json = backup(keyring, did, '1234');
const did = fromMnemonic(testKeyring, mnemonic);
const json = backup(testKeyring, did, '1234');

expect(restore(keyring, json, '1234')).toMatchObject(did);
expect(restore(testKeyring, json, '1234')).toMatchObject(did);
});
});
Loading

0 comments on commit 579c000

Please sign in to comment.