diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c26cc707..deb033086 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.36.1 + +- Add `fromUri` to keyring along with hard & soft key derivation. + # 0.35.1 - Remove NodeJs-only `syncify` function, not exported by the package (with binary dependency for Node) diff --git a/lerna.json b/lerna.json index adfbc2111..dce831ff8 100644 --- a/lerna.json +++ b/lerna.json @@ -9,5 +9,5 @@ "packages": [ "packages/*" ], - "version": "0.35.10" + "version": "0.36.0" } diff --git a/packages/chainspec/package.json b/packages/chainspec/package.json index 92bcad269..a050b4f45 100644 --- a/packages/chainspec/package.json +++ b/packages/chainspec/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/chainspec", - "version": "0.35.10", + "version": "0.36.0", "description": "Contains chain specifications for known chains", "main": "index.js", "keywords": [ @@ -29,6 +29,6 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/chainspec#readme", "dependencies": { "@babel/runtime": "^7.3.4", - "@polkadot/util": "^0.35.10" + "@polkadot/util": "^0.36.0" } } diff --git a/packages/db/package.json b/packages/db/package.json index a7b113c30..5b7eb33fa 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/db", - "version": "0.35.10", + "version": "0.36.0", "description": "Implementation of a basic sync in-memory and on-disk databases with overlays", "main": "index.js", "keywords": [ @@ -29,8 +29,8 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/db#readme", "dependencies": { "@babel/runtime": "^7.3.4", - "@polkadot/trie-hash": "^0.35.10", - "@polkadot/util": "^0.35.10", + "@polkadot/trie-hash": "^0.36.0", + "@polkadot/util": "^0.36.0", "@types/mkdirp": "^0.5.2", "@types/rimraf": "^2.0.2", "@types/snappy": "^6.0.0", diff --git a/packages/keyring/package.json b/packages/keyring/package.json index e889160b6..345a1d097 100644 --- a/packages/keyring/package.json +++ b/packages/keyring/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/keyring", - "version": "0.35.10", + "version": "0.36.0", "description": "Keyring management", "main": "index.js", "engines": { @@ -31,8 +31,8 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/keyring#readme", "dependencies": { "@babel/runtime": "^7.3.4", - "@polkadot/util": "^0.35.10", - "@polkadot/util-crypto": "^0.35.10", + "@polkadot/util": "^0.36.0", + "@polkadot/util-crypto": "^0.36.0", "@types/bs58": "^4.0.0", "bs58": "^4.0.1" } diff --git a/packages/keyring/src/index.ts b/packages/keyring/src/index.ts index ce017cea9..3f7a2db70 100644 --- a/packages/keyring/src/index.ts +++ b/packages/keyring/src/index.ts @@ -2,10 +2,11 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { KeyringInstance, KeyringPair, KeyringPair$Json, KeyringPair$Meta, KeyringOptions, KeyringPairType } from './types'; +import { KeypairType } from '@polkadot/util-crypto/types'; +import { KeyringInstance, KeyringPair, KeyringPair$Json, KeyringPair$Meta, KeyringOptions } from './types'; -import { assert, hexToU8a, isNumber } from '@polkadot/util/index'; -import { mnemonicToSeed , naclKeypairFromSeed as naclFromSeed, schnorrkelKeypairFromSeed as schnorrkelFromSeed } from '@polkadot/util-crypto/index'; +import { assert, hexToU8a, isNumber, isHex, stringToU8a } from '@polkadot/util/index'; +import { keyExtract, mnemonicToSeed , naclKeypairFromSeed as naclFromSeed, schnorrkelKeypairFromSeed as schnorrkelFromSeed, mnemonicToMiniSecret, keyFromPath } from '@polkadot/util-crypto/index'; import { decodeAddress, encodeAddress, setAddressPrefix } from './address'; import createPair from './pair'; @@ -29,13 +30,15 @@ import Pairs from './pairs'; */ export default class Keyring implements KeyringInstance { private _pairs: Pairs; - private _type: KeyringPairType; + private _type: KeypairType; + + constructor (options: KeyringOptions = {}) { + options.type = options.type || 'ed25519'; - constructor (options: KeyringOptions = { type: 'ed25519' }) { assert(options && ['ed25519', 'sr25519'].includes(options.type || 'undefined'), `Expected a keyring type of either 'ed25519' or 'sr25519', found '${options.type}`); this._pairs = new Pairs(); - this._type = options.type as KeyringPairType; + this._type = options.type; setAddressPrefix(isNumber(options.addressPrefix) ? options.addressPrefix : 42); } @@ -44,6 +47,20 @@ export default class Keyring implements KeyringInstance { encodeAddress = encodeAddress; setAddressPrefix = setAddressPrefix; + /** + * @description True for Ed25519 keyring + */ + get isEd25519 (): boolean { + return this.type === 'ed25519'; + } + + /** + * @description True for Ed25519 keyring + */ + get isSr25519 (): boolean { + return this.type === 'sr25519'; + } + /** * @description retrieve the pairs (alias for getPairs) */ @@ -61,7 +78,7 @@ export default class Keyring implements KeyringInstance { /** * @description Returns the type of the keyring, either ed25519 of sr25519 */ - get type (): KeyringPairType { + get type (): KeypairType { return this._type; } @@ -81,7 +98,7 @@ export default class Keyring implements KeyringInstance { * of an account backup), and then generates a keyring pair from them that it passes to * `addPair` to stores in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value. */ - addFromAddress (address: string | Uint8Array, meta: KeyringPair$Meta = {}, encoded: Uint8Array | null = null, type: KeyringPairType = this.type): KeyringPair { + addFromAddress (address: string | Uint8Array, meta: KeyringPair$Meta = {}, encoded: Uint8Array | null = null, type: KeypairType = this.type): KeyringPair { return this.addPair(createPair(type, { publicKey: this.decodeAddress(address) }, meta, encoded)); } @@ -107,7 +124,7 @@ export default class Keyring implements KeyringInstance { * of an account backup), and then generates a keyring pair from it that it passes to * `addPair` to stores in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value. */ - addFromMnemonic (mnemonic: string, meta: KeyringPair$Meta = {}, type: KeyringPairType = this.type): KeyringPair { + addFromMnemonic (mnemonic: string, meta: KeyringPair$Meta = {}, type: KeypairType = this.type): KeyringPair { return this.addFromSeed(mnemonicToSeed(mnemonic), meta, type); } @@ -118,14 +135,39 @@ export default class Keyring implements KeyringInstance { * Allows user to provide the account seed as an argument, and then generates a keyring pair from it that it passes to * `addPair` to store in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value. */ - addFromSeed (seed: Uint8Array, meta: KeyringPair$Meta = {}, type: KeyringPairType = this.type): KeyringPair { - const keypair = type === 'sr25519' + addFromSeed (seed: Uint8Array, meta: KeyringPair$Meta = {}, type: KeypairType = this.type): KeyringPair { + const keypair = this.isSr25519 ? schnorrkelFromSeed(seed) : naclFromSeed(seed); return this.addPair(createPair(type, { ...keypair, seed }, meta, null)); } + /** + * @name addFromUri + * @summary Creates an account via an suri + * @description Extracts the phrase, path and password from a SURI format for specifying secret keys `//////` (the `///password` may be omitted, and `/` and `//` maybe repeated and mixed). The secret can be a hex string, mnemonic phrase or a string (to be padded) + */ + addFromUri (suri: string, meta: KeyringPair$Meta = {}, type: KeypairType = this.type): KeyringPair { + const { password, phrase, path } = keyExtract(suri); + let seed; + + if (isHex(phrase, 256)) { + seed = hexToU8a(phrase); + } else { + const str = phrase as string; + const parts = str.split(' '); + + if ([12, 15, 18, 21, 24].includes(parts.length)) { + seed = mnemonicToMiniSecret(phrase, password); + } else { + seed = stringToU8a(str.padEnd(32)); + } + } + + return this.addFromSeed(keyFromPath(seed, path, type), meta, type); + } + /** * @name getPair * @summary Retrieves an account keyring pair from the Keyring Pair Dictionary, given an account address diff --git a/packages/keyring/src/pair/index.ts b/packages/keyring/src/pair/index.ts index 552c8ba04..ad136838b 100644 --- a/packages/keyring/src/pair/index.ts +++ b/packages/keyring/src/pair/index.ts @@ -2,8 +2,8 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { KeypairType } from '@polkadot/util-crypto/types'; -import { KeyringPair, KeyringPair$Json, KeyringPair$Meta, KeyringPairType } from '../types'; +import { Keypair, KeypairType } from '@polkadot/util-crypto/types'; +import { KeyringPair, KeyringPair$Json, KeyringPair$Meta } from '../types'; import { PairInfo } from './types'; import { naclKeypairFromSeed as naclFromSeed, naclSign, naclVerify, schnorrkelKeypairFromSeed as schnorrkelFromSeed, schnorrkelSign, schnorrkelVerify } from '@polkadot/util-crypto/index'; @@ -13,18 +13,21 @@ import decode from './decode'; import encode from './encode'; import toJson from './toJson'; -const fromSeed = (type: KeyringPairType, seed: Uint8Array) => - type === 'sr25519' +const isSr25519 = (type: KeypairType): boolean => + type === 'sr25519'; + +const fromSeed = (type: KeypairType, seed: Uint8Array) => + isSr25519(type) ? schnorrkelFromSeed(seed) : naclFromSeed(seed); -const sign = (type: KeyringPairType, message: Uint8Array, pair: Partial) => - type === 'sr25519' +const sign = (type: KeypairType, message: Uint8Array, pair: Partial) => + isSr25519(type) ? schnorrkelSign(message, pair) : naclSign(message, pair); -const verify = (type: KeyringPairType, message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array) => - type === 'sr25519' +const verify = (type: KeypairType, message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array) => + isSr25519(type) ? schnorrkelVerify(message, signature, publicKey) : naclVerify(message, signature, publicKey); @@ -59,7 +62,7 @@ const verify = (type: KeyringPairType, message: Uint8Array, signature: Uint8Arra * an `encoded` property that is assigned with the encoded public key in hex format, and an `encoding` * property that indicates whether the public key value of the `encoded` property is encoded or not. */ -export default function createPair (type: KeyringPairType, { publicKey, seed }: PairInfo, meta: KeyringPair$Meta = {}, encoded: Uint8Array | null = null): KeyringPair { +export default function createPair (type: KeypairType, { publicKey, seed }: PairInfo, meta: KeyringPair$Meta = {}, encoded: Uint8Array | null = null): KeyringPair { let secretKey: Uint8Array | undefined; if (seed) { @@ -98,7 +101,7 @@ export default function createPair (type: KeyringPairType, { publicKey, seed }: sign(type, message, { publicKey, secretKey }), toJson: (passphrase?: string): KeyringPair$Json => toJson(type, { meta, publicKey }, encode({ publicKey, seed }, passphrase), !!passphrase), - toType: (type: KeyringPairType): KeyringPair => + toType: (type: KeypairType): KeyringPair => createPair(type, { publicKey, seed }, meta, null), verify: (message: Uint8Array, signature: Uint8Array): boolean => verify(type, message, signature, publicKey) diff --git a/packages/keyring/src/pair/nobody.ts b/packages/keyring/src/pair/nobody.ts index 03734b3eb..9e9390cd7 100644 --- a/packages/keyring/src/pair/nobody.ts +++ b/packages/keyring/src/pair/nobody.ts @@ -9,6 +9,7 @@ import addressEncode from '../address/encode'; const publicKey = new Uint8Array(32); const address = addressEncode(publicKey); const meta = { + isTesting: true, name: 'nobody' }; const json: KeyringPair$Json = { diff --git a/packages/keyring/src/pair/toJson.ts b/packages/keyring/src/pair/toJson.ts index 404d83d94..b32022f3a 100644 --- a/packages/keyring/src/pair/toJson.ts +++ b/packages/keyring/src/pair/toJson.ts @@ -2,7 +2,8 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { KeyringPair$Json, KeyringPair$Meta, KeyringPairType } from '../types'; +import { KeypairType } from '@polkadot/util-crypto/types'; +import { KeyringPair$Json, KeyringPair$Meta } from '../types'; import { u8aToHex } from '@polkadot/util/index'; @@ -12,7 +13,7 @@ type PairStateJson = KeyringPair$Meta & { publicKey: Uint8Array }; -export default function toJson (type: KeyringPairType, { publicKey, meta }: PairStateJson, encoded: Uint8Array, isEncrypted: boolean): KeyringPair$Json { +export default function toJson (type: KeypairType, { publicKey, meta }: PairStateJson, encoded: Uint8Array, isEncrypted: boolean): KeyringPair$Json { return { address: encodeAddress(publicKey), encoded: u8aToHex(encoded), diff --git a/packages/keyring/src/suri.spec.ts b/packages/keyring/src/suri.spec.ts new file mode 100644 index 000000000..7bdeb890e --- /dev/null +++ b/packages/keyring/src/suri.spec.ts @@ -0,0 +1,75 @@ +// Copyright 2017-2019 @polkadot/keyring authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +// From https://github.com/paritytech/substrate/wiki/Secret-URI-Test-Vectors + +import { u8aToHex } from '@polkadot/util/index'; +import { cryptoWaitReady } from '@polkadot/util-crypto/index'; + +import Keyring from './index'; + +const PHRASE = 'bottom drive obey lake curtain smoke basket hold race lonely fit walk'; + +const TESTS = [ + { + pk: '0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a', + ss: '5DfhGyQdFobKM8NsWvEeAKk5EQQgYe9AydgJ7rMB6E1EqAS7', + uri: PHRASE + }, + { + pk: '0xb69355deefa7a8f33e9297f5af22e680f03597a99d4f4b1c44be47e7a2275802', + ss: '5GC6LfpV352HtJPySfAecb5JdePtf4R9Vq49NUU8RhzgBq1z', + uri: `${PHRASE}///password` + }, + { + pk: '0x40b9675df90efa6069ff623b0fdfcf706cd47ca7452a5056c7ad58194d23440a', + ss: '5DXZzrDxHbkQov4QBAY4TjpwnHCMrKXkomTnKSw8UArBESDT', + uri: `${PHRASE}/foo` + }, + { + pk: '0x545ecfd16d2ccbece3c3d8e284ba21b624d53a010d19673285a02aca92a62724', + ss: '5DyL3XpLxWKJgeUYkFFhepm9DWFMHjvW6JKyVst6F6bX1DQw', + uri: `${PHRASE}//foo` + }, + { + pk: '0xc6755aae1c6a172dc06a8bcf46d119a56ec04b22d7c673255dfc6fb5d7afd250', + ss: '5GYvCYSJxHTNRMqtkLX5AGpTYjSiaHeCdVgBQJWp6Jb1eWZR', + uri: `${PHRASE}//foo/bar` + }, + { + pk: '0xbed7420abfb5398eaa5c1e5ce484bf200c735ee0606ed97048dae9a6e7b1aa59', + ss: '5GNvuAdKoC5mHzmSSctsZAC4WkrhZC5W7FBB4G3N5XMCBhMD', + uri: `${PHRASE}/foo//bar` + }, + { + pk: '0xd0c0cb1e54a54222058552d7bf94a8abaaafd778adae57a30a9bba5afb01f17a', + ss: '5GnR66wpdL4hnArhDRyyBCqchgVYXVMQDDSZQWegfSSnAEFh', + uri: `${PHRASE}//foo/bar//42/69` + }, + { + pk: '0x12dccbb4d851a7bc36bb4f5f6f84a1caaf04c542509b1e3b84f1f47445c1bf08', + ss: '5CVSJt82L8jYodrwYKCoP6LtC6V2VYPHYMHtHzjhdNr1KDdu', + uri: `${PHRASE}//foo/bar//42/69///password` + } +]; + +// TODO Enable once we have proper schnorrkel support +describe.skip('keyring.addFromUri', () => { + let keyring: Keyring; + + beforeEach(async () => { + keyring = new Keyring({ type: 'sr25519' }); + + await cryptoWaitReady(); + }); + + TESTS.forEach(({ pk, ss, uri }) => { + it(`creates ${uri}`, () => { + const pair = keyring.addFromUri(uri); + + expect(u8aToHex(pair.publicKey())).toEqual(pk); + expect(pair.address()).toEqual(ss); + }); + }); +}); diff --git a/packages/keyring/src/testing.ts b/packages/keyring/src/testing.ts index 3a82b5277..68df31064 100644 --- a/packages/keyring/src/testing.ts +++ b/packages/keyring/src/testing.ts @@ -4,33 +4,10 @@ import { KeyringInstance, KeyringOptions } from './types'; -import { stringToU8a } from '@polkadot/util/index'; - import Keyring from './index'; -function padSeed (seed: string): Uint8Array { - return stringToU8a(seed.padEnd(32)); -} - -const SEEDS: { [index: string ]: Uint8Array } = { - alice: - padSeed('Alice'), - bob: - padSeed('Bob'), - charlie: - padSeed('Charlie'), - dave: - padSeed('Dave'), - eve: - padSeed('Eve'), - ferdie: - padSeed('Ferdie') - // NOTE These were originally part of tests, don't remove completely (yet), first check impact - // one: - // padSeed('12345678901234567890123456789012'), - // two: - // hexToU8a('0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') -}; +const DEV_PHRASE = 'bottom drive obey lake curtain smoke basket hold race lonely fit walk'; +const SEEDS = ['Alice', 'Bob', 'Charlie', 'Dave', 'Eve', 'Ferdie']; /** * @name testKeyring @@ -38,21 +15,22 @@ const SEEDS: { [index: string ]: Uint8Array } = { * @description The test accounts (i.e. alice, bob, dave, eve, ferdie) * are available on the dev chain and each test account is initialised with DOT funds. */ -export default function testKeyring (options?: KeyringOptions): KeyringInstance { +export default function testKeyring (options?: KeyringOptions, isHdKd: boolean = false): KeyringInstance { const keyring = new Keyring(options); - Object - .keys(SEEDS) - .forEach((name) => { - const pair = keyring.addFromSeed(SEEDS[name], { - isTesting: true, - name - }); - - pair.lock = () => { - // we don't have lock/unlock functionality here - }; + SEEDS.forEach((entry) => { + const phrase = isHdKd + ? `${DEV_PHRASE}//${entry}` + : entry; + const pair = keyring.addFromUri(phrase, { + isTesting: true, + name: entry.toLowerCase() }); + pair.lock = () => { + // we don't have lock/unlock functionality here + }; + }); + return keyring; } diff --git a/packages/keyring/src/testingPairs.spec.ts b/packages/keyring/src/testingPairs.spec.ts index 4fc66e4a2..353f3554f 100644 --- a/packages/keyring/src/testingPairs.spec.ts +++ b/packages/keyring/src/testingPairs.spec.ts @@ -2,10 +2,26 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. +import testingPairs from './testingPairs'; + describe('testing', () => { it('creates without failing', () => { expect( - require('./testingPairs') - ).toBeDefined(); + Object.keys(testingPairs()) + ).toHaveLength(1 + 6); + }); + + describe('ed25519', () => { + it('has the correct address for Alice (non-HDKD)', () => { + expect( + testingPairs({ type: 'ed25519' }, false).alice.address() + ).toEqual('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ'); + }); + + it('has the correct address for Alice (HDKD)', () => { + expect( + testingPairs({ type: 'ed25519' }, true).alice.address() + ).toEqual('5FA9nQDVg267DEd8m1ZypXLBnvN7SFxYwV7ndqSYGiN9TmTd'); + }); }); }); diff --git a/packages/keyring/src/testingPairs.ts b/packages/keyring/src/testingPairs.ts index 4a23afa87..1d7dbf9d0 100644 --- a/packages/keyring/src/testingPairs.ts +++ b/packages/keyring/src/testingPairs.ts @@ -11,16 +11,15 @@ type TestKeyringMap = { [index: string]: KeyringPair }; -export default function testKeyringPairs (options?: KeyringOptions): TestKeyringMap { - const keyring = createKeyring(options); +export default function testKeyringPairs (options?: KeyringOptions, isHdKd: boolean = false): TestKeyringMap { + const keyring = createKeyring(options, isHdKd); const pairs = keyring.getPairs(); return pairs.reduce((result, pair) => { const { name } = pair.getMeta(); - // @ts-ignore dunno what the complaint here is about... result[name as string] = pair; return result; - }, { 'nobody': nobody() }); + }, { 'nobody': nobody() } as TestKeyringMap); } diff --git a/packages/keyring/src/types.ts b/packages/keyring/src/types.ts index 30cd15e1c..921ecae81 100644 --- a/packages/keyring/src/types.ts +++ b/packages/keyring/src/types.ts @@ -2,13 +2,12 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. +import { KeypairType } from '@polkadot/util-crypto/types'; import { Prefix } from './address/types'; -export type KeyringPairType = 'ed25519' | 'sr25519'; - export type KeyringOptions = { addressPrefix?: Prefix, - type?: KeyringPairType + type?: KeypairType }; export type KeyringPair$Meta = { @@ -18,7 +17,7 @@ export type KeyringPair$Meta = { export type KeyringPair$JsonVersion = '0' | '1'; export type KeyringPair$JsonEncoding = { - content: ['pkcs8', KeyringPairType], + content: ['pkcs8', KeypairType], type: 'xsalsa20-poly1305' | 'none', version: KeyringPair$JsonVersion }; @@ -31,7 +30,7 @@ export type KeyringPair$Json = { }; export interface KeyringPair { - readonly type: KeyringPairType; + readonly type: KeypairType; address: () => string; decodePkcs8: (passphrase?: string, encoded?: Uint8Array) => void; @@ -43,7 +42,7 @@ export interface KeyringPair { setMeta: (meta: KeyringPair$Meta) => void; sign (message: Uint8Array): Uint8Array; toJson (passphrase?: string): KeyringPair$Json; - toType (type: KeyringPairType): KeyringPair; + toType (type: KeypairType): KeyringPair; verify (message: Uint8Array, signature: Uint8Array): boolean; } @@ -55,19 +54,22 @@ export interface KeyringPairs { } export interface KeyringInstance { + readonly isEd25519: boolean; + readonly isSr25519: boolean; readonly pairs: Array; readonly publicKeys: Array; - readonly type: KeyringPairType; + readonly type: KeypairType; decodeAddress (encoded: string | Uint8Array): Uint8Array; encodeAddress (key: Uint8Array | string): string; setAddressPrefix (prefix: Prefix): void; addPair (pair: KeyringPair): KeyringPair; - addFromAddress (address: string | Uint8Array, meta?: KeyringPair$Meta, encoded?: Uint8Array | null, type?: KeyringPairType): KeyringPair; - addFromMnemonic (mnemonic: string, meta?: KeyringPair$Meta, type?: KeyringPairType): KeyringPair; - addFromSeed (seed: Uint8Array, meta?: KeyringPair$Meta, type?: KeyringPairType): KeyringPair; + addFromAddress (address: string | Uint8Array, meta?: KeyringPair$Meta, encoded?: Uint8Array | null, type?: KeypairType): KeyringPair; addFromJson (pair: KeyringPair$Json): KeyringPair; + addFromMnemonic (mnemonic: string, meta?: KeyringPair$Meta, type?: KeypairType): KeyringPair; + addFromSeed (seed: Uint8Array, meta?: KeyringPair$Meta, type?: KeypairType): KeyringPair; + addFromUri (suri: string, meta?: KeyringPair$Meta, type?: KeypairType): KeyringPair; getPair (address: string | Uint8Array): KeyringPair; getPairs (): Array; getPublicKeys (): Array; diff --git a/packages/trie-codec/package.json b/packages/trie-codec/package.json index 69dc2356d..dc9d7fffe 100644 --- a/packages/trie-codec/package.json +++ b/packages/trie-codec/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/trie-codec", - "version": "0.35.10", + "version": "0.36.0", "description": "This is an implementation of the codec for Substrate Trie", "main": "index.js", "keywords": [ @@ -29,6 +29,6 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/trie-codec#readme", "dependencies": { "@babel/runtime": "^7.3.4", - "@polkadot/util": "^0.35.10" + "@polkadot/util": "^0.36.0" } } diff --git a/packages/trie-db/package.json b/packages/trie-db/package.json index ef0237357..ba4a0cfae 100644 --- a/packages/trie-db/package.json +++ b/packages/trie-db/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/trie-db", - "version": "0.35.10", + "version": "0.36.0", "description": "This is an implementation of the modified merkle patricia tree as specified in Ethereum's yellow paper, adapted for Polkadot", "main": "index.js", "keywords": [ @@ -29,15 +29,15 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/trie-db#readme", "dependencies": { "@babel/runtime": "^7.3.4", - "@polkadot/db": "^0.35.10", - "@polkadot/trie-codec": "^0.35.10", - "@polkadot/trie-hash": "^0.35.10", - "@polkadot/util": "^0.35.10", - "@polkadot/util-crypto": "^0.35.10" + "@polkadot/db": "^0.36.0", + "@polkadot/trie-codec": "^0.36.0", + "@polkadot/trie-hash": "^0.36.0", + "@polkadot/util": "^0.36.0", + "@polkadot/util-crypto": "^0.36.0" }, "devDependencies": { - "@polkadot/chainspec": "^0.35.10", - "@polkadot/util-rlp": "^0.35.10", + "@polkadot/chainspec": "^0.36.0", + "@polkadot/util-rlp": "^0.36.0", "ethereumjs-testing": "1.0.4" } } diff --git a/packages/trie-hash/package.json b/packages/trie-hash/package.json index f5f916353..8a8708966 100644 --- a/packages/trie-hash/package.json +++ b/packages/trie-hash/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/trie-hash", - "version": "0.35.10", + "version": "0.36.0", "description": "Generates trie roots from key-value pairs", "main": "index.js", "keywords": [ @@ -29,9 +29,9 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/trie-hash#readme", "dependencies": { "@babel/runtime": "^7.3.4", - "@polkadot/util": "^0.35.10" + "@polkadot/util": "^0.36.0" }, "devDependencies": { - "@polkadot/chainspec": "^0.35.10" + "@polkadot/chainspec": "^0.36.0" } } diff --git a/packages/util-crypto/package.json b/packages/util-crypto/package.json index 2fb6142d5..538e2dcf2 100644 --- a/packages/util-crypto/package.json +++ b/packages/util-crypto/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/util-crypto", - "version": "0.35.10", + "version": "0.36.0", "description": "A collection of useful crypto utilities for @polkadot", "main": "index.js", "keywords": [ @@ -30,7 +30,7 @@ "dependencies": { "@babel/runtime": "^7.3.4", "@polkadot/schnorrkel-js": "^0.1.2-3", - "@polkadot/util": "^0.35.10", + "@polkadot/util": "^0.36.0", "@types/bip39": "^2.4.2", "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^3.5.0", diff --git a/packages/util-crypto/src/index.ts b/packages/util-crypto/src/index.ts index d3c055199..13f160039 100644 --- a/packages/util-crypto/src/index.ts +++ b/packages/util-crypto/src/index.ts @@ -6,6 +6,7 @@ import { schnorrkelWaitReady } from './schnorrkel'; export * from './blake2'; export * from './keccak'; +export * from './key'; export * from './mnemonic'; export * from './nacl'; export * from './random'; diff --git a/packages/util-crypto/src/key/DeriveJunction.ts b/packages/util-crypto/src/key/DeriveJunction.ts new file mode 100644 index 000000000..ed8254c8f --- /dev/null +++ b/packages/util-crypto/src/key/DeriveJunction.ts @@ -0,0 +1,85 @@ +// Copyright 2017-2019 @polkadot/util-crypto authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import BN from 'bn.js'; +import { bnToHex, compactAddLength, hexToU8a, isBn, isHex, isNumber, isString, stringToU8a } from '@polkadot/util/index'; + +import blake2AsU8a from '../blake2/asU8a'; + +const RE_NUMBER = /^\d+$/; + +const JUNCTION_ID_LEN: number = 32; +const BN_OPTIONS = { + bitLength: 256, + isLe: true +}; + +export default class DeriveJunction { + private _chainCode: Uint8Array = new Uint8Array(32); + private _isHard: boolean = false; + + static from (value: string): DeriveJunction { + const [code, isHard] = value[0] === '/' + ? [value.substr(1), true] + : [value, false]; + const result = new DeriveJunction(); + + result.soft( + RE_NUMBER.test(code) + ? parseInt(code, 10) + : code + ); + + return isHard + ? result.harden() + : result; + } + + get chainCode (): Uint8Array { + return this._chainCode; + } + + get isHard (): boolean { + return this._isHard; + } + + get isSoft (): boolean { + return !this._isHard; + } + + hard (value: number | BN | string | Uint8Array): DeriveJunction { + return this.soft(value).harden(); + } + + harden (): DeriveJunction { + this._isHard = true; + + return this; + } + + soft (value: number | BN | string | Uint8Array): DeriveJunction { + if (isNumber(value) || isBn(value)) { + return this.soft(bnToHex(value, BN_OPTIONS)); + } else if (isString(value)) { + return isHex(value) + ? this.soft(hexToU8a(value)) + : this.soft(compactAddLength(stringToU8a(value))); + } + + if (value.length > JUNCTION_ID_LEN) { + return this.soft(blake2AsU8a(value)); + } + + this._chainCode.fill(0); + this._chainCode.set(value, 0); + + return this; + } + + soften (): DeriveJunction { + this._isHard = false; + + return this; + } +} diff --git a/packages/util-crypto/src/key/extract.spec.ts b/packages/util-crypto/src/key/extract.spec.ts new file mode 100644 index 000000000..c8c7a5b69 --- /dev/null +++ b/packages/util-crypto/src/key/extract.spec.ts @@ -0,0 +1,131 @@ +// Copyright 2017-2019 @polkadot/util-crypto authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import keyExtract from './extract'; + +describe('keyExtract', () => { + it('derives on "hello world"', () => { + expect( + keyExtract('hello world') + ).toEqual({ + path: [], + phrase: 'hello world' + }); + }); + + it('derives on "hello world/1', () => { + expect( + keyExtract('hello world/1') + ).toEqual({ + path: [ + { _isHard: false, _chainCode: Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) } + ], + phrase: 'hello world' + }); + }); + + it('derives on "hello world/DOT', () => { + expect( + keyExtract('hello world/DOT') + ).toEqual({ + path: [ + { _isHard: false, _chainCode: Uint8Array.from([12, 68, 79, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) } + ], + phrase: 'hello world' + }); + }); + + it('derives on "hello world//1', () => { + expect( + keyExtract('hello world//1') + ).toEqual({ + path: [ + { _isHard: true, _chainCode: Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) } + ], + phrase: 'hello world' + }); + }); + + it('derives on "hello world//DOT', () => { + expect( + keyExtract('hello world//DOT') + ).toEqual({ + path: [ + { _isHard: true, _chainCode: Uint8Array.from([12, 68, 79, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) } + ], + phrase: 'hello world' + }); + }); + + it('derives on "hello world//1/DOT', () => { + expect( + keyExtract('hello world//1/DOT') + ).toEqual({ + path: [ + { _isHard: true, _chainCode: Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) }, + { _isHard: false, _chainCode: Uint8Array.from([12, 68, 79, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) } + ], + phrase: 'hello world' + }); + }); + + it('derives on "hello world//DOT/1', () => { + expect( + keyExtract('hello world//DOT/1') + ).toEqual({ + path: [ + { _isHard: true, _chainCode: Uint8Array.from([12, 68, 79, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) }, + { _isHard: false, _chainCode: Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) } + ], + phrase: 'hello world' + }); + }); + + it('derives on "hello world///password"', () => { + expect( + keyExtract('hello world///password') + ).toEqual({ + password: 'password', + path: [], + phrase: 'hello world' + }); + }); + + it('derives on "hello world//1/DOT///password"', () => { + expect( + keyExtract('hello world//1/DOT///password') + ).toEqual({ + path: [ + { _isHard: true, _chainCode: Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) }, + { _isHard: false, _chainCode: Uint8Array.from([12, 68, 79, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) } + ], + password: 'password', + phrase: 'hello world' + }); + }); + + it('derives on "hello world/1//DOT///password"', () => { + expect( + keyExtract('hello world/1//DOT///password') + ).toEqual({ + path: [ + { _isHard: false, _chainCode: Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) }, + { _isHard: true, _chainCode: Uint8Array.from([12, 68, 79, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) } + ], + password: 'password', + phrase: 'hello world' + }); + }); + + it('derives on actual Alice', () => { + expect( + keyExtract('bottom drive obey lake curtain smoke basket hold race lonely fit walk//Alice') + ).toEqual({ + path: [ + { _isHard: true, _chainCode: Uint8Array.from([20, 65, 108, 105, 99, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) } + ], + phrase: 'bottom drive obey lake curtain smoke basket hold race lonely fit walk' + }); + }); +}); diff --git a/packages/util-crypto/src/key/extract.ts b/packages/util-crypto/src/key/extract.ts new file mode 100644 index 000000000..b6997fbec --- /dev/null +++ b/packages/util-crypto/src/key/extract.ts @@ -0,0 +1,41 @@ +// Copyright 2017-2019 @polkadot/util-crypto authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { assert, isNull } from '@polkadot/util/index'; + +import DeriveJunction from './DeriveJunction'; + +type DeriveResult = { + password?: string, + path: Array, + phrase: string +}; + +const RE_CAPTURE = /^(\w+( \w+)*)((\/\/?[^\/]+)*)(\/\/\/(.*))?$/; +const RE_JUNCTION = /\/(\/?)([^\/]+)/g; + +/** + * @description Extracts the phrase, path and password from a SURI format for specifying secret keys `//////` (the `///password` may be omitted, and `/` and `//` maybe repeated and mixed). + */ +export default function keyExtract (suri: string): DeriveResult { + const matches = suri.match(RE_CAPTURE); + + assert(!isNull(matches), `Unable to match '${suri}' to a secret URI`); + + const [, phrase, , junctions, , , password] = matches as Array; + const parts = junctions.match(RE_JUNCTION); + const path: Array = []; + + if (parts) { + parts.forEach((value: string) => { + path.push(DeriveJunction.from(value.substr(1))); + }); + } + + return { + password, + path, + phrase + }; +} diff --git a/packages/util-crypto/src/key/fromPath.ts b/packages/util-crypto/src/key/fromPath.ts new file mode 100644 index 000000000..6036b988a --- /dev/null +++ b/packages/util-crypto/src/key/fromPath.ts @@ -0,0 +1,17 @@ +// Copyright 2017-2019 @polkadot/util-crypto authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { KeypairType } from '../types'; + +import DeriveJunction from './DeriveJunction'; +import keyHdkdEd15519 from './hdkdEd25519'; +import keyHdkdSr15519 from './hdkdSr25519'; + +export default function keyFromPath (seed: Uint8Array, path: Array, type: KeypairType): Uint8Array { + return path.reduce((seed, junction) => { + return type === 'ed25519' + ? keyHdkdEd15519(seed, junction) + : keyHdkdSr15519(seed, junction); + }, seed); +} diff --git a/packages/util-crypto/src/key/hdkdEd25519.ts b/packages/util-crypto/src/key/hdkdEd25519.ts new file mode 100644 index 000000000..d298268d6 --- /dev/null +++ b/packages/util-crypto/src/key/hdkdEd25519.ts @@ -0,0 +1,18 @@ +// Copyright 2017-2019 @polkadot/util-crypto authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { assert, compactAddLength, stringToU8a, u8aConcat } from '@polkadot/util/index'; + +import blake2AsU8a from '../blake2/asU8a'; +import DeriveJunction from './DeriveJunction'; + +const HDKD = compactAddLength(stringToU8a('Ed25519HDKD')); + +export default function keyHdkdEd25519 (seed: Uint8Array, { chainCode, isHard }: DeriveJunction): Uint8Array { + assert(isHard, 'A soft key was found in the path (and is unsupported)'); + + return blake2AsU8a( + u8aConcat(HDKD, seed, chainCode) + ); +} diff --git a/packages/util-crypto/src/key/hdkdSr25519.ts b/packages/util-crypto/src/key/hdkdSr25519.ts new file mode 100644 index 000000000..583812e6c --- /dev/null +++ b/packages/util-crypto/src/key/hdkdSr25519.ts @@ -0,0 +1,17 @@ +// Copyright 2017-2019 @polkadot/util-crypto authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { stringToU8a, u8aConcat } from '@polkadot/util/index'; + +import blake2AsU8a from '../blake2/asU8a'; +import DeriveJunction from './DeriveJunction'; + +const HDKD = stringToU8a('SchnorrRistrettoHDKD'); + +// FIXME This should pull in from schnorrkel and do the magic there +export default function keyHdkdSr25519 (seed: Uint8Array, { chainCode }: DeriveJunction): Uint8Array { + return blake2AsU8a( + u8aConcat(HDKD, seed, chainCode) + ); +} diff --git a/packages/util-crypto/src/key/index.ts b/packages/util-crypto/src/key/index.ts new file mode 100644 index 000000000..9db936f53 --- /dev/null +++ b/packages/util-crypto/src/key/index.ts @@ -0,0 +1,11 @@ +// Copyright 2017-2019 @polkadot/util-crypto authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +/** + * @summary Create keys from paths, seeds and password + */ +export { default as keyExtract } from './extract'; +export { default as keyFromPath } from './fromPath'; +export { default as keyHdkdEd25519 } from './hdkdEd25519'; +export { default as keyHdkdSr25519 } from './hdkdEd25519'; diff --git a/packages/util-crypto/src/nacl/keypair/fromRandom.spec.ts b/packages/util-crypto/src/nacl/keypair/fromRandom.spec.ts index b0ec4b0dc..f95676b66 100644 --- a/packages/util-crypto/src/nacl/keypair/fromRandom.spec.ts +++ b/packages/util-crypto/src/nacl/keypair/fromRandom.spec.ts @@ -2,12 +2,12 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { KeypairType } from '../../types'; +import { Keypair } from '../../types'; import { naclKeypairFromRandom } from '../index'; describe('naclKeypairFromRandom', () => { - let keypair: KeypairType; + let keypair: Keypair; beforeEach(() => { keypair = naclKeypairFromRandom(); diff --git a/packages/util-crypto/src/nacl/keypair/fromRandom.ts b/packages/util-crypto/src/nacl/keypair/fromRandom.ts index 64dd16c92..e2c2ed600 100644 --- a/packages/util-crypto/src/nacl/keypair/fromRandom.ts +++ b/packages/util-crypto/src/nacl/keypair/fromRandom.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { KeypairType } from '../../types'; +import { Keypair } from '../../types'; import nacl from 'tweetnacl'; @@ -20,6 +20,6 @@ import nacl from 'tweetnacl'; * naclKeypairFromRandom(); // => { secretKey: [...], publicKey: [...] } * ``` */ -export default function naclKeypairFromRandom (): KeypairType { +export default function naclKeypairFromRandom (): Keypair { return nacl.sign.keyPair(); } diff --git a/packages/util-crypto/src/nacl/keypair/fromSecret.ts b/packages/util-crypto/src/nacl/keypair/fromSecret.ts index bdcc4a618..dd523022d 100644 --- a/packages/util-crypto/src/nacl/keypair/fromSecret.ts +++ b/packages/util-crypto/src/nacl/keypair/fromSecret.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { KeypairType } from '../../types'; +import { Keypair } from '../../types'; import nacl from 'tweetnacl'; @@ -20,6 +20,6 @@ import nacl from 'tweetnacl'; * naclKeypairFromSecret(...); // => { secretKey: [...], publicKey: [...] } * ``` */ -export default function naclKeypairFromSecret (secret: Uint8Array): KeypairType { +export default function naclKeypairFromSecret (secret: Uint8Array): Keypair { return nacl.sign.keyPair.fromSecretKey(secret); } diff --git a/packages/util-crypto/src/nacl/keypair/fromSeed.ts b/packages/util-crypto/src/nacl/keypair/fromSeed.ts index 43e4b7393..db801cea6 100644 --- a/packages/util-crypto/src/nacl/keypair/fromSeed.ts +++ b/packages/util-crypto/src/nacl/keypair/fromSeed.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { KeypairType } from '../../types'; +import { Keypair } from '../../types'; import nacl from 'tweetnacl'; @@ -20,6 +20,6 @@ import nacl from 'tweetnacl'; * naclKeypairFromSeed(...); // => { secretKey: [...], publicKey: [...] } * ``` */ -export default function naclKeypairFromSeed (seed: Uint8Array): KeypairType { +export default function naclKeypairFromSeed (seed: Uint8Array): Keypair { return nacl.sign.keyPair.fromSeed(seed); } diff --git a/packages/util-crypto/src/nacl/keypair/fromString.ts b/packages/util-crypto/src/nacl/keypair/fromString.ts index 4f3b8be8c..108ddd3ca 100644 --- a/packages/util-crypto/src/nacl/keypair/fromString.ts +++ b/packages/util-crypto/src/nacl/keypair/fromString.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { KeypairType } from '../../types'; +import { Keypair } from '../../types'; import { stringToU8a } from '@polkadot/util/index'; @@ -23,7 +23,7 @@ import fromSeed from './fromSeed'; * naclKeypairFromString('test'); // => { secretKey: [...], publicKey: [...] } * ``` */ -export default function naclKeypairFromString (value: string): KeypairType { +export default function naclKeypairFromString (value: string): Keypair { return fromSeed( blake2AsU8a( stringToU8a(value), diff --git a/packages/util-crypto/src/nacl/sign.ts b/packages/util-crypto/src/nacl/sign.ts index 089420589..ef5e82c24 100644 --- a/packages/util-crypto/src/nacl/sign.ts +++ b/packages/util-crypto/src/nacl/sign.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { KeypairType } from '../types'; +import { Keypair } from '../types'; import nacl from 'tweetnacl'; import { assert } from '@polkadot/util/index'; @@ -21,7 +21,7 @@ import { assert } from '@polkadot/util/index'; * naclSign([...], [...]); // => [...] * ``` */ -export default function naclSign (message: Uint8Array, { secretKey }: Partial): Uint8Array { +export default function naclSign (message: Uint8Array, { secretKey }: Partial): Uint8Array { assert(secretKey && secretKey.length === 64, 'Expected valid secretKey, 64 bytes'); return nacl.sign.detached(message, secretKey as Uint8Array); diff --git a/packages/util-crypto/src/schnorrkel/keypair/fromSeed.ts b/packages/util-crypto/src/schnorrkel/keypair/fromSeed.ts index d2b7a4c7d..073b31358 100644 --- a/packages/util-crypto/src/schnorrkel/keypair/fromSeed.ts +++ b/packages/util-crypto/src/schnorrkel/keypair/fromSeed.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { KeypairType } from '../../types'; +import { Keypair } from '../../types'; import schnorrkel from '@polkadot/schnorrkel-js'; @@ -13,7 +13,7 @@ const PUB_LEN = 32; * @name schnorrkelKeypairFromSeed * @description Returns a object containing a `publicKey` & `secretKey` generated from the supplied seed. */ -export default function schnorrkelKeypairFromSeed (seed: Uint8Array): KeypairType { +export default function schnorrkelKeypairFromSeed (seed: Uint8Array): Keypair { const full = schnorrkel.keypair_from_seed(seed); return { diff --git a/packages/util-crypto/src/schnorrkel/sign.ts b/packages/util-crypto/src/schnorrkel/sign.ts index 3cdd4e856..ae69fb217 100644 --- a/packages/util-crypto/src/schnorrkel/sign.ts +++ b/packages/util-crypto/src/schnorrkel/sign.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { KeypairType } from '../types'; +import { Keypair } from '../types'; import { assert } from '@polkadot/util/index'; @@ -12,7 +12,7 @@ import schnorrkel from '@polkadot/schnorrkel-js'; * @name schnorrkelSign * @description Returns message signature of `message`, using the supplied pair */ -export default function schnorrkelSign (message: Uint8Array, { publicKey, secretKey }: Partial): Uint8Array { +export default function schnorrkelSign (message: Uint8Array, { publicKey, secretKey }: Partial): Uint8Array { assert(publicKey && publicKey.length === 32, 'Expected valid publicKey, 32-bytes'); assert(secretKey && secretKey.length === 64, 'Expected valid secretKey, 64-bytes'); diff --git a/packages/util-crypto/src/types.ts b/packages/util-crypto/src/types.ts index 5af78e18e..9d2b0c57a 100644 --- a/packages/util-crypto/src/types.ts +++ b/packages/util-crypto/src/types.ts @@ -2,7 +2,9 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -export type KeypairType = { +export type Keypair = { publicKey: Uint8Array; secretKey: Uint8Array; }; + +export type KeypairType = 'ed25519' | 'sr25519'; diff --git a/packages/util-rlp/package.json b/packages/util-rlp/package.json index a9abedbb8..4d20cd184 100644 --- a/packages/util-rlp/package.json +++ b/packages/util-rlp/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/util-rlp", - "version": "0.35.10", + "version": "0.36.0", "description": "RLP encoding and decoding", "main": "index.js", "keywords": [ @@ -31,7 +31,7 @@ "homepage": "https://github.com/polkadot-js/common/tree/master/packages/util-rlp#readme", "dependencies": { "@babel/runtime": "^7.3.4", - "@polkadot/util": "^0.35.10" + "@polkadot/util": "^0.36.0" }, "devDependencies": { "ethereumjs-testing": "1.0.4" diff --git a/packages/util/package.json b/packages/util/package.json index 886a2f10d..404a68f4c 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@polkadot/util", - "version": "0.35.10", + "version": "0.36.0", "description": "A collection of useful utilities for @polkadot", "main": "index.js", "keywords": [