Initial pair encryption (xsalsa20-poly1305) (#107)
* Allow keypair generation from input string * Add keyfile encryption/decryption * Pass secret through n rounds * Split definition types * Additional cleanups * Pass salt as blake2b input * Move kdf hashing to util-cypto * Dangling comma * Pull through secret as string | Uint8Array * Update documentation
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
Utility methods for this package are split into groups
|
||||
|
||||
- [blake2](blake2.md) Create blake2b values with specified bitlengths
|
||||
- [kdf](kdf.md) Create Keys for use in encryption (rounds & salt) based on inputs
|
||||
- [keccak](keccak.md) Create Keccak256 values as hex & Uint8Array output
|
||||
- [nacl](nacl.md) Implements [NaCl](http://nacl.cr.yp.to/) secret-key authenticated encryption, public-key authenticated encryption, hashing, and public-key signatures
|
||||
- [random](random.md) Returns a sequence of secure random bytes in a variety of formats
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# kdf
|
||||
|
||||
Create Keys for use in encryption (rounds & salt) based on inputs
|
||||
|
||||
- [kdfAsU8a](#kdfasu8a) Create Uint8Array key based on inputs
|
||||
|
||||
## kdfAsU8a
|
||||
|
||||
Create Uint8Array key based on inputs
|
||||
|
||||
```js
|
||||
kdfAsU8a (secret: Uint8Array | string, rounds?: number, salt?: Uint8Array): { key: Uint8Array, rounds: number, salt: Uint8Array }
|
||||
```
|
||||
|
||||
|
||||
From either a `string` or a `Uint8Array` input, create a key with an optional (or random) salt based on the number of rounds with Blake2. Return return the result key as a `Uint8Array` in addition to the salt used and rounds employed.
|
||||
|
||||
```js
|
||||
import { kdfAsU8a } from '@polkadot/util-crypto';
|
||||
|
||||
kdfAsU8a('123') // => { key: Uint8Array, rounds: number, salt: Uint8Array }
|
||||
```
|
||||
@@ -2,9 +2,45 @@
|
||||
|
||||
Implements [NaCl](http://nacl.cr.yp.to/) secret-key authenticated encryption, public-key authenticated encryption, hashing, and public-key signatures
|
||||
|
||||
- [naclDecrypt](#nacldecrypt) Decrypts a message using the supplied secretKey and nonce
|
||||
- [naclEncrypt](#naclencrypt) Encrypts a message using the supplied secretKey and nonce
|
||||
- [naclSign](#naclsign) Signs a message using the supplied secretKey
|
||||
- [naclSign](#naclsign) Verifies the signature on the supplied message.
|
||||
|
||||
## naclDecrypt
|
||||
|
||||
Decrypts a message using the supplied secretKey and nonce
|
||||
|
||||
```js
|
||||
naclDecrypt (message: Uint8Array, secretKey: Uint8Array, nonce: Uint8Array): Uint8Array
|
||||
```
|
||||
|
||||
|
||||
Returns an decrypted message, using the `secretKey` and `nonce`.
|
||||
|
||||
```js
|
||||
import { naclDecrypt } from '@polkadot/util-crypto';
|
||||
|
||||
naclDecrypt([...], [...], [...]) // => [...]
|
||||
```
|
||||
|
||||
## naclEncrypt
|
||||
|
||||
Encrypts a message using the supplied secretKey and nonce
|
||||
|
||||
```js
|
||||
naclEncrypt (message: Uint8Array, secretKey: Uint8Array, nonce?: Uint8Array): { encrypted: Uint8Array, nonce: Uint8Array }
|
||||
```
|
||||
|
||||
|
||||
Returns an encrypted message, using the `secretKey` and `nonce`. If the `nonce` was not supplied, a random value is generated.
|
||||
|
||||
```js
|
||||
import { naclEncrypt } from '@polkadot/util-crypto';
|
||||
|
||||
naclSign([...], [...]) // => [...]
|
||||
```
|
||||
|
||||
## naclSign
|
||||
|
||||
Signs a message using the supplied secretKey
|
||||
|
||||
@@ -16,6 +16,6 @@ const blake2bAsU8a = require('./blake2b/asU8a');
|
||||
|
||||
blake2AsU8a('abc') // => [0xba, 0x80, 0xa53, 0xf98, 0x1c, 0x4d, 0x0d]
|
||||
*/
|
||||
module.exports = function blake2AsU8a (data: Uint8Array, bitLength: number = 256): Uint8Array {
|
||||
return blake2bAsU8a(data, bitLength);
|
||||
module.exports = function blake2AsU8a (data: Uint8Array, bitLength: number = 256, key?: Uint8Array): Uint8Array {
|
||||
return blake2bAsU8a(data, bitLength, key);
|
||||
};
|
||||
|
||||
@@ -16,6 +16,6 @@ const blake2AsU8a = require('./asU8a');
|
||||
|
||||
blake2AsU8a256('abc') // => 0x44bc2cf5ad770999
|
||||
*/
|
||||
module.exports = function blake2AsU8a256 (data: Uint8Array): Uint8Array {
|
||||
return blake2AsU8a(data, 256);
|
||||
module.exports = function blake2AsU8a256 (data: Uint8Array, key?: Uint8Array): Uint8Array {
|
||||
return blake2AsU8a(data, 256, key);
|
||||
};
|
||||
|
||||
@@ -17,6 +17,6 @@ const blakejs = require('blakejs');
|
||||
|
||||
blake2bAsU8a('abc') // => Uint8Array('508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982')
|
||||
*/
|
||||
module.exports = function blake2bAsU8a (data: Uint8Array, bitLength: number = 512): Uint8Array {
|
||||
return blakejs.blake2b(data, null, bitLength / 8);
|
||||
module.exports = function blake2bAsU8a (data: Uint8Array, bitLength: number = 512, key: ?Uint8Array = null): Uint8Array {
|
||||
return blakejs.blake2b(data, key, bitLength / 8);
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// @flow
|
||||
|
||||
const blake2 = require('./blake2');
|
||||
const kdf = require('./kdf');
|
||||
const keccak = require('./keccak');
|
||||
const nacl = require('./nacl');
|
||||
const random = require('./random');
|
||||
@@ -14,5 +15,5 @@ const xxhash = require('./xxhash');
|
||||
@summary Utility methods for this package are split into groups
|
||||
*/
|
||||
module.exports = Object.assign(
|
||||
{}, blake2, keccak, nacl, random, sha512, xxhash
|
||||
{}, blake2, kdf, keccak, nacl, random, sha512, xxhash
|
||||
);
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// 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
|
||||
|
||||
type KdfU8a = {
|
||||
key: Uint8Array,
|
||||
rounds: number,
|
||||
salt: Uint8Array
|
||||
};
|
||||
|
||||
const isU8a = require('@polkadot/util/is/u8a');
|
||||
const u8aFromUtf8 = require('@polkadot/util/u8a/fromUtf8');
|
||||
|
||||
const blake2AsU8a256 = require('../blake2/asU8a256');
|
||||
const randomAsU8a = require('../random/asU8a');
|
||||
|
||||
/**
|
||||
@name kdfAsU8a
|
||||
@signature kdfAsU8a (secret: Uint8Array | string, rounds?: number, salt?: Uint8Array): { key: Uint8Array, rounds: number, salt: Uint8Array }
|
||||
@summary Create Uint8Array key based on inputs
|
||||
@description
|
||||
From either a `string` or a `Uint8Array` input, create a key with an optional (or random) salt based on the number of rounds with Blake2. Return return the result key as a `Uint8Array` in addition to the salt used and rounds employed.
|
||||
@example
|
||||
import { kdfAsU8a } from '@polkadot/util-crypto';
|
||||
|
||||
kdfAsU8a('123') // => { key: Uint8Array, rounds: number, salt: Uint8Array }
|
||||
*/
|
||||
module.exports = function kdfAsU8a (secret: Uint8Array | string, _rounds: number = 16, salt: Uint8Array = randomAsU8a(32)): KdfU8a {
|
||||
const rounds = Math.max(1, _rounds);
|
||||
let key: Uint8Array = isU8a(secret)
|
||||
// flowlint-next-line unclear-type:off
|
||||
? ((secret: any): Uint8Array)
|
||||
// flowlint-next-line unclear-type:off
|
||||
: u8aFromUtf8(((secret: any): string));
|
||||
|
||||
for (let count = 0; count < rounds; count++) {
|
||||
key = blake2AsU8a256(key, salt);
|
||||
}
|
||||
|
||||
return {
|
||||
key,
|
||||
rounds,
|
||||
salt
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
// 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 { kdfAsU8a } = require('./index');
|
||||
|
||||
describe('kdfAsU8a', () => {
|
||||
it('generates known via specified salt & rounds', () => {
|
||||
const kdf = kdfAsU8a('test', 4, new Uint8Array(32));
|
||||
|
||||
expect(
|
||||
kdf
|
||||
).toEqual({
|
||||
key: new Uint8Array([103, 101, 136, 180, 146, 65, 105, 190, 91, 158, 187, 202, 45, 7, 115, 229, 215, 76, 8, 12, 185, 45, 25, 148, 98, 156, 53, 167, 51, 15, 26, 150]),
|
||||
rounds: 4,
|
||||
salt: new Uint8Array(32)
|
||||
});
|
||||
});
|
||||
|
||||
it('defaults with rounds & random salt', () => {
|
||||
const kdf = kdfAsU8a(new Uint8Array(1, 2, 3, 4));
|
||||
|
||||
expect(kdf.key).toHaveLength(32);
|
||||
expect(kdf.rounds).toEqual(16);
|
||||
expect(kdf.salt).not.toEqual(new Uint8Array(32));
|
||||
});
|
||||
|
||||
it('does at least 1 round', () => {
|
||||
const kdf = kdfAsU8a(new Uint8Array(1, 2, 3, 4), -10);
|
||||
|
||||
expect(kdf.rounds).toEqual(1);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
// 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
|
||||
|
||||
const kdfAsU8a = require('./asU8a');
|
||||
|
||||
/**
|
||||
@summary Create Keys for use in encryption (rounds & salt) based on inputs
|
||||
*/
|
||||
module.exports = {
|
||||
kdfAsU8a
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
// 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
|
||||
|
||||
const nacl = require('tweetnacl');
|
||||
|
||||
/**
|
||||
@name naclDecrypt
|
||||
@signature naclDecrypt (message: Uint8Array, secretKey: Uint8Array, nonce: Uint8Array): Uint8Array
|
||||
@summary Decrypts a message using the supplied secretKey and nonce
|
||||
@description
|
||||
Returns an decrypted message, using the `secretKey` and `nonce`.
|
||||
@example
|
||||
import { naclDecrypt } from '@polkadot/util-crypto';
|
||||
|
||||
naclDecrypt([...], [...], [...]) // => [...]
|
||||
*/
|
||||
module.exports = function naclDecrypt (message: Uint8Array, secret: Uint8Array, nonce: Uint8Array): ?Uint8Array {
|
||||
return nacl.secretbox.open(message, nonce, secret);
|
||||
};
|
||||
@@ -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.
|
||||
|
||||
const { naclDecrypt, naclEncrypt } = require('./index');
|
||||
|
||||
describe('naclDecrypt', () => {
|
||||
it('decrypts a encrypted message', () => {
|
||||
const secret = new Uint8Array(32);
|
||||
const message = new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]);
|
||||
const { encrypted, nonce } = naclEncrypt(message, secret);
|
||||
|
||||
expect(
|
||||
naclDecrypt(encrypted, secret, nonce)
|
||||
).toEqual(
|
||||
message
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
// 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
|
||||
|
||||
type Encrypted = {
|
||||
encrypted: Uint8Array,
|
||||
nonce: Uint8Array
|
||||
};
|
||||
|
||||
const nacl = require('tweetnacl');
|
||||
|
||||
const randomAsU8a = require('../random/asU8a');
|
||||
|
||||
/**
|
||||
@name naclEncrypt
|
||||
@signature naclEncrypt (message: Uint8Array, secretKey: Uint8Array, nonce?: Uint8Array): { encrypted: Uint8Array, nonce: Uint8Array }
|
||||
@summary Encrypts a message using the supplied secretKey and nonce
|
||||
@description
|
||||
Returns an encrypted message, using the `secretKey` and `nonce`. If the `nonce` was not supplied, a random value is generated.
|
||||
@example
|
||||
import { naclEncrypt } from '@polkadot/util-crypto';
|
||||
|
||||
naclSign([...], [...]) // => [...]
|
||||
*/
|
||||
module.exports = function naclEncrypt (message: Uint8Array, secret: Uint8Array, nonce: Uint8Array = randomAsU8a(24)): Encrypted {
|
||||
const encrypted = nacl.secretbox(message, nonce, secret);
|
||||
|
||||
return {
|
||||
encrypted,
|
||||
nonce
|
||||
};
|
||||
};
|
||||
@@ -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.
|
||||
|
||||
const { naclEncrypt } = require('./index');
|
||||
|
||||
describe('naclEncrypt', () => {
|
||||
it('encrypts a message', () => {
|
||||
const secret = new Uint8Array(32);
|
||||
const message = new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]);
|
||||
|
||||
expect(
|
||||
naclEncrypt(message, secret, new Uint8Array(24))
|
||||
).toEqual({
|
||||
encrypted: new Uint8Array([94, 21, 20, 69, 68, 221, 140, 245, 200, 67, 77, 188, 129, 85, 227, 141, 199, 60, 184, 251, 251, 129, 205, 46, 234]),
|
||||
nonce: new Uint8Array(24)
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -3,9 +3,12 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
const naclDecrypt = require('./decrypt');
|
||||
const naclEncrypt = require('./encrypt');
|
||||
const naclKeypairFromRandom = require('./keypair/fromRandom');
|
||||
const naclKeypairFromSecret = require('./keypair/fromSecret');
|
||||
const naclKeypairFromSeed = require('./keypair/fromSeed');
|
||||
const naclKeypairFromString = require('./keypair/fromString');
|
||||
const naclSign = require('./sign');
|
||||
const naclVerify = require('./verify');
|
||||
|
||||
@@ -13,9 +16,12 @@ const naclVerify = require('./verify');
|
||||
@summary Implements [NaCl](http://nacl.cr.yp.to/) secret-key authenticated encryption, public-key authenticated encryption, hashing, and public-key signatures
|
||||
*/
|
||||
module.exports = {
|
||||
naclDecrypt,
|
||||
naclEncrypt,
|
||||
naclKeypairFromRandom,
|
||||
naclKeypairFromSecret,
|
||||
naclKeypairFromSeed,
|
||||
naclKeypairFromString,
|
||||
naclSign,
|
||||
naclVerify
|
||||
};
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// 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 '../../types';
|
||||
|
||||
const u8aFromUtf8 = require('@polkadot/util/u8a/fromUtf8');
|
||||
|
||||
const blake2AsU8a256 = require('../../blake2/asU8a256');
|
||||
const fromSeed = require('./fromSeed');
|
||||
|
||||
/**
|
||||
@name naclKeypairFromString
|
||||
@signature naclKeypairFromString (value: string): { secretKey: Uint8Array, publicKey: Uint8Array }
|
||||
@summary Creates a new public/secret keypair from a string.
|
||||
@description
|
||||
Returns a object containing a `publicKey` & `secretKey` generated from the supplied string. The string is hashed and the value used as the input seed.
|
||||
@example
|
||||
import { naclKeypairFromString } from '@polkadot/util-crypto';
|
||||
|
||||
naclKeypairFromString('test') // => { secretKey: [...], publicKey: [...] }
|
||||
*/
|
||||
module.exports = function naclKeypairFromString (value: string): KeypairType {
|
||||
return fromSeed(
|
||||
blake2AsU8a256(
|
||||
u8aFromUtf8(value)
|
||||
)
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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 { naclKeypairFromString } = require('../index');
|
||||
|
||||
describe('naclKeypairFromSeed', () => {
|
||||
it('generates a valid publicKey/secretKey pair', () => {
|
||||
expect(
|
||||
naclKeypairFromString('test')
|
||||
).toEqual({
|
||||
publicKey: new Uint8Array([188, 108, 179, 142, 36, 142, 76, 87, 77, 193, 147, 139, 254, 110, 196, 217, 117, 233, 167, 165, 250, 150, 247, 237, 198, 68, 129, 4, 211, 209, 136, 48]),
|
||||
secretKey: new Uint8Array([146, 139, 32, 54, 105, 67, 226, 175, 209, 30, 188, 14, 174, 46, 83, 169, 59, 241, 119, 164, 252, 243, 91, 204, 100, 213, 3, 112, 78, 101, 226, 2, 188, 108, 179, 142, 36, 142, 76, 87, 77, 193, 147, 139, 254, 110, 196, 217, 117, 233, 167, 165, 250, 150, 247, 237, 198, 68, 129, 4, 211, 209, 136, 48])
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -2,5 +2,6 @@
|
||||
|
||||
|
||||
|
||||
- [pair](pair.md)
|
||||
|
||||
# Available methods
|
||||
@@ -0,0 +1,3 @@
|
||||
# pair
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
import type { KeyringPairEncrypted, KeyringPair } from './types';
|
||||
|
||||
const createPair = require('./pair');
|
||||
|
||||
module.exports = function decrypt (box: KeyringPairEncrypted, secret: Uint8Array | string): KeyringPair {
|
||||
const pair = createPair({
|
||||
publicKey: box.publicKey,
|
||||
secretKey: new Uint8Array([])
|
||||
});
|
||||
|
||||
pair.decryptSelf(box, secret);
|
||||
|
||||
return pair;
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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('decrypt', () => {
|
||||
const publicKey = 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 seedOne = '12345678901234567890123456789012';
|
||||
let keypair;
|
||||
let encrypted;
|
||||
|
||||
beforeEach(() => {
|
||||
keypair = index();
|
||||
|
||||
keypair.addFromSeed(seedOne);
|
||||
encrypted = keypair.encrypt(publicKey, 'test');
|
||||
|
||||
keypair = index();
|
||||
});
|
||||
|
||||
it('decrypts a previously encrypted', () => {
|
||||
expect(
|
||||
keypair.decrypt(encrypted, 'test')
|
||||
).toMatchObject({
|
||||
publicKey
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
// 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 { KeyringPairEncrypted, KeyringPair } from './types';
|
||||
|
||||
module.exports = function encrypt (pair: ?KeyringPair, secret: Uint8Array | string): ?KeyringPairEncrypted {
|
||||
if (!pair) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return pair.encryptSelf(secret);
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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('encrypt', () => {
|
||||
const publicKey = 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 seedOne = '12345678901234567890123456789012';
|
||||
let keypair;
|
||||
|
||||
beforeEach(() => {
|
||||
keypair = index();
|
||||
|
||||
keypair.addFromSeed(seedOne);
|
||||
});
|
||||
|
||||
it('encrypts the key', () => {
|
||||
expect(
|
||||
keypair.encrypt(publicKey, 'test').publicKey
|
||||
).toEqual(publicKey);
|
||||
});
|
||||
|
||||
it('returns null for non-existing', () => {
|
||||
expect(
|
||||
keypair.encrypt(new Uint8Array([]), 'test')
|
||||
).toEqual(null);
|
||||
});
|
||||
});
|
||||
@@ -3,34 +3,29 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { KeyringInstance, KeyringPair } from './types';
|
||||
|
||||
type KeyringPairMap = {
|
||||
[Uint8Array]: KeyringPair
|
||||
};
|
||||
import type { KeyringPairEncrypted, KeyringInstance, KeyringPair } from './types';
|
||||
|
||||
const naclKeypairFromSeed = require('@polkadot/util-crypto/nacl/keypair/fromSeed');
|
||||
|
||||
const decrypt = require('./decrypt');
|
||||
const encrypt = require('./encrypt');
|
||||
const createPair = require('./pair');
|
||||
const createPairs = require('./pairs');
|
||||
|
||||
module.exports = function keyring (): KeyringInstance {
|
||||
const pairs: KeyringPairMap = {};
|
||||
const getPairs = (): Array<KeyringPair> =>
|
||||
// flowlint-next-line unclear-type:off
|
||||
((Object.values(pairs): any): Array<KeyringPair>);
|
||||
const pairs = createPairs();
|
||||
|
||||
return {
|
||||
addFromSeed: (seed: Uint8Array | string): KeyringPair => {
|
||||
const pair = createPair(naclKeypairFromSeed(seed));
|
||||
|
||||
pairs[pair.publicKey] = pair;
|
||||
|
||||
return pair;
|
||||
},
|
||||
addFromSeed: (seed: Uint8Array | string): KeyringPair =>
|
||||
pairs.add(createPair(naclKeypairFromSeed(seed))),
|
||||
decrypt: (encrypted: KeyringPairEncrypted, secret: Uint8Array | string): KeyringPair =>
|
||||
pairs.add(decrypt(encrypted, secret)),
|
||||
encrypt: (publicKey: Uint8Array, secret: Uint8Array | string): ?KeyringPairEncrypted =>
|
||||
encrypt(pairs.get(publicKey), secret),
|
||||
getPair: (publicKey: Uint8Array): ?KeyringPair =>
|
||||
pairs[publicKey],
|
||||
getPairs,
|
||||
pairs.get(publicKey),
|
||||
getPairs: pairs.all,
|
||||
getPublicKeys: (): Array<Uint8Array> =>
|
||||
getPairs().map(({ publicKey }) => publicKey)
|
||||
pairs.all().map(({ publicKey }) => publicKey)
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// 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 { KeyringPairEncrypted } from '../types';
|
||||
|
||||
const kdf = require('@polkadot/util-crypto/kdf/asU8a');
|
||||
const naclDecrypt = require('@polkadot/util-crypto/nacl/decrypt');
|
||||
const assert = require('@polkadot/util/assert');
|
||||
|
||||
module.exports = function decrypt ({ crypto: { params: { nonce }, kdf: { rounds, salt }, text } }: KeyringPairEncrypted, secret: Uint8Array | string): Uint8Array {
|
||||
const { key } = kdf(secret, rounds, salt);
|
||||
const secretKey = naclDecrypt(text, key, nonce);
|
||||
|
||||
assert(secretKey, 'Unable to decrypt pair using secret');
|
||||
|
||||
// $FlowFixMe checking for type just above
|
||||
return ((secretKey: any): Uint8Array);
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
// 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 { KeyringPairEncrypted } from '../types';
|
||||
|
||||
const kdf = require('@polkadot/util-crypto/kdf/asU8a');
|
||||
const naclEncrypt = require('@polkadot/util-crypto/nacl/encrypt');
|
||||
|
||||
module.exports = function encrypt (message: Uint8Array, secret: Uint8Array | string, publicKey: Uint8Array): KeyringPairEncrypted {
|
||||
const { key, rounds, salt } = kdf(secret);
|
||||
const { encrypted, nonce } = naclEncrypt(message, key);
|
||||
|
||||
return {
|
||||
crypto: {
|
||||
params: {
|
||||
nonce
|
||||
},
|
||||
kdf: {
|
||||
rounds,
|
||||
salt
|
||||
},
|
||||
text: encrypted
|
||||
},
|
||||
publicKey
|
||||
};
|
||||
};
|
||||
@@ -4,14 +4,22 @@
|
||||
// @flow
|
||||
|
||||
import type { KeypairType } from '@polkadot/util-crypto/types';
|
||||
import type { KeyringPair } from './types';
|
||||
import type { KeyringPairEncrypted, KeyringPair } from '../types';
|
||||
|
||||
const naclSign = require('@polkadot/util-crypto/nacl/sign');
|
||||
const naclVerify = require('@polkadot/util-crypto/nacl/verify');
|
||||
|
||||
const decrypt = require('./decrypt');
|
||||
const encrypt = require('./encrypt');
|
||||
|
||||
module.exports = function pair ({ publicKey, secretKey }: KeypairType): KeyringPair {
|
||||
return {
|
||||
publicKey,
|
||||
decryptSelf: (encrypted: KeyringPairEncrypted, secret: Uint8Array | string): void => {
|
||||
secretKey = decrypt(encrypted, secret);
|
||||
},
|
||||
encryptSelf: (secret: Uint8Array | string): KeyringPairEncrypted =>
|
||||
encrypt(secretKey, secret, publicKey),
|
||||
sign: (message: Uint8Array): Uint8Array =>
|
||||
naclSign(message, secretKey),
|
||||
verify: (message: Uint8Array, signature: Uint8Array): boolean =>
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
const keyring = require('./testing')();
|
||||
const keyring = require('../testing')();
|
||||
|
||||
// aligned with @polkadot/util-crypto tests
|
||||
describe('pair', () => {
|
||||
@@ -0,0 +1,27 @@
|
||||
// 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 { KeyringPairs, KeyringPair } from './types';
|
||||
|
||||
type KeyringPairMap = {
|
||||
[Uint8Array]: KeyringPair
|
||||
};
|
||||
|
||||
module.exports = function pairs (): KeyringPairs {
|
||||
const self: KeyringPairMap = {};
|
||||
|
||||
return {
|
||||
add: (pair: KeyringPair): KeyringPair => {
|
||||
self[pair.publicKey] = pair;
|
||||
|
||||
return pair;
|
||||
},
|
||||
all: (): Array<KeyringPair> =>
|
||||
// flowlint-next-line unclear-type:off
|
||||
((Object.values(self): any): Array<KeyringPair>),
|
||||
get: (publicKey: Uint8Array): ?KeyringPair =>
|
||||
self[publicKey]
|
||||
};
|
||||
};
|
||||
@@ -3,15 +3,41 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
export type KeyringPairEncrypted$Cipher = 'xsalsa20-poly1305';
|
||||
|
||||
export type KeyringPairEncrypted = {
|
||||
crypto: {
|
||||
params: {
|
||||
nonce: Uint8Array
|
||||
},
|
||||
kdf: {
|
||||
rounds: number,
|
||||
salt: Uint8Array
|
||||
},
|
||||
text: Uint8Array
|
||||
},
|
||||
publicKey: Uint8Array
|
||||
};
|
||||
|
||||
export type KeyringPair = {
|
||||
publicKey: Uint8Array,
|
||||
|
||||
decryptSelf: (box: KeyringPairEncrypted, secret: Uint8Array | string) => void,
|
||||
encryptSelf: (secret: Uint8Array | string) => KeyringPairEncrypted,
|
||||
sign (message: Uint8Array): Uint8Array,
|
||||
verify (message: Uint8Array, signature: Uint8Array): boolean
|
||||
};
|
||||
|
||||
export type KeyringPairs = {
|
||||
add: (pair: KeyringPair) => KeyringPair,
|
||||
all: () => Array<KeyringPair>,
|
||||
get: (publicKey: Uint8Array) => ?KeyringPair
|
||||
};
|
||||
|
||||
export type KeyringInstance = {
|
||||
addFromSeed (seed: Uint8Array | string): KeyringPair,
|
||||
decrypt (encrypted: KeyringPairEncrypted, secret: Uint8Array | string): KeyringPair,
|
||||
encrypt (publicKey: Uint8Array, secret: Uint8Array | string): ?KeyringPairEncrypted,
|
||||
getPair (publicKey: Uint8Array): ?KeyringPair,
|
||||
getPairs (): Array<KeyringPair>,
|
||||
getPublicKeys (): Array<Uint8Array>
|
||||
|
||||
Reference in New Issue
Block a user