Add @polkadot/util-keyring (#99)

This commit is contained in:
Jaco Greeff
2018-02-23 11:41:59 +01:00
committed by GitHub
parent 3a175a078b
commit cdc848dce0
19 changed files with 300 additions and 22 deletions
+37
View File
@@ -0,0 +1,37 @@
// Copyright 2017-2018 Jaco Greeff
// This software may be modified and distributed under the terms
// of the ISC license. See the LICENSE file for details.
// @flow
import type { KeyringInstance, KeyringPair } from './types';
type KeyringPairMap = {
[string]: KeyringPair
};
const naclKeypairFromSeed = require('@polkadot/util-crypto/nacl/keypair/fromSeed');
const u8aToString = require('@polkadot/util/u8a/toString');
const createPair = require('./pair');
module.exports = function keyring (): KeyringInstance {
const pairs: KeyringPairMap = {};
const getPairs = (): Array<KeyringPair> =>
// flowlint-next-line unclear-type:off
((Object.values(pairs): any): Array<KeyringPair>);
return {
addFromSeed: (seed: Uint8Array | string): KeyringPair => {
const pair = createPair(naclKeypairFromSeed(seed));
pairs[pair.id] = pair;
return pair;
},
getPair: (publicKey: Uint8Array): ?KeyringPair =>
pairs[u8aToString(publicKey)],
getPairs,
getPublicKeys: (): Array<Uint8Array> =>
getPairs().map(({ publicKey }) => publicKey)
};
};
+43
View File
@@ -0,0 +1,43 @@
// Copyright 2017-2018 Jaco Greeff
// This software may be modified and distributed under the terms
// of the ISC license. See the LICENSE file for details.
const index = require('./index');
describe('keypair', () => {
const publicKeyOne = new Uint8Array([47, 140, 97, 41, 216, 22, 207, 81, 195, 116, 188, 127, 8, 195, 230, 62, 209, 86, 207, 120, 174, 251, 74, 101, 80, 217, 123, 135, 153, 121, 119, 238]);
const publicKeyTwo = new Uint8Array([215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58, 14, 225, 114, 243, 218, 166, 35, 37, 175, 2, 26, 104, 247, 7, 81, 26]);
const seedOne = '12345678901234567890123456789012';
const seedTwo = '0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60';
let keypair;
beforeEach(() => {
keypair = index();
keypair.addFromSeed(seedOne);
});
it('adds the pair', () => {
expect(
keypair.addFromSeed(seedTwo)
).toMatchObject({
publicKey: publicKeyTwo
});
});
it('allows publicKeys retrieval', () => {
keypair.addFromSeed(seedTwo);
expect(
keypair.getPublicKeys()
).toEqual([ publicKeyOne, publicKeyTwo ]);
});
it('allows retrieval of a specific item', () => {
expect(
keypair.getPair(publicKeyOne)
).toMatchObject({
publicKey: publicKeyOne
});
});
});
+22
View File
@@ -0,0 +1,22 @@
// Copyright 2017-2018 Jaco Greeff
// This software may be modified and distributed under the terms
// of the ISC license. See the LICENSE file for details.
// @flow
import type { KeypairType } from '@polkadot/util-crypto/types';
import type { KeyringPair } from './types';
const naclSign = require('@polkadot/util-crypto/nacl/sign');
const naclVerify = require('@polkadot/util-crypto/nacl/verify');
const u8aToString = require('@polkadot/util/u8a/toString');
module.exports = function pair ({ publicKey, secretKey }: KeypairType): KeyringPair {
return {
id: u8aToString(publicKey),
publicKey,
sign: (message: Uint8Array): Uint8Array =>
naclSign(message, secretKey),
verify: (message: Uint8Array, signature: Uint8Array): boolean =>
naclVerify(message, signature, publicKey)
};
};
+44
View File
@@ -0,0 +1,44 @@
// Copyright 2017-2018 Jaco Greeff
// This software may be modified and distributed under the terms
// of the ISC license. See the LICENSE file for details.
const keyring = require('./testing')();
// aligned with @polkadot/util-crypto tests
describe('pair', () => {
const SIGNATURE = new Uint8Array([28, 58, 206, 239, 249, 70, 59, 191, 166, 40, 219, 218, 235, 170, 25, 79, 10, 94, 9, 197, 34, 126, 1, 150, 246, 68, 28, 238, 36, 26, 172, 163, 168, 90, 202, 211, 126, 246, 57, 212, 43, 24, 88, 197, 240, 113, 118, 76, 37, 81, 91, 110, 236, 50, 144, 134, 100, 223, 220, 238, 34, 185, 211, 7]);
it('has a publicKey', () => {
expect(
keyring.one.publicKey
).toEqual(
new Uint8Array([47, 140, 97, 41, 216, 22, 207, 81, 195, 116, 188, 127, 8, 195, 230, 62, 209, 86, 207, 120, 174, 251, 74, 101, 80, 217, 123, 135, 153, 121, 119, 238])
);
});
it('allows signing', () => {
expect(
keyring.one.sign(
new Uint8Array([0x61, 0x62, 0x63, 0x64])
)
).toEqual(SIGNATURE);
});
it('validates a correctly signed message', () => {
expect(
keyring.one.verify(
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
SIGNATURE
)
).toEqual(true);
});
it('fails a correctly signed message (message changed)', () => {
expect(
keyring.one.verify(
new Uint8Array([0x61, 0x62, 0x63, 0x64, 0x65]),
SIGNATURE
)
).toEqual(false);
});
});
+43
View File
@@ -0,0 +1,43 @@
// Copyright 2017-2018 Jaco Greeff
// This software may be modified and distributed under the terms
// of the ISC license. See the LICENSE file for details.
// @flow
import type { KeyringPair } from './types';
type TestKeyring = {
[string]: KeyringPair
};
const createKeyring = require('./index');
const SEEDS = {
alice:
'Alice ',
bob:
'Bob ',
charlie:
'Charlie ',
dave:
'Dave ',
eve:
'Eve ',
ferdie:
'Ferdie ',
one:
'12345678901234567890123456789012',
two:
'0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60'
};
module.exports = function testKeyring (): TestKeyring {
const keyring = createKeyring();
return Object
.keys(SEEDS)
.reduce((result, key) => {
result[key] = keyring.addFromSeed(SEEDS[key]);
return result;
}, {});
};
+19
View File
@@ -0,0 +1,19 @@
// Copyright 2017-2018 Jaco Greeff
// This software may be modified and distributed under the terms
// of the ISC license. See the LICENSE file for details.
// @flow
export type KeyringPair = {
id: string,
publicKey: Uint8Array,
sign (message: Uint8Array): Uint8Array,
verify (message: Uint8Array, signature: Uint8Array): boolean
};
export type KeyringInstance = {
addFromSeed (seed: Uint8Array | string): KeyringPair,
getPair (publicKey: Uint8Array): ?KeyringPair,
getPairs (): Array<KeyringPair>,
getPublicKeys (): Array<Uint8Array>
};