This commit is contained in:
ian.he
2019-04-11 13:42:06 +12:00
commit 4e30fab9d6
688 changed files with 51707 additions and 0 deletions
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+21
View File
@@ -0,0 +1,21 @@
# @polkadot/util-crypto
Various useful cyrpto utility functions that are used across all projects in the [@polkadot](https://polkadot.js.org) namespace. It provides utility functions with additional safety checks, allowing not only for consistent coding, but also reducing the general boilerplate.
## Usage
Installation -
```
yarn add @polkadot/util-crypto
```
Functions can be imported as follows:
```js
import { mnemonicGenerate } from '@polkadot/util-crypto';
```
## Utilities
[Utilities](SUMMARY.md)
+46
View File
@@ -0,0 +1,46 @@
{
"name": "@plugnet/util-crypto",
"version": "0.76.1",
"description": "A collection of useful crypto utilities for @plugnet",
"main": "index.js",
"keywords": [
"Plugnet"
],
"author": "Jaco Greeff <jacogr@gmail.com>",
"maintainers": [
"Jaco Greeff <jacogr@gmail.com>"
],
"contributors": [],
"license": "Apache-2.0",
"engines": {
"node": ">=6.4"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
},
"repository": {
"type": "git",
"url": "git+https://github.com/polkadot-js/common.git"
},
"bugs": {
"url": "https://github.com/polkadot-js/common/issues"
},
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/util-crypto#readme",
"dependencies": {
"@babel/runtime": "^7.4.3",
"@plugnet/util": "^0.76.1",
"@polkadot/wasm-crypto": "^0.8.1",
"@types/bip39": "^2.4.2",
"@types/pbkdf2": "^3.0.0",
"@types/secp256k1": "^3.5.0",
"@types/webassembly-js-api": "^0.0.2",
"@types/xxhashjs": "^0.2.1",
"bip39": "^2.5.0",
"blakejs": "^1.1.0",
"js-sha3": "^0.8.0",
"secp256k1": "^3.6.2",
"tweetnacl": "^1.0.1",
"xxhashjs": "^0.2.2"
}
}
@@ -0,0 +1,46 @@
// 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 { hexToU8a } from '@plugnet/util';
import { waitReady } from '@plugnet/wasm-crypto';
import { blake2AsHex } from '.';
describe('blake2AsHex', () => {
beforeEach(async () => {
await waitReady();
});
it('returns a 64-bit value (specified)', () => {
expect(
blake2AsHex('abc', 64)
).toEqual('0xd8bb14d833d59559');
});
it('returns a 128-bit value (as specified)', () => {
expect(
blake2AsHex('abc', 128)
).toEqual('0xcf4ab791c62b8d2b2109c90275287816');
});
it('returns a 256-bit value (default)', () => {
expect(
blake2AsHex('abc')
).toEqual('0xbddd813c634239723171ef3fee98579b94964e3bb1cb3e427262c8c068d52319');
});
it('returns a 512-bit value (as specified)', () => {
expect(
blake2AsHex('abc', 512)
).toEqual('0xba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923');
});
it('matches with the Rust implementation', () => {
expect(
blake2AsHex(
hexToU8a('0x454545454545454545454545454545454545454545454545454545454545454501000000000000002481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29dbdbf025dd4a69a6f4ee6e1577b251b655097e298b692cb34c18d3182cac3de0dc00000000'), 256
)
).toEqual('0x1025e5db74fdaf4d2818822dccf0e1604ae9ccc62f26cecfde23448ff0248abf');
});
});
+27
View File
@@ -0,0 +1,27 @@
// 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 { u8aToHex } from '@plugnet/util';
import blake2AsU8a from './asU8a';
/**
* @name blake2AsHex
* @summary Creates a blake2b hex from the input.
* @description
* From a `Uint8Array` input, create the blake2b and return the result as a hex string with the specified `bitLength`.
* @example
* <BR>
*
* ```javascript
* import { blake2AsHex } from '@plugnet/util-crypto';
*
* blake2AsHex('abc'); // => 0xba80a53f981c4d0d
* ```
*/
export default function blake2AsHex (data: Uint8Array | string, bitLength: number = 256): string {
return u8aToHex(
blake2AsU8a(data, bitLength)
);
}
@@ -0,0 +1,46 @@
// 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 { hexToU8a } from '@plugnet/util';
import { waitReady } from '@plugnet/wasm-crypto';
import { blake2AsU8a } from '.';
describe('blake2AsU8a', () => {
beforeEach(async () => {
await waitReady();
});
it('returns a 64-bit value by default', () => {
expect(
blake2AsU8a('abc')
).toEqual(
new Uint8Array([189, 221, 129, 60, 99, 66, 57, 114, 49, 113, 239, 63, 238, 152, 87, 155, 148, 150, 78, 59, 177, 203, 62, 66, 114, 98, 200, 192, 104, 213, 35, 25])
);
});
it('returns a 128-bit value (as specified)', () => {
expect(
blake2AsU8a('abc', 128)
).toEqual(
new Uint8Array([207, 74, 183, 145, 198, 43, 141, 43, 33, 9, 201, 2, 117, 40, 120, 22])
);
});
it('returns a 256-bit value (as specified)', () => {
expect(
blake2AsU8a('abc', 256)
).toEqual(
new Uint8Array([189, 221, 129, 60, 99, 66, 57, 114, 49, 113, 239, 63, 238, 152, 87, 155, 148, 150, 78, 59, 177, 203, 62, 66, 114, 98, 200, 192, 104, 213, 35, 25])
);
});
it('returns a 512-bit value (as specified)', () => {
expect(
blake2AsU8a('abc', 512)
).toEqual(
hexToU8a('0xba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923')
);
});
});
+29
View File
@@ -0,0 +1,29 @@
// 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 blakejs from 'blakejs';
import { u8aToU8a } from '@plugnet/util';
import { blake2b, isReady } from '@plugnet/wasm-crypto';
/**
* @name blake2AsU8a
* @summary Creates a blake2b u8a from the input.
* @description
* From a `Uint8Array` input, create the blake2b and return the result as a u8a with the specified `bitLength`.
* @example
* <BR>
*
* ```javascript
* import { blake2AsU8a } from '@plugnet/util-crypto';
*
* blake2AsU8a('abc'); // => [0xba, 0x80, 0xa53, 0xf98, 0x1c, 0x4d, 0x0d]
* ```
*/
export default function blake2AsU8a (data: Uint8Array | string, bitLength: number = 256, key: Uint8Array | null = null): Uint8Array {
const byteLength = Math.ceil(bitLength / 8);
return isReady()
? blake2b(u8aToU8a(data), u8aToU8a(key), byteLength)
: blakejs.blake2b(data, key, byteLength);
}
+10
View File
@@ -0,0 +1,10 @@
// 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 blake2b values with specified bitlengths
*/
export { default as blake2AsHex } from './asHex';
export { default as blake2AsU8a } from './asU8a';
+34
View File
@@ -0,0 +1,34 @@
// 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 './polyfill';
import wasmCrypto from '@plugnet/wasm-crypto';
export * from './blake2';
export * from './keccak';
export * from './key';
export * from './mnemonic';
export * from './nacl';
export * from './random';
export * from './schnorrkel';
export * from './secp256k1';
export * from './sha512';
export * from './xxhash';
export function cryptoWaitReady (): Promise<boolean> {
return wasmCrypto
.waitReady()
.then(() => true)
.catch((error) => {
console.error('Unable to initialize @polkadot/util-crypto', error);
return false;
});
}
// start init process immediately
cryptoWaitReady().catch(() => {
// shouldn't happen, logged above
});
@@ -0,0 +1,22 @@
// 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 { waitReady } from '@plugnet/wasm-crypto';
import { keccakAsHex } from '.';
const value = 'test value';
const result = '2d07364b5c231c56ce63d49430e085ea3033c750688ba532b24029124c26ca5e';
describe('keccakAsHex', () => {
beforeEach(async () => {
await waitReady();
});
it('returns a prefixed hex representation', () => {
expect(
keccakAsHex(value)
).toEqual(`0x${result}`);
});
});
+27
View File
@@ -0,0 +1,27 @@
// 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 { u8aToHex } from '@plugnet/util';
import keccakAsU8a from './asU8a';
/**
* @name keccakAsHex
* @summary Creates a keccak hex string from the input.
* @description
* From either a `string` or a `Buffer` input, create the keccak and return the result as a `0x` prefixed hex string.
* @example
* <BR>
*
* ```javascript
* import { keccakAsHex } from '@plugnet/util-crypto';
*
* keccakAsHex('123'); // => 0x...
* ```
*/
export default function keccakAsHex (value: Buffer | Uint8Array | string): string {
return u8aToHex(
keccakAsU8a(value)
);
}
@@ -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 { hexToU8a, stringToU8a } from '@plugnet/util';
import { waitReady } from '@plugnet/wasm-crypto';
import { keccakAsU8a } from '.';
describe('keccakAsU8a', () => {
beforeEach(async () => {
await waitReady();
});
const input = 'test value';
const output = hexToU8a(
'0x2d07364b5c231c56ce63d49430e085ea3033c750688ba532b24029124c26ca5e'
);
it('returns an hex representation (string)', () => {
expect(
keccakAsU8a(input)
).toEqual(output);
});
it('returns an hex representation (Buffer)', () => {
expect(
keccakAsU8a(
Buffer.from(input)
)
).toEqual(output);
});
it('returns an hex representation (Uint8Array)', () => {
expect(
keccakAsU8a(
stringToU8a(input)
)
).toEqual(output);
});
});
+29
View File
@@ -0,0 +1,29 @@
// 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 jssha3 from 'js-sha3';
import { u8aToU8a } from '@plugnet/util';
import { isReady, keccak256 } from '@plugnet/wasm-crypto';
/**
* @name keccakAsU8a
* @summary Creates a keccak Uint8Array from the input.
* @description
* From either a `string` or a `Buffer` input, create the keccak and return the result as a `Uint8Array`.
* @example
* <BR>
*
* ```javascript
* import { keccakAsU8a } from '@plugnet/util-crypto';
*
* keccakAsU8a('123'); // => Uint8Array
* ```
*/
export default function keccakAsU8a (value: Buffer | Uint8Array | string): Uint8Array {
return isReady()
? keccak256(u8aToU8a(value))
: new Uint8Array(
jssha3.keccak256.update(value).arrayBuffer()
);
}
+10
View File
@@ -0,0 +1,10 @@
// 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 Keccak256 values as hex & Uint8Array output
*/
export { default as keccakAsHex } from './asHex';
export { default as keccakAsU8a } from './asU8a';
@@ -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 '@plugnet/util';
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;
}
}
@@ -0,0 +1,53 @@
// 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 keyExtractPath from './extractPath';
describe('keyExtractPath', () => {
it('extracts properly from soft', () => {
expect(
keyExtractPath('/1')
).toEqual({
parts: ['/1'],
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]) }
]
});
});
it('extracts properly from hard', () => {
expect(
keyExtractPath('//1')
).toEqual({
parts: ['//1'],
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]) }
]
});
});
it('extracts properly from hard/soft', () => {
expect(
keyExtractPath('//1/2')
).toEqual({
parts: ['//1', '/2'],
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([2, 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]) }
]
});
});
it('does not extract from invalid paths', () => {
expect(
() => keyExtractPath('1/2')
).toThrow(/does not match input/);
});
it('does not extract from invalid paths', () => {
expect(
() => keyExtractPath('hello')
).toThrow(/does not match input/);
});
});
@@ -0,0 +1,37 @@
// 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 DeriveJunction from './DeriveJunction';
import { assert } from '@plugnet/util';
const RE_JUNCTION = /\/(\/?)([^\/]+)/g;
type ExtractResult = {
parts: null | Array<string>,
path: Array<DeriveJunction>
};
/**
* @description Extract derivation juntions from the supplied path
*/
export default function keyExtractPath (derivePath: string): ExtractResult {
const parts = derivePath.match(RE_JUNCTION);
const path: Array<DeriveJunction> = [];
let constructed = '';
if (parts) {
constructed = parts.join('');
parts.forEach((value: string) => {
path.push(DeriveJunction.from(value.substr(1)));
});
}
assert(constructed === derivePath, `Re-constructed path "${constructed}" does not match input`);
return {
parts,
path
};
}
@@ -0,0 +1,137 @@
// 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 keyExtractSuri from './extractSuri';
describe('keyExtractSuri', () => {
it('does not extract from invalid suri', () => {
expect(
() => keyExtractSuri('//2')
).toThrow(/to a secret URI/);
});
it('derives on "hello world"', () => {
expect(
keyExtractSuri('hello world')
).toEqual({
path: [],
phrase: 'hello world'
});
});
it('derives on "hello world/1', () => {
expect(
keyExtractSuri('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(
keyExtractSuri('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(
keyExtractSuri('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(
keyExtractSuri('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(
keyExtractSuri('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(
keyExtractSuri('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(
keyExtractSuri('hello world///password')
).toEqual({
password: 'password',
path: [],
phrase: 'hello world'
});
});
it('derives on "hello world//1/DOT///password"', () => {
expect(
keyExtractSuri('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(
keyExtractSuri('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(
keyExtractSuri('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'
});
});
});
@@ -0,0 +1,34 @@
// 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 '@plugnet/util';
import DeriveJunction from './DeriveJunction';
import keyExtractPath from './extractPath';
type ExtractResult = {
password?: string,
path: Array<DeriveJunction>,
phrase: string
};
const RE_CAPTURE = /^(\w+( \w+)*)((\/\/?[^\/]+)*)(\/\/\/(.*))?$/;
/**
* @description Extracts the phrase, path and password from a SURI format for specifying secret keys `<secret>/<soft-key>//<hard-key>///<password>` (the `///password` may be omitted, and `/<soft-key>` and `//<hard-key>` maybe repeated and mixed).
*/
export default function keyExtract (suri: string): ExtractResult {
const matches = suri.match(RE_CAPTURE);
assert(!isNull(matches), `Unable to match '${suri}' to a secret URI`);
const [, phrase, , derivePath, , , password] = matches as Array<string>;
const { path } = keyExtractPath(derivePath);
return {
password,
path,
phrase
};
}
+19
View File
@@ -0,0 +1,19 @@
// 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, Keypair } from '../types';
import DeriveJunction from './DeriveJunction';
import keyHdkdEd15519 from './hdkdEd25519';
import keyHdkdSr15519 from './hdkdSr25519';
export default function keyFromPath (pair: Keypair, path: Array<DeriveJunction>, type: KeypairType): Keypair {
const isEd25519 = type === 'ed25519';
return path.reduce((pair, junction) => {
return isEd25519
? keyHdkdEd15519(pair, junction)
: keyHdkdSr15519(pair, junction);
}, pair);
}
@@ -0,0 +1,19 @@
// 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 { Keypair } from '../types';
import { assert } from '@plugnet/util';
import naclDeriveHard from '../nacl/deriveHard';
import naclKeypairFromSeed from '../nacl/keypair/fromSeed';
import DeriveJunction from './DeriveJunction';
export default function keyHdkdEd25519 (keypair: Keypair, { chainCode, isHard }: DeriveJunction): Keypair {
assert(isHard, 'A soft key was found in the path (and is unsupported)');
return naclKeypairFromSeed(
naclDeriveHard(keypair.secretKey.subarray(0, 32), chainCode)
);
}
@@ -0,0 +1,15 @@
// 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 { Keypair } from '../types';
import schnorrkelDeriveHard from '../schnorrkel/deriveHard';
import schnorrkelDeriveSoft from '../schnorrkel/deriveSoft';
import DeriveJunction from './DeriveJunction';
export default function keyHdkdSr25519 (keypair: Keypair, { chainCode, isSoft }: DeriveJunction): Keypair {
return isSoft
? schnorrkelDeriveSoft(keypair, chainCode)
: schnorrkelDeriveHard(keypair, chainCode);
}
+12
View File
@@ -0,0 +1,12 @@
// 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 keyExtractPath } from './extractPath';
export { default as keyExtractSuri } from './extractSuri';
export { default as keyFromPath } from './fromPath';
export { default as keyHdkdEd25519 } from './hdkdEd25519';
export { default as keyHdkdSr25519 } from './hdkdEd25519';
@@ -0,0 +1,35 @@
// 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 generate from './generate';
import validate from './validate';
import { cryptoWaitReady } from '..';
describe('mnemonicGenerate', () => {
beforeEach(async () => {
await cryptoWaitReady();
});
it('generates a valid mnemonic (default strength)', () => {
const mnemonic = generate();
console.error(mnemonic);
expect(
validate(mnemonic)
).toEqual(true);
});
[12, 15, 18, 21, 24].forEach((num) => {
it(`generates a valid mnemonic (${num} words)`, () => {
const mnemonic = generate(num as any);
const isValid = validate(mnemonic);
console.error(mnemonic);
expect(mnemonic.split(' ')).toHaveLength(num);
expect(isValid).toEqual(true);
});
});
});
@@ -0,0 +1,37 @@
// 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 '../polyfill';
import { generateMnemonic } from 'bip39';
import { bip39Generate, isReady } from '@plugnet/wasm-crypto';
type WordCount = 12 | 15 | 18 | 21 | 24;
// mapping of words to the actual strength (as expected)
const STRENGTH_MAP = {
12: 16 * 8,
15: 20 * 8,
18: 24 * 8,
21: 28 * 8,
24: 32 * 8
};
/**
* @name mnemonicGenerate
* @summary Creates a valid mnemonic string using using [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki).
* @example
* <BR>
*
* ```javascript
* import { mnemonicGenerate } from '@plugnet/util-crypto';
*
* const mnemonic = mnemonicGenerate(); // => string
* ```
*/
export default function mnemonicGenerate (numWords: WordCount = 12): string {
return isReady()
? bip39Generate(numWords)
: generateMnemonic(STRENGTH_MAP[numWords]);
}
@@ -0,0 +1,15 @@
// 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 '../polyfill';
/**
* @summary Create valid mnemonic strings, validate them using BIP39, and convert them to valid seeds
*/
export { default as mnemonicGenerate } from './generate';
export { default as mnemonicToEntropy } from './toEntropy';
export { default as mnemonicToMiniSecret } from './toMiniSecret';
export { default as mnemonicToSeed } from './toSeed';
export { default as mnemonicValidate } from './validate';
@@ -0,0 +1,21 @@
// 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 { u8aToHex } from '@plugnet/util';
import toEntropy from './toEntropy';
import tests from '../schnorrkel/keypair/testing';
import { cryptoWaitReady } from '..';
describe('mnemonicToEntropy', () => {
beforeEach(async () => {
await cryptoWaitReady();
});
tests.forEach(([mnemonic, entropy], index) => {
it(`Created correct entropy for ${index}`, () => {
expect(u8aToHex(toEntropy(mnemonic))).toEqual(entropy);
});
});
});
@@ -0,0 +1,19 @@
// 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 '../polyfill';
import { mnemonicToEntropy } from 'bip39';
import { hexAddPrefix, hexToU8a } from '@plugnet/util';
import { bip39ToEntropy, isReady } from '@plugnet/wasm-crypto';
export default function toEntropy (mnemonic: string): Uint8Array {
return isReady()
? bip39ToEntropy(mnemonic)
: hexToU8a(
hexAddPrefix(
mnemonicToEntropy(mnemonic)
)
);
}
@@ -0,0 +1,32 @@
// 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 { u8aToHex } from '@plugnet/util';
import mnemonicToMiniSecret from './toMiniSecret';
import tests from '../schnorrkel/keypair/testing';
import { cryptoWaitReady } from '..';
describe('mnemonicToMiniSecret', () => {
beforeEach(async () => {
await cryptoWaitReady();
});
it('generates a valid seed', () => {
expect(
u8aToHex(mnemonicToMiniSecret('seed sock milk update focus rotate barely fade car face mechanic mercy'))
).toEqual('0x4d1ab2a57929edfd018aaa974e62ed557e3f54b4104acabedf73c8f5a1dbb029');
});
tests.forEach(([mnemonic, , seed], index) => {
it(`Created correct seed for ${index}`, () => {
expect(
u8aToHex(mnemonicToMiniSecret(mnemonic, 'Substrate'))
).toEqual(
// mini returned here, only check first 32-bytes (64 hex + 2 prefix)
seed.substr(0, 66)
);
});
});
});
@@ -0,0 +1,25 @@
// 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 '../polyfill';
import { pbkdf2Sync } from 'pbkdf2';
import { bufferToU8a, stringToU8a, u8aToBuffer } from '@plugnet/util';
import { bip39ToMiniSecret, isReady } from '@plugnet/wasm-crypto';
import toEntropy from './toEntropy';
export default function toMiniSecret (mnemonic: string, password: string = ''): Uint8Array {
if (isReady()) {
return bip39ToMiniSecret(mnemonic, password);
}
const entropy = u8aToBuffer(toEntropy(mnemonic));
const salt = u8aToBuffer(stringToU8a(`mnemonic${password}`));
// return the first 32 bytes as the seed
return bufferToU8a(
pbkdf2Sync(entropy, salt, 2048, 64, 'sha512')
).slice(0, 32);
}
@@ -0,0 +1,15 @@
// 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 { u8aToHex } from '@plugnet/util';
import toSeed from './toSeed';
describe('mnemonicToSeed', () => {
it('generates a valid seed', () => {
expect(
u8aToHex(toSeed('seed sock milk update focus rotate barely fade car face mechanic mercy'))
).toEqual('0x3c121e20de068083b49c2315697fb59a2d9e8643c24e5ea7628132c58969a027');
});
});
@@ -0,0 +1,30 @@
// 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 { mnemonicToSeed } from 'bip39';
import { bufferToU8a } from '@plugnet/util';
import { bip39ToSeed, isReady } from '@plugnet/wasm-crypto';
/**
* @name toSeed
* @summary Creates a valid seed from a mnemonic input
* @example
* <BR>
*
* ```javascript
* import { mnemonicGenerate, mnemonicToSeed, mnemonicValidate } from '@plugnet/util-crypto';
*
* const mnemonic = mnemonicGenerate(); // => string
* const isValidMnemonic = mnemonicValidate(mnemonic); // => boolean
*
* if (isValidMnemonic) {
* console.log(`Seed generated from mnemonic: ${mnemonicToSeed(mnemonic)}`); => u8a
* }
* ```
*/
export default function toSeed (mnemonic: string, password: string = ''): Uint8Array {
return isReady()
? bip39ToSeed(mnemonic, password)
: bufferToU8a(mnemonicToSeed(mnemonic, password)).subarray(0, 32);
}
@@ -0,0 +1,24 @@
// 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 validate from './validate';
import { cryptoWaitReady } from '..';
describe('mnemonicValidate', () => {
beforeEach(async () => {
await cryptoWaitReady();
});
it('returns true on valid', () => {
expect(
validate('seed sock milk update focus rotate barely fade car face mechanic mercy')
).toEqual(true);
});
it('returns false on invalid', () => {
expect(
validate('wine photo extra cushion basket dwarf humor cloud truck job boat submit')
).toEqual(false);
});
});
@@ -0,0 +1,27 @@
// 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 '../polyfill';
import { validateMnemonic } from 'bip39';
import { bip39Validate, isReady } from '@plugnet/wasm-crypto';
/**
* @name mnemonicValidate
* @summary Validates a mnemonic input using [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki).
* @example
* <BR>
*
* ```javascript
* import { mnemonicGenerate, mnemonicValidate } from '@plugnet/util-crypto';
*
* const mnemonic = mnemonicGenerate(); // => string
* const isValidMnemonic = mnemonicValidate(mnemonic); // => boolean
* ```
*/
export default function mnemonicValidate (mnemonic: string): boolean {
return isReady()
? bip39Validate(mnemonic)
: validateMnemonic(mnemonic);
}
@@ -0,0 +1,25 @@
// 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 { naclDecrypt, naclEncrypt } from '.';
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, nonce, secret)
).toEqual(
message
);
});
it('returns null on invalid', () => {
expect(
naclDecrypt(new Uint8Array(), new Uint8Array(24), new Uint8Array(32))
).toEqual(null);
});
});
+23
View File
@@ -0,0 +1,23 @@
// 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 nacl from 'tweetnacl';
/**
* @name naclDecrypt
* @summary Decrypts a message using the supplied secretKey and nonce
* @description
* Returns an decrypted message, using the `secret` and `nonce`.
* @example
* <BR>
*
* ```javascript
* import { naclDecrypt } from '@plugnet/util-crypto';
*
* naclDecrypt([...], [...], [...]); // => [...]
* ```
*/
export default function naclDecrypt (encrypted: Uint8Array, nonce: Uint8Array, secret: Uint8Array): Uint8Array | null {
return nacl.secretbox.open(encrypted, nonce, secret) || null;
}
@@ -0,0 +1,15 @@
// 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 { compactAddLength, stringToU8a, u8aConcat } from '@plugnet/util';
import blake2AsU8a from '../blake2/asU8a';
const HDKD = compactAddLength(stringToU8a('Ed25519HDKD'));
export default function deriveHard (seed: Uint8Array, chainCode: Uint8Array): Uint8Array {
return blake2AsU8a(
u8aConcat(HDKD, seed, chainCode)
);
}
@@ -0,0 +1,19 @@
// 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 { naclEncrypt } from '.';
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)
});
});
});
+33
View File
@@ -0,0 +1,33 @@
// 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 nacl from 'tweetnacl';
import randomAsU8a from '../random/asU8a';
type Encrypted = {
encrypted: Uint8Array,
nonce: Uint8Array
};
/**
* @name naclEncrypt
* @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
* <BR>
*
* ```javascript
* import { naclEncrypt } from '@plugnet/util-crypto';
*
* naclEncrypt([...], [...]); // => [...]
* ```
*/
export default function naclEncrypt (message: Uint8Array, secret: Uint8Array, nonce: Uint8Array = randomAsU8a(24)): Encrypted {
return {
encrypted: nacl.secretbox(message, nonce, secret),
nonce
};
}
+16
View File
@@ -0,0 +1,16 @@
// 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 Implements [NaCl](http://nacl.cr.yp.to/) secret-key authenticated encryption, public-key authenticated encryption, hashing, and public-key signatures
*/
export { default as naclDecrypt } from './decrypt';
export { default as deriveHard } from './deriveHard';
export { default as naclEncrypt } from './encrypt';
export { default as naclKeypairFromRandom } from './keypair/fromRandom';
export { default as naclKeypairFromSecret } from './keypair/fromSecret';
export { default as naclKeypairFromSeed } from './keypair/fromSeed';
export { default as naclKeypairFromString } from './keypair/fromString';
export { default as naclSign } from './sign';
export { default as naclVerify } from './verify';
@@ -0,0 +1,27 @@
// 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 { Keypair } from '../../types';
import { naclKeypairFromRandom } from '..';
describe('naclKeypairFromRandom', () => {
let keypair: Keypair;
beforeEach(() => {
keypair = naclKeypairFromRandom();
});
it('generates a valid publicKey', () => {
expect(
keypair.publicKey
).toHaveLength(32);
});
it('generates a valid secretKey', () => {
expect(
keypair.secretKey
).toHaveLength(64);
});
});
@@ -0,0 +1,25 @@
// 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 { Keypair } from '../../types';
import nacl from 'tweetnacl';
/**
* @name naclKeypairFromRandom
* @summary Creates a new public/secret keypair.
* @description
* Returns a new generate object containing a `publicKey` & `secretKey`.
* @example
* <BR>
*
* ```javascript
* import { naclKeypairFromRandom } from '@plugnet/util-crypto';
*
* naclKeypairFromRandom(); // => { secretKey: [...], publicKey: [...] }
* ```
*/
export default function naclKeypairFromRandom (): Keypair {
return nacl.sign.keyPair();
}
@@ -0,0 +1,32 @@
// 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 { naclKeypairFromSecret } from '..';
describe('naclKeypairFromSecret', () => {
const secretKey = new Uint8Array([
18, 52, 86, 120, 144, 18, 52, 86,
120, 144, 18, 52, 86, 120, 144, 18,
18, 52, 86, 120, 144, 18, 52, 86,
120, 144, 18, 52, 86, 120, 144, 18,
180, 114, 93, 155, 165, 255, 217, 82,
16, 250, 209, 11, 193, 10, 88, 218,
190, 190, 41, 193, 236, 252, 1, 152,
216, 214, 0, 41, 45, 138, 13, 53
]);
it('generates a valid publicKey/secretKey pair', () => {
expect(
naclKeypairFromSecret(secretKey)
).toEqual({
publicKey: new Uint8Array([
180, 114, 93, 155, 165, 255, 217, 82,
16, 250, 209, 11, 193, 10, 88, 218,
190, 190, 41, 193, 236, 252, 1, 152,
216, 214, 0, 41, 45, 138, 13, 53
]),
secretKey
});
});
});
@@ -0,0 +1,25 @@
// 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 { Keypair } from '../../types';
import nacl from 'tweetnacl';
/**
* @name naclKeypairFromSecret
* @summary Creates a new public/secret keypair from a secret.
* @description
* Returns a object containing a `publicKey` & `secretKey` generated from the supplied secret.
* @example
* <BR>
*
* ```javascript
* import { naclKeypairFromSecret } from '@plugnet/util-crypto';
*
* naclKeypairFromSecret(...); // => { secretKey: [...], publicKey: [...] }
* ```
*/
export default function naclKeypairFromSecret (secret: Uint8Array): Keypair {
return nacl.sign.keyPair.fromSecretKey(secret);
}
@@ -0,0 +1,39 @@
// 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 } from '@plugnet/util';
import { waitReady } from '@plugnet/wasm-crypto';
import { naclKeypairFromSeed } from '..';
describe('naclKeypairFromSeed', () => {
// NOTE: Aligned with Rust test, b"12345678901234567890123456789012"
const TEST = stringToU8a('12345678901234567890123456789012');
const RESULT = {
publicKey: new Uint8Array([
0x2f, 0x8c, 0x61, 0x29, 0xd8, 0x16, 0xcf, 0x51,
0xc3, 0x74, 0xbc, 0x7f, 0x08, 0xc3, 0xe6, 0x3e,
0xd1, 0x56, 0xcf, 0x78, 0xae, 0xfb, 0x4a, 0x65,
0x50, 0xd9, 0x7b, 0x87, 0x99, 0x79, 0x77, 0xee
]),
secretKey: new Uint8Array([
49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50,
// public part
0x2f, 0x8c, 0x61, 0x29, 0xd8, 0x16, 0xcf, 0x51,
0xc3, 0x74, 0xbc, 0x7f, 0x08, 0xc3, 0xe6, 0x3e,
0xd1, 0x56, 0xcf, 0x78, 0xae, 0xfb, 0x4a, 0x65,
0x50, 0xd9, 0x7b, 0x87, 0x99, 0x79, 0x77, 0xee
])
};
beforeEach(async () => {
await waitReady();
});
it('generates a valid publicKey/secretKey pair (u8a)', () => {
expect(
naclKeypairFromSeed(TEST)
).toEqual(RESULT);
});
});
@@ -0,0 +1,35 @@
// 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 { Keypair } from '../../types';
import nacl from 'tweetnacl';
import { isReady, ed25519KeypairFromSeed } from '@plugnet/wasm-crypto';
/**
* @name naclKeypairFromSeed
* @summary Creates a new public/secret keypair from a seed.
* @description
* Returns a object containing a `publicKey` & `secretKey` generated from the supplied seed.
* @example
* <BR>
*
* ```javascript
* import { naclKeypairFromSeed } from '@plugnet/util-crypto';
*
* naclKeypairFromSeed(...); // => { secretKey: [...], publicKey: [...] }
* ```
*/
export default function naclKeypairFromSeed (seed: Uint8Array): Keypair {
if (isReady()) {
const full = ed25519KeypairFromSeed(seed);
return {
publicKey: full.slice(32),
secretKey: full.slice(0, 64)
};
}
return nacl.sign.keyPair.fromSeed(seed);
}
@@ -0,0 +1,16 @@
// 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 { naclKeypairFromString } from '..';
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])
});
});
});
@@ -0,0 +1,33 @@
// 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 { Keypair } from '../../types';
import { stringToU8a } from '@plugnet/util';
import blake2AsU8a from '../../blake2/asU8a';
import fromSeed from './fromSeed';
/**
* @name naclKeypairFromString
* @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
* <BR>
*
* ```javascript
* import { naclKeypairFromString } from '@plugnet/util-crypto';
*
* naclKeypairFromString('test'); // => { secretKey: [...], publicKey: [...] }
* ```
*/
export default function naclKeypairFromString (value: string): Keypair {
return fromSeed(
blake2AsU8a(
stringToU8a(value),
256
)
);
}
@@ -0,0 +1,27 @@
// 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 } from '@plugnet/util';
import { waitReady } from '@plugnet/wasm-crypto';
import { naclSign, naclKeypairFromSeed } from '.';
describe('naclSign', () => {
beforeEach(async () => {
await waitReady();
});
it('returns a valid signature for the message', () => {
expect(
naclSign(
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
naclKeypairFromSeed(
stringToU8a('12345678901234567890123456789012')
)
)
).toEqual(
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])
);
});
});
+31
View File
@@ -0,0 +1,31 @@
// 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 { Keypair } from '../types';
import nacl from 'tweetnacl';
import { assert } from '@plugnet/util';
import { isReady, ed25519Sign } from '@plugnet/wasm-crypto';
/**
* @name naclSign
* @summary Signs a message using the supplied secretKey
* @description
* Returns message signature of `message`, using the `secretKey`.
* @example
* <BR>
*
* ```javascript
* import { naclSign } from '@plugnet/util-crypto';
*
* naclSign([...], [...]); // => [...]
* ```
*/
export default function naclSign (message: Uint8Array, { publicKey, secretKey }: Partial<Keypair>): Uint8Array {
assert(secretKey, 'Expected valid secretKey');
return isReady()
? ed25519Sign(publicKey as Uint8Array, (secretKey as Uint8Array).subarray(0, 32), message)
: nacl.sign.detached(message, secretKey as Uint8Array);
}
@@ -0,0 +1,54 @@
// 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 } from '@plugnet/util';
import { waitReady } from '@plugnet/wasm-crypto';
import { naclVerify, naclKeypairFromSeed } from '.';
describe('naclSign', () => {
let publicKey: Uint8Array;
let signature: Uint8Array;
beforeEach(async () => {
await waitReady();
publicKey = naclKeypairFromSeed(
stringToU8a('12345678901234567890123456789012')
).publicKey;
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('validates a correctly signed message', () => {
expect(
naclVerify(
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
signature,
publicKey
)
).toEqual(true);
});
it('fails a correctly signed message (message changed)', () => {
expect(
naclVerify(
new Uint8Array([0x61, 0x62, 0x63, 0x64, 0x65]),
signature,
publicKey
)
).toEqual(false);
});
it('fails a correctly signed message (signature changed)', () => {
signature[0] = 0xff;
expect(
naclVerify(
new Uint8Array([0x61, 0x62, 0x63, 0x64]),
signature,
publicKey
)
).toEqual(false);
});
});
+26
View File
@@ -0,0 +1,26 @@
// 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 nacl from 'tweetnacl';
import { isReady, ed25519Verify } from '@plugnet/wasm-crypto';
/**
* @name naclSign
* @summary Verifies the signature on the supplied message.
* @description
* Verifies the `signature` on `message` with the supplied `plublicKey`. Returns `true` on sucess, `false` otherwise.
* @example
* <BR>
*
* ```javascript
* import { naclVerify } from '@plugnet/util-crypto';
*
* naclVerify([...], [...], [...]); // => true/false
* ```
*/
export default function naclVerify (message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean {
return isReady()
? ed25519Verify(signature, message, publicKey)
: nacl.sign.detached.verify(message, signature, publicKey);
}
+5
View File
@@ -0,0 +1,5 @@
// 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 '@polkadot/wasm-crypto/crypto-polyfill';
@@ -0,0 +1,37 @@
// 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 { isHex } from '@plugnet/util';
import { randomAsHex } from '.';
describe('randomAsBuffer', () => {
it('generated results does not match', () => {
expect(
randomAsHex()
).not.toEqual(
randomAsHex()
);
});
it('is a valid hex number', () => {
expect(
isHex(
randomAsHex()
)
).toEqual(true);
});
it('generates 32 bytes by default', () => {
expect(
randomAsHex()
).toHaveLength(32 * 2 + 2);
});
it('generates with the supplied length', () => {
expect(
randomAsHex(66)
).toHaveLength(66 * 2 + 2);
});
});
+27
View File
@@ -0,0 +1,27 @@
// 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 { u8aToHex } from '@plugnet/util';
import randomAsU8a from './asU8a';
/**
* @name randomAsHex
* @summary Creates a hex string filled with random bytes.
* @description
* Returns a hex string with the specified (optional) length filled with random bytes.
* @example
* <BR>
*
* ```javascript
* import { randomAsHex } from '@plugnet/util-crypto';
*
* randomAsHex(); // => 0x...
* ```
*/
export default function randomAsHex (length: number = 32): string {
return u8aToHex(
randomAsU8a(length)
);
}
@@ -0,0 +1,15 @@
// 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 { randomAsNumber } from '.';
describe('randomAsNumber', () => {
it('generates subsequent non-matching numbers', () => {
expect(
randomAsNumber()
).not.toEqual(
randomAsNumber()
);
});
});
@@ -0,0 +1,30 @@
// 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 { hexToBn } from '@plugnet/util';
import randomAsHex from './asHex';
const BN_53 = new BN(0b11111111111111111111111111111111111111111111111111111);
/**
* @name randomAsNumber
* @summary Creates a random number from random bytes.
* @description
* Returns a random number generated from the secure bytes.
* @example
* <BR>
*
* ```javascript
* import { randomAsNumber } from '@plugnet/util-crypto';
*
* randomAsNumber(); // => <random number>
* ```
*/
export default function randomAsNumber (): number {
return hexToBn(
randomAsHex(8)
).and(BN_53).toNumber();
}
@@ -0,0 +1,35 @@
// 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 { isU8a } from '@plugnet/util';
import { randomAsU8a } from '.';
describe('randomAsU8a', () => {
it('generates a Uint8Array', () => {
expect(
isU8a(randomAsU8a())
).toEqual(true);
});
it('generated results does not match', () => {
expect(
randomAsU8a()
).not.toEqual(
randomAsU8a()
);
});
it('generates 32 bytes by default', () => {
expect(
randomAsU8a()
).toHaveLength(32);
});
it('generates with the suuplied length', () => {
expect(
randomAsU8a(66)
).toHaveLength(66);
});
});
+23
View File
@@ -0,0 +1,23 @@
// 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 nacl from 'tweetnacl';
/**
* @name randomAsU8a
* @summary Creates a Uint8Array filled with random bytes.
* @description
* Returns a `Uint8Array` with the specified (optional) length filled with random bytes.
* @example
* <BR>
*
* ```javascript
* import { randomAsU8a } from '@plugnet/util-crypto';
*
* randomAsU8a(); // => Uint8Array([...])
* ```
*/
export default function randomAsU8a (length: number = 32): Uint8Array {
return nacl.randomBytes(length);
}
+11
View File
@@ -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 Returns a sequence of secure random bytes in a variety of formats
*/
export { default as randomAsHex } from './asHex';
export { default as randomAsNumber } from './asNumber';
export { default as randomAsU8a } from './asU8a';
@@ -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 { Keypair } from '../types';
import '../polyfill';
import { sr25519DeriveKeypairHard } from '@plugnet/wasm-crypto';
import keypairFromU8a from './keypair/fromU8a';
import keypairToU8a from './keypair/toU8a';
export default function deriveHard (keypair: Keypair, chainCode: Uint8Array): Keypair {
return keypairFromU8a(
sr25519DeriveKeypairHard(keypairToU8a(keypair), chainCode)
);
}
@@ -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 { Keypair } from '../types';
import '../polyfill';
import { sr25519DeriveKeypairSoft } from '@plugnet/wasm-crypto';
import keypairFromU8a from './keypair/fromU8a';
import keypairToU8a from './keypair/toU8a';
export default function deriveSoft (keypair: Keypair, chainCode: Uint8Array): Keypair {
return keypairFromU8a(
sr25519DeriveKeypairSoft(keypairToU8a(keypair), chainCode)
);
}
@@ -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.
import '../polyfill';
export { default as schnorrkelDeriveHard } from './deriveHard';
export { default as schnorrkelDeriveSoft } from './deriveSoft';
export { default as schnorrkelKeypairFromSeed } from './keypair/fromSeed';
export { default as schnorrkelSign } from './sign';
export { default as schnorrkelVerify } from './verify';
@@ -0,0 +1,39 @@
// 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, u8aToHex } from '@plugnet/util';
import { waitReady } from '@plugnet/wasm-crypto';
import { mnemonicToMiniSecret } from '../../mnemonic';
import { schnorrkelKeypairFromSeed } from '..';
import tests from './testing';
describe('schnorrkelKeypairFromSeed', () => {
const TEST = stringToU8a('12345678901234567890123456789012');
const RESULT = {
publicKey: new Uint8Array([116, 28, 8, 160, 111, 65, 197, 150, 96, 143, 103, 116, 37, 155, 217, 4, 51, 4, 173, 250, 93, 62, 234, 98, 118, 11, 217, 190, 151, 99, 77, 99]),
secretKey: new Uint8Array([240, 16, 102, 96, 195, 221, 162, 63, 22, 218, 169, 172, 91, 129, 27, 150, 48, 119, 245, 188, 10, 248, 159, 133, 128, 79, 13, 232, 228, 36, 240, 80, 249, 141, 102, 243, 148, 66, 80, 111, 249, 71, 253, 145, 31, 24, 199, 167, 165, 218, 99, 154, 99, 232, 211, 180, 226, 51, 247, 65, 67, 217, 81, 193])
};
beforeEach(async () => {
return waitReady();
});
it('generates a valid publicKey/secretKey pair (u8a)', () => {
expect(
schnorrkelKeypairFromSeed(TEST)
).toEqual(RESULT);
});
tests.forEach(([mnemonic, , , secret], index) => {
it(`creates valid against known (${index})`, () => {
const seed = mnemonicToMiniSecret(mnemonic, 'Substrate');
const pair = schnorrkelKeypairFromSeed(seed);
expect(
u8aToHex(pair.secretKey)
).toEqual(secret);
});
});
});
@@ -0,0 +1,21 @@
// 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 { Keypair } from '../../types';
import '../../polyfill';
import { sr25519KeypairFromSeed } from '@plugnet/wasm-crypto';
import keypairFromU8a from './fromU8a';
/**
* @name schnorrkelKeypairFromSeed
* @description Returns a object containing a `publicKey` & `secretKey` generated from the supplied seed.
*/
export default function schnorrkelKeypairFromSeed (seed: Uint8Array): Keypair {
return keypairFromU8a(
sr25519KeypairFromSeed(seed)
);
}
@@ -0,0 +1,15 @@
// 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 { Keypair } from '../../types';
const SEC_LEN = 64;
const PUB_LEN = 32;
export default function schnorrkelKeypairFromU8a (full: Uint8Array): Keypair {
return {
publicKey: full.slice(SEC_LEN, SEC_LEN + PUB_LEN),
secretKey: full.slice(0, SEC_LEN)
};
}
@@ -0,0 +1,155 @@
// 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.
// mnemonic, entropy, seed, secret (expanded)
type Test = [string, string, string, string];
const tests: Array<Test> = [
[
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
'0x00000000000000000000000000000000',
'0x44e9d125f037ac1d51f0a7d3649689d422c2af8b1ec8e00d71db4d7bf6d127e33f50c3d5c84fa3e5399c72d6cbbbbc4a49bf76f76d952f479d74655a2ef2d453',
'0xb0b3174fe43c15938bb0d0cc5b6f7ac7295f557ee1e6fdeb24fb73f4e0cb2b6ec40ffb9da4af6d411eae8e292750fd105ff70fe93f337b5b590f5a9d9030c750'
],
[
'legal winner thank year wave sausage worth useful legal winner thank yellow',
'0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f',
'0x4313249608fe8ac10fd5886c92c4579007272cb77c21551ee5b8d60b780416850f1e26c1f4b8d88ece681cb058ab66d6182bc2ce5a03181f7b74c27576b5c8bf',
'0x20666c9dd63c5b04a6a14377579af14aba60707752d134726304d0804992e26f9092c47fbb9e14c02fd53c702c8a3cfca4735638599da5c4362e0d0560dceb58'
],
[
'letter advice cage absurd amount doctor acoustic avoid letter advice cage above',
'0x80808080808080808080808080808080',
'0x27f3eb595928c60d5bc91a4d747da40ed236328183046892ed6cd5aa9ae38122acd1183adf09a89839acb1e6eaa7fb563cc958a3f9161248d5a036e0d0af533d',
'0x709e8254d0a9543c6b35b145dd23349e6369d487a1d10b0cfe09c05ff521f4691ad8bb8221339af38fc48510ec2dfc3104bb94d38f1fa241ceb252943df7b6b5'
],
[
'zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong',
'0xffffffffffffffffffffffffffffffff',
'0x227d6256fd4f9ccaf06c45eaa4b2345969640462bbb00c5f51f43cb43418c7a753265f9b1e0c0822c155a9cabc769413ecc14553e135fe140fc50b6722c6b9df',
'0x88206f4b4102ad30ee40b4b5943c5259db77fd576d95d79eeea00160197e406308821814dea9442675a5d3fa375b3bd65ffe92be43e07dbf6bb4ab84e9d4449d'
],
[
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent',
'0x000000000000000000000000000000000000000000000000',
'0x44e9d125f037ac1d51f0a7d3649689d422c2af8b1ec8e00d71db4d7bf6d127e33f50c3d5c84fa3e5399c72d6cbbbbc4a49bf76f76d952f479d74655a2ef2d453',
'0xb0b3174fe43c15938bb0d0cc5b6f7ac7295f557ee1e6fdeb24fb73f4e0cb2b6ec40ffb9da4af6d411eae8e292750fd105ff70fe93f337b5b590f5a9d9030c750'
],
[
'legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will',
'0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f',
'0xcb1d50e14101024a88905a098feb1553d4306d072d7460e167a60ccb3439a6817a0afc59060f45d999ddebc05308714733c9e1e84f30feccddd4ad6f95c8a445',
'0x50dcb74f223740d6a256000a2f1ccdb60044b39ce3aad71a3bd7761848d5f55d5a34f96e0b96ecb45d7a142e07ddfde734f9525f9f88310ab50e347da5789d3e'
],
[
'letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always',
'0x808080808080808080808080808080808080808080808080',
'0x9ddecf32ce6bee77f867f3c4bb842d1f0151826a145cb4489598fe71ac29e3551b724f01052d1bc3f6d9514d6df6aa6d0291cfdf997a5afdb7b6a614c88ab36a',
'0x88112947a30e864b511838b6daf6e1e13801ae003d6d9b73eb5892c355f7e37ab3bb71200092d004467b06fe67bc153ee4e2bb7af2f544815b0dde276d2dae75'
],
[
'zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when',
'0xffffffffffffffffffffffffffffffffffffffffffffffff',
'0x8971cb290e7117c64b63379c97ed3b5c6da488841bd9f95cdc2a5651ac89571e2c64d391d46e2475e8b043911885457cd23e99a28b5a18535fe53294dc8e1693',
'0x4859cdeda3f957b7ffcd2d59257c30e43996796f38e1be5c6136c9bf3744e047ce9a52c11793c98d0dc8caee927576ce46ef2e5f4b3f1d5e4b1344b2c31ebe8e'
],
[
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art',
'0x0000000000000000000000000000000000000000000000000000000000000000',
'0x44e9d125f037ac1d51f0a7d3649689d422c2af8b1ec8e00d71db4d7bf6d127e33f50c3d5c84fa3e5399c72d6cbbbbc4a49bf76f76d952f479d74655a2ef2d453',
'0xb0b3174fe43c15938bb0d0cc5b6f7ac7295f557ee1e6fdeb24fb73f4e0cb2b6ec40ffb9da4af6d411eae8e292750fd105ff70fe93f337b5b590f5a9d9030c750'
],
[
'legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title',
'0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f',
'0x3037276a5d05fcd7edf51869eb841bdde27c574dae01ac8cfb1ea476f6bea6ef57ab9afe14aea1df8a48f97ae25b37d7c8326e49289efb25af92ba5a25d09ed3',
'0xe8962ace15478f69fa42ddd004aad2c285c9f5a02e0712860e83fbec041f89489046aa57b21db2314d93aeb4a2d7cbdab21d4856e8e151894abd17fb04ae65e1'
],
[
'letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless',
'0x8080808080808080808080808080808080808080808080808080808080808080',
'0x2c9c6144a06ae5a855453d98c3dea470e2a8ffb78179c2e9eb15208ccca7d831c97ddafe844ab933131e6eb895f675ede2f4e39837bb5769d4e2bc11df58ac42',
'0x78667314bf1e52e38d29792cdf294efcaddadc4fa9ce48c5f2bef4daad7ed95d1db960d6f6f895c1a9d2a3ddcc0398ba6578580ea1f03f65ea9a68e97cf3f840'
],
[
'zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote',
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
'0x047e89ef7739cbfe30da0ad32eb1720d8f62441dd4f139b981b8e2d0bd412ed4eb14b89b5098c49db2301d4e7df4e89c21e53f345138e56a5e7d63fae21c5939',
'0xe09f4ae0d4e22f6c9bbc4251c880e73d93d10fdf7f152c393ce36e4e942b3155a6f4b48e6c6ebce902a10d4ab46ef59cd154c15aeb8f7fcd4e1e26342d40806d'
],
[
'ozone drill grab fiber curtain grace pudding thank cruise elder eight picnic',
'0x9e885d952ad362caeb4efe34a8e91bd2',
'0xf4956be6960bc145cdab782e649a5056598fd07cd3f32ceb73421c3da27833241324dc2c8b0a4d847eee457e6d4c5429f5e625ece22abaa6a976e82f1ec5531d',
'0xb0eb046f48eacb7ad6c4da3ff92bfc29c9ad471bae3e554d5d63e58827160c70c7e5165598761f96b5659ab28c474f50e89ee13c67e30bca40fdcf4335835649'
],
[
'gravity machine north sort system female filter attitude volume fold club stay feature office ecology stable narrow fog',
'0x6610b25967cdcca9d59875f5cb50b0ea75433311869e930b',
'0xfbcc5229ade0c0ff018cb7a329c5459f91876e4dde2a97ddf03c832eab7f26124366a543f1485479c31a9db0d421bda82d7e1fe562e57f3533cb1733b001d84d',
'0xd8da734285a13967647dd906288e1ac871e1945d0c6b72fa259de4051a9b75431be0c4eb40b1ca38c780f445e3e2809282b9efef4dcc3538355e68094f1e79fa'
],
[
'hamster diagram private dutch cause delay private meat slide toddler razor book happy fancy gospel tennis maple dilemma loan word shrug inflict delay length',
'0x68a79eaca2324873eacc50cb9c6eca8cc68ea5d936f98787c60c7ebc74e6ce7c',
'0x7c60c555126c297deddddd59f8cdcdc9e3608944455824dd604897984b5cc369cad749803bb36eb8b786b570c9cdc8db275dbe841486676a6adf389f3be3f076',
'0x883b72fa7fb06b6abd0fc2cdb0018b3578e086e93074256bbbb8c68e53c04a56391bc0d19d7b2fa22a8148ccbe191d969c4323faca1935a576cc1b24301f203a'
],
[
'scheme spot photo card baby mountain device kick cradle pact join borrow',
'0xc0ba5a8e914111210f2bd131f3d5e08d',
'0xc12157bf2506526c4bd1b79a056453b071361538e9e2c19c28ba2cfa39b5f23034b974e0164a1e8acd30f5b4c4de7d424fdb52c0116bfc6a965ba8205e6cc121',
'0x7039a64150089f8d43188af964c7b8e2b8c9ba20aede085baca5672e978a47576c7193c3e557f37cdeeee5e5131b854e4309efc55259b050474e1f0884a7a621'
],
[
'horn tenant knee talent sponsor spell gate clip pulse soap slush warm silver nephew swap uncle crack brave',
'0x6d9be1ee6ebd27a258115aad99b7317b9c8d28b6d76431c3',
'0x23766723e970e6b79dec4d5e4fdd627fd27d1ee026eb898feb9f653af01ad22080c6f306d1061656d01c4fe9a14c05f991d2c7d8af8730780de4f94cd99bd819',
'0xe07a1f3073edad5b63585cdf1d5e6f8e50e3145de550fc8eb1fb430cce62d76d251904272c5d25fd634615d413bb31a2bc7b5d6eeb2f6ddc68a2b95ac6bd49bc'
],
[
'panda eyebrow bullet gorilla call smoke muffin taste mesh discover soft ostrich alcohol speed nation flash devote level hobby quick inner drive ghost inside',
'0x9f6a2878b2520799a44ef18bc7df394e7061a224d2c33cd015b157d746869863',
'0xf4c83c86617cb014d35cd87d38b5ef1c5d5c3d58a73ab779114438a7b358f457e0462c92bddab5a406fe0e6b97c71905cf19f925f356bc673ceb0e49792f4340',
'0x607f8595266ac0d4aa91bf4fddbd2a868889317f40099979be9743c46c418976e6ff3717bd11b94b418f91c8b88eae142cecb19104820997ddf5a379dd9da5ae'
],
[
'cat swing flag economy stadium alone churn speed unique patch report train',
'0x23db8160a31d3e0dca3688ed941adbf3',
'0x719d4d4de0638a1705bf5237262458983da76933e718b2d64eb592c470f3c5d222e345cc795337bb3da393b94375ff4a56cfcd68d5ea25b577ee9384d35f4246',
'0xd078b66bb357f1f06e897a6fdfa2f3dfb0da05836ded1fd0793373068b7e854e783a548a6d194f142e1ba78bf42a49fa58e3673b363ba6f6494efffa28f168df'
],
[
'light rule cinnamon wrap drastic word pride squirrel upgrade then income fatal apart sustain crack supply proud access',
'0x8197a4a47f0425faeaa69deebc05ca29c0a5b5cc76ceacc0',
'0x7ae1291db32d16457c248567f2b101e62c5549d2a64cd2b7605d503ec876d58707a8d663641e99663bc4f6cc9746f4852e75e7e54de5bc1bd3c299c9a113409e',
'0x5095fe4d0144b06e82aa4753d595fd10de9bba3733eba8ce0784417182317e725fac31b2fb53f4856a5e38866501425b485f4d2eaf2666a9f20ae68f4331ed2c'
],
[
'all hour make first leader extend hole alien behind guard gospel lava path output census museum junior mass reopen famous sing advance salt reform',
'0x066dca1a2bb7e8a1db2832148ce9933eea0f3ac9548d793112d9a95c9407efad',
'0xa911a5f4db0940b17ecb79c4dcf9392bf47dd18acaebdd4ef48799909ebb49672947cc15f4ef7e8ef47103a1a91a6732b821bda2c667e5b1d491c54788c69391',
'0x8844cb50f3ba8030ab61afee623534836d4ea3677d42bae470fc5e251ea0ca7ec9ea65c8c40be191c7c8683165848279ced81f3a121c9450078a496b6c59f610'
],
[
'vessel ladder alter error federal sibling chat ability sun glass valve picture',
'0xf30f8c1da665478f49b001d94c5fc452',
'0x4e2314ca7d9eebac6fe5a05a5a8d3546bc891785414d82207ac987926380411e559c885190d641ff7e686ace8c57db6f6e4333c1081e3d88d7141a74cf339c8f',
'0x18917f0c7480c95cd4d98bdc7df773c366d33590252707da1358eb58b43a7b765e3c513878541bfbfb466bb4206f581edf9bf601409c72afac130bcc8b5661b5'
],
[
'scissors invite lock maple supreme raw rapid void congress muscle digital elegant little brisk hair mango congress clump',
'0xc10ec20dc3cd9f652c7fac2f1230f7a3c828389a14392f05',
'0x7a83851102849edc5d2a3ca9d8044d0d4f00e5c4a292753ed3952e40808593251b0af1dd3c9ed9932d46e8608eb0b928216a6160bd4fc775a6e6fbd493d7c6b2',
'0xb0bf86b0955413fc95144bab124e82042d0cce9c292c1bfd0874ae5a95412977e7bc109aeef33c7c90be952a83f3fe528419776520de721ef6ec9e814749c3fc'
],
[
'void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold',
'0xf585c11aec520db57dd353c69554b21a89b20fb0650966fa0a9d6f74fd989d8f',
'0x938ba18c3f521f19bd4a399c8425b02c716844325b1a65106b9d1593fbafe5e0b85448f523f91c48e331995ff24ae406757cff47d11f240847352b348ff436ed',
'0xc07ba4a979657576f4f7446e3bd2672c87131fa0f472a8bc1f2e9b28c11fb04c66da12cd280662196a5888d8a77178dab8034ed42b11d1654a31db6e1ff4d4c5'
]
];
export default tests;
@@ -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.
import { Keypair } from '../../types';
import { u8aConcat } from '@plugnet/util';
export default function schnorrkelKeypairToU8a ({ publicKey, secretKey }: Keypair): Uint8Array {
return u8aConcat(secretKey, publicKey).slice();
}
@@ -0,0 +1,21 @@
// 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 { Keypair } from '../types';
import '../polyfill';
import { assert } from '@plugnet/util';
import { sr25519Sign } from '@plugnet/wasm-crypto';
/**
* @name schnorrkelSign
* @description Returns message signature of `message`, using the supplied pair
*/
export default function schnorrkelSign (message: Uint8Array, { publicKey, secretKey }: Partial<Keypair>): Uint8Array {
assert(publicKey && publicKey.length === 32, 'Expected valid publicKey, 32-bytes');
assert(secretKey && secretKey.length === 64, 'Expected valid secretKey, 64-bytes');
return sr25519Sign(publicKey as Uint8Array, secretKey as Uint8Array, message);
}
@@ -0,0 +1,32 @@
// 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 } from '@plugnet/util';
import { waitReady } from '@plugnet/wasm-crypto';
import randomAsU8a from '../random/asU8a';
import pairFromSeed from './keypair/fromSeed';
import sign from './sign';
import verify from './verify';
const MESSAGE = stringToU8a('this is a message');
describe('sign and verify', () => {
beforeEach(async () => {
return waitReady();
});
it('has 64-byte signatures', () => {
const pair = pairFromSeed(randomAsU8a());
expect(sign(MESSAGE, pair)).toHaveLength(64);
});
it('can sign and verify a message', () => {
const pair = pairFromSeed(randomAsU8a());
const signature = sign(MESSAGE, pair);
expect(verify(MESSAGE, signature, pair.publicKey)).toBe(true);
});
});
@@ -0,0 +1,15 @@
// 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 '../polyfill';
import { sr25519Verify } from '@plugnet/wasm-crypto';
/**
* @name schnorrkelVerify
* @description Verifies the signature of `message`, using the supplied pair
*/
export default function schnorrkelVerify (message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean {
return sr25519Verify(signature, message, publicKey);
}
@@ -0,0 +1,5 @@
// 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.
export { default as secp256k1Recover } from './recover';
@@ -0,0 +1,16 @@
// 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 secp256k1 from 'secp256k1';
import { u8aToBuffer, u8aToU8a } from '@plugnet/util';
/**
* @name secp256k1Recover
* @description Recovers a publicKey from the supplied signature
*/
export default function secp256k1Recover (message: Uint8Array, signature: Uint8Array, recovery: number): Uint8Array {
return u8aToU8a(
secp256k1.recover(u8aToBuffer(message), u8aToBuffer(signature), recovery)
);
}
@@ -0,0 +1,25 @@
// 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 { waitReady } from '@plugnet/wasm-crypto';
import { sha512AsU8a } from '.';
describe('sha512AsU8a', () => {
beforeEach(async () => {
await waitReady();
});
it('creates a sha-512 hash', () => {
expect(
sha512AsU8a(
Uint8Array.from([0x61, 0x62, 0x63, 0x64])
)
).toEqual(
Uint8Array.from([
216, 2, 47, 32, 96, 173, 110, 253, 41, 122, 183, 61, 204, 83, 85, 201, 178, 20, 5, 75, 13, 23, 118, 161, 54, 166, 105, 210, 106, 125, 59, 20, 247, 58, 160, 208, 235, 255, 25, 238, 51, 51, 104, 240, 22, 75, 100, 25, 169, 109, 164, 158, 62, 72, 23, 83, 231, 233, 107, 113, 107, 220, 203, 111
])
);
});
});
+26
View File
@@ -0,0 +1,26 @@
// 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 nacl from 'tweetnacl';
import { isReady, sha512 } from '@plugnet/wasm-crypto';
/**
* @name sha512AsU8a
* @summary Creates sha-512 hash of the input.
* @description
* Returns a sha-512 `Uint8Array` from the supplied data.
* @example
* <BR>
*
* ```javascript
* import { sha512AsU8a } from '@plugnet/util-crypto';
*
* sha512AsU8a(Uint8Array.from([...])); // => Uint8Array([...])
* ```
*/
export default function sha512AsU8a (data: Uint8Array): Uint8Array {
return isReady()
? sha512(data)
: nacl.hash(data);
}
+9
View File
@@ -0,0 +1,9 @@
// 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 Implements Sha-512 hashing functions for a variety of input and outputs
*/
export { default as sha512AsU8a } from './asU8a';
+15
View File
@@ -0,0 +1,15 @@
// 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.
export type Keypair = {
publicKey: Uint8Array;
secretKey: Uint8Array;
};
export type Seedpair = {
publicKey: Uint8Array;
seed: Uint8Array;
};
export type KeypairType = 'ed25519' | 'sr25519';
@@ -0,0 +1,31 @@
// 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 { waitReady } from '@plugnet/wasm-crypto';
import { xxhashAsHex } from '.';
describe('xxhashAsHex', () => {
beforeEach(async () => {
await waitReady();
});
it('returns a 64-bit value by default', () => {
expect(
xxhashAsHex('abc')
).toEqual('0x990977adf52cbc44');
});
it('returns a 128-bit value (as specified)', () => {
expect(
xxhashAsHex('abc', 128)
).toEqual('0x990977adf52cbc440889329981caa9be');
});
it('returns a 256-bit value (as specified)', () => {
expect(
xxhashAsHex('abc', 256)
).toEqual('0x990977adf52cbc440889329981caa9bef7da5770b2b8a05303b75d95360dd62b');
});
});
+27
View File
@@ -0,0 +1,27 @@
// 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 { u8aToHex } from '@plugnet/util';
import xxhashAsU8a from './asU8a';
/**
* @name xxhashAsHex
* @summary Creates a xxhash64 hex from the input.
* @description
* From either a `string`, `Uint8Array` or a `Buffer` input, create the xxhash64 and return the result as a hex string with the specified `bitLength`.
* @example
* <BR>
*
* ```javascript
* import { xxhashAsHex } from '@plugnet/util-crypto';
*
* xxhashAsHex('abc'); // => 0x44bc2cf5ad770999
* ```
*/
export default function xxhashAsHex (data: Buffer | Uint8Array | string, bitLength: number = 64): string {
return u8aToHex(
xxhashAsU8a(data, bitLength)
);
}
@@ -0,0 +1,38 @@
// 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 { hexToU8a } from '@plugnet/util';
import { waitReady } from '@plugnet/wasm-crypto';
import { xxhashAsU8a } from '.';
describe('xxhashAsU8a', () => {
beforeEach(async () => {
await waitReady();
});
it('returns a 64-bit value by default', () => {
expect(
xxhashAsU8a('abc')
).toEqual(
hexToU8a('0x990977adf52cbc44')
);
});
it('returns a 128-bit value (as specified)', () => {
expect(
xxhashAsU8a('abc', 128)
).toEqual(
hexToU8a('0x990977adf52cbc440889329981caa9be')
);
});
it('returns a 256-bit value (as specified)', () => {
expect(
xxhashAsU8a('abc', 256)
).toEqual(
hexToU8a('0x990977adf52cbc440889329981caa9bef7da5770b2b8a05303b75d95360dd62b')
);
});
});
+38
View File
@@ -0,0 +1,38 @@
// 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 { u8aToU8a } from '@plugnet/util';
import { isReady, twox } from '@plugnet/wasm-crypto';
import xxhash64AsBn from './xxhash64/asBn';
/**
* @name xxhashAsU8a
* @summary Creates a xxhash64 u8a from the input.
* @description
* From either a `string`, `Uint8Array` or a `Buffer` input, create the xxhash64 and return the result as a `Uint8Array` with the specified `bitLength`.
* @example
* <BR>
*
* ```javascript
* import { xxhashAsU8a } from '@plugnet/util-crypto';
*
* xxhashAsU8a('abc'); // => 0x44bc2cf5ad770999
* ```
*/
export default function xxhashAsU8a (data: Buffer | Uint8Array | string, bitLength: number = 64): Uint8Array {
const iterations = Math.ceil(bitLength / 64);
if (isReady()) {
return twox(u8aToU8a(data), iterations);
}
const u8a = new Uint8Array(Math.ceil(bitLength / 8));
for (let seed = 0; seed < iterations; seed++) {
u8a.set(xxhash64AsBn(data, seed).toArray('le', 8), seed * 8);
}
return u8a;
}
+10
View File
@@ -0,0 +1,10 @@
// 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 xxhash64 values with specified bitlengths
*/
export { default as xxhashAsHex } from './asHex';
export { default as xxhashAsU8a } from './asU8a';
@@ -0,0 +1,13 @@
// 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 { xxhash64AsBn } from '.';
describe('xxhash64AsBn', () => {
it('creates the correct BN output', () => {
expect(
xxhash64AsBn('abcd', 0xabcd).toString(16)
).toEqual('e29f70f8b8c96df7');
});
});
@@ -0,0 +1,28 @@
// 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 xxhash64AsRaw from './asRaw';
/**
* @name xxhash64AsBn
* @summary Creates a xxhash BN from the input.
* @description
* From either a `string`, `Uint8Array` or a `Buffer` input, create the xxhash and return the result as a BN.
* @example
* <BR>
*
* ```javascript
* import { xxhash64AsNumber } from '@plugnet/util-crypto';
*
* xxhash64AsBn('abcd', 0xabcd)); // => new BN(0xe29f70f8b8c96df7)
* ```
*/
export default function xxhash64AsBn (data: Buffer | Uint8Array | string, seed: number): BN {
return new BN(
xxhash64AsRaw(data, seed),
16
);
}
@@ -0,0 +1,13 @@
// 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 { xxhash64AsHex } from '.';
describe('xxhash64AsHex', () => {
it('creates the correct hex output', () => {
expect(
xxhash64AsHex('abcd', 0xabcd)
).toEqual('0xe29f70f8b8c96df7');
});
});
@@ -0,0 +1,27 @@
// 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 { hexAddPrefix } from '@plugnet/util';
import xxhash64AsRaw from './asRaw';
/**
* @name xxhash64AsHex
* @summary Creates a xxhash hex from the input.
* @description
* From either a `string`, `Uint8Array` or a `Buffer` input, create the xxhash and return the result as a hex string.
* @example
* <BR>
*
* ```javascript
* import { xxhash64AsHex } from '@plugnet/util-crypto';
*
* xxhash64AsHex('abcd', 0xabcd)); // => 0xe29f70f8b8c96df7
* ```
*/
export default function xxhash64AsHex (data: Buffer | Uint8Array | string, seed: number): string {
return hexAddPrefix(
xxhash64AsRaw(data, seed)
);
}
@@ -0,0 +1,13 @@
// 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 { xxhash64AsRaw } from '.';
describe('xxhash64AsRaw', () => {
it('creates the correct non-prefixed hex output', () => {
expect(
xxhash64AsRaw('abcd', 0xabcd)
).toEqual('e29f70f8b8c96df7');
});
});
@@ -0,0 +1,23 @@
// 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 xxhash64AsValue from './asValue';
/**
* @name xxhash64AsRaw
* @summary Creates a xxhash non-prefixed hex from the input.
* @description
* From either a `string`, `Uint8Array` or a `Buffer` input, create the xxhash and return the result as a non-prefixed hex string.
* @example
* <BR>
*
* ```javascript
* import { xxhash64AsRaw } from '@plugnet/util-crypto';
*
* xxhash64AsRaw('abcd', 0xabcd)); // => e29f70f8b8c96df7
* ```
*/
export default function xxhash64AsRaw (data: Buffer | Uint8Array | string, seed: number): string {
return xxhash64AsValue(data, seed).toString(16);
}
@@ -0,0 +1,25 @@
// 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 xxhash64AsValue from './asValue';
describe('xxhash64AsValue', () => {
it('creates the correct output (string input)', () => {
expect(
xxhash64AsValue('abcd', 0xabcd).toString(16)
).toEqual('e29f70f8b8c96df7');
});
it('creates the correct output (Buffer input)', () => {
expect(
xxhash64AsValue(Buffer.from([0x61, 0x62, 0x63, 0x64]), 0xabcd).toString(16)
).toEqual('e29f70f8b8c96df7');
});
it('creates the correct output (Uint8Array input)', () => {
expect(
xxhash64AsValue(new Uint8Array([0x61, 0x62, 0x63, 0x64]), 0xabcd).toString(16)
).toEqual('e29f70f8b8c96df7');
});
});
@@ -0,0 +1,33 @@
// 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 xxhashjs from 'xxhashjs';
import { isBuffer, isString, u8aToBuffer } from '@plugnet/util';
/**
* @name xxhash64AsValue
* @summary Creates a hex number from the input.
* @description
* From either a `string`, `Uint8Array` or a `Buffer` input, create the xxhash and return the result as a hex number
* @example
* <BR>
*
* ```javascript
* import { xxhash64AsValue } from '@plugnet/util-crypto';
*
* xxhash64AsValue('abcd', 0xabcd)); // => e29f70f8b8c96df7
* ```
*/
export default function xxhash64AsValue (data: Buffer | Uint8Array | string, seed: number): number {
if (isBuffer(data) || isString(data)) {
// @ts-ignore Buffer is ArrayBuffer underlying
return xxhashjs.h64(data, seed);
}
// @ts-ignore conversion works, yields correct result
return xxhashjs.h64(
u8aToBuffer(data),
seed
) as any;
}
@@ -0,0 +1,16 @@
// 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 xxhash64AsBn from './asBn';
import xxhash64AsHex from './asHex';
import xxhash64AsRaw from './asRaw';
/**
* @summary Create [XXHash](http://cyan4973.github.io/xxHash/) values as BN, hex & number output
*/
export {
xxhash64AsBn,
xxhash64AsHex,
xxhash64AsRaw
};