@pezkuwi/util-crypto 14.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/package.json +45 -0
- package/src/address/addressToEvm.spec.ts +16 -0
- package/src/address/addressToEvm.ts +12 -0
- package/src/address/check.spec.ts +44 -0
- package/src/address/check.ts +34 -0
- package/src/address/checksum.spec.ts +45 -0
- package/src/address/checksum.ts +25 -0
- package/src/address/decode.spec.ts +138 -0
- package/src/address/decode.ts +41 -0
- package/src/address/defaults.ts +12 -0
- package/src/address/derive.spec.ts +26 -0
- package/src/address/derive.ts +36 -0
- package/src/address/encode.spec.ts +177 -0
- package/src/address/encode.ts +43 -0
- package/src/address/encodeDerived.spec.ts +14 -0
- package/src/address/encodeDerived.ts +19 -0
- package/src/address/encodeMulti.spec.ts +18 -0
- package/src/address/encodeMulti.ts +18 -0
- package/src/address/eq.spec.ts +45 -0
- package/src/address/eq.ts +24 -0
- package/src/address/evmToAddress.spec.ts +20 -0
- package/src/address/evmToAddress.ts +24 -0
- package/src/address/index.ts +21 -0
- package/src/address/is.spec.ts +113 -0
- package/src/address/is.ts +14 -0
- package/src/address/keyDerived.spec.ts +24 -0
- package/src/address/keyDerived.ts +22 -0
- package/src/address/keyMulti.spec.ts +20 -0
- package/src/address/keyMulti.ts +23 -0
- package/src/address/setSS58Format.spec.ts +21 -0
- package/src/address/setSS58Format.ts +20 -0
- package/src/address/sort.spec.ts +22 -0
- package/src/address/sort.ts +17 -0
- package/src/address/sshash.ts +12 -0
- package/src/address/types.ts +6 -0
- package/src/address/util.ts +8 -0
- package/src/address/validate.spec.ts +113 -0
- package/src/address/validate.ts +10 -0
- package/src/base32/bs32.ts +53 -0
- package/src/base32/decode.spec.ts +34 -0
- package/src/base32/encode.spec.ts +30 -0
- package/src/base32/helpers.ts +93 -0
- package/src/base32/index.ts +8 -0
- package/src/base32/is.spec.ts +32 -0
- package/src/base32/validate.spec.ts +44 -0
- package/src/base58/bs58.ts +43 -0
- package/src/base58/decode.spec.ts +31 -0
- package/src/base58/encode.spec.ts +26 -0
- package/src/base58/index.ts +8 -0
- package/src/base58/validate.spec.ts +20 -0
- package/src/base64/bs64.ts +43 -0
- package/src/base64/decode.spec.ts +42 -0
- package/src/base64/encode.spec.ts +14 -0
- package/src/base64/index.ts +10 -0
- package/src/base64/pad.spec.ts +14 -0
- package/src/base64/pad.ts +10 -0
- package/src/base64/trim.spec.ts +14 -0
- package/src/base64/trim.ts +14 -0
- package/src/base64/validate.spec.ts +32 -0
- package/src/blake2/asHex.spec.ts +57 -0
- package/src/blake2/asU8a.spec.ts +74 -0
- package/src/blake2/asU8a.ts +40 -0
- package/src/blake2/index.ts +8 -0
- package/src/bn.ts +15 -0
- package/src/bundle.ts +33 -0
- package/src/bundleInit.ts +11 -0
- package/src/crypto.spec.ts +18 -0
- package/src/crypto.ts +18 -0
- package/src/ed25519/deriveHard.ts +18 -0
- package/src/ed25519/index.ts +13 -0
- package/src/ed25519/pair/fromRandom.spec.ts +28 -0
- package/src/ed25519/pair/fromRandom.ts +25 -0
- package/src/ed25519/pair/fromSecret.spec.ts +33 -0
- package/src/ed25519/pair/fromSecret.ts +29 -0
- package/src/ed25519/pair/fromSeed.spec.ts +42 -0
- package/src/ed25519/pair/fromSeed.ts +41 -0
- package/src/ed25519/pair/fromString.spec.ts +17 -0
- package/src/ed25519/pair/fromString.ts +31 -0
- package/src/ed25519/sign.spec.ts +40 -0
- package/src/ed25519/sign.ts +38 -0
- package/src/ed25519/verify.spec.ts +84 -0
- package/src/ed25519/verify.ts +41 -0
- package/src/ethereum/encode.spec.ts +59 -0
- package/src/ethereum/encode.ts +39 -0
- package/src/ethereum/index.ts +6 -0
- package/src/ethereum/isAddress.spec.ts +34 -0
- package/src/ethereum/isAddress.ts +16 -0
- package/src/ethereum/isChecksum.ts +27 -0
- package/src/ethereum/isCheksum.spec.ts +30 -0
- package/src/hd/ethereum/index.spec.ts +54 -0
- package/src/hd/ethereum/index.ts +69 -0
- package/src/hd/index.ts +6 -0
- package/src/hd/ledger/derivePrivate.ts +34 -0
- package/src/hd/ledger/index.spec.ts +64 -0
- package/src/hd/ledger/index.ts +42 -0
- package/src/hd/ledger/master.spec.ts +19 -0
- package/src/hd/ledger/master.ts +26 -0
- package/src/hd/validatePath.spec.ts +30 -0
- package/src/hd/validatePath.ts +24 -0
- package/src/helpers.ts +38 -0
- package/src/hmac/index.ts +4 -0
- package/src/hmac/shaAsU8a.spec.ts +45 -0
- package/src/hmac/shaAsU8a.ts +48 -0
- package/src/index.ts +6 -0
- package/src/json/constants.ts +11 -0
- package/src/json/decrypt.ts +25 -0
- package/src/json/decryptData.ts +45 -0
- package/src/json/encrypt.ts +25 -0
- package/src/json/encryptFormat.ts +20 -0
- package/src/json/index.ts +7 -0
- package/src/json/types.ts +22 -0
- package/src/keccak/asHex.spec.ts +30 -0
- package/src/keccak/asU8a.spec.ts +56 -0
- package/src/keccak/asU8a.ts +45 -0
- package/src/keccak/index.ts +8 -0
- package/src/key/DeriveJunction.ts +79 -0
- package/src/key/extractPath.spec.ts +51 -0
- package/src/key/extractPath.ts +37 -0
- package/src/key/extractSuri.spec.ts +147 -0
- package/src/key/extractSuri.ts +40 -0
- package/src/key/fromPath.ts +28 -0
- package/src/key/hdkdDerive.ts +17 -0
- package/src/key/hdkdEcdsa.ts +8 -0
- package/src/key/hdkdEd25519.ts +7 -0
- package/src/key/hdkdSr25519.ts +14 -0
- package/src/key/index.ts +12 -0
- package/src/mnemonic/bip39.spec.ts +80 -0
- package/src/mnemonic/bip39.ts +127 -0
- package/src/mnemonic/generate.spec.ts +58 -0
- package/src/mnemonic/generate.ts +25 -0
- package/src/mnemonic/index.ts +11 -0
- package/src/mnemonic/toEntropy.spec.ts +36 -0
- package/src/mnemonic/toEntropy.ts +13 -0
- package/src/mnemonic/toLegacySeed.spec.ts +52 -0
- package/src/mnemonic/toLegacySeed.ts +39 -0
- package/src/mnemonic/toMiniSecret.spec.ts +67 -0
- package/src/mnemonic/toMiniSecret.ts +23 -0
- package/src/mnemonic/toMiniSecretCmp.spec.ts +64 -0
- package/src/mnemonic/validate.spec.ts +39 -0
- package/src/mnemonic/validate.ts +26 -0
- package/src/mnemonic/wordlists/en.ts +7 -0
- package/src/mnemonic/wordlists/es.ts +7 -0
- package/src/mnemonic/wordlists/fr.ts +7 -0
- package/src/mnemonic/wordlists/index.ts +11 -0
- package/src/mnemonic/wordlists/it.ts +7 -0
- package/src/mnemonic/wordlists/jp.ts +7 -0
- package/src/mnemonic/wordlists/ko.ts +7 -0
- package/src/mnemonic/wordlists/zh-s.ts +7 -0
- package/src/mnemonic/wordlists/zh-t.ts +7 -0
- package/src/mod.ts +4 -0
- package/src/nacl/decrypt.spec.ts +26 -0
- package/src/nacl/decrypt.ts +22 -0
- package/src/nacl/encrypt.spec.ts +20 -0
- package/src/nacl/encrypt.ts +31 -0
- package/src/nacl/index.ts +8 -0
- package/src/nacl/tweetnacl-secretbox-data.spec.ts +4629 -0
- package/src/nacl/tweetnacl-secretbox.spec.ts +161 -0
- package/src/nacl/tweetnacl.ts +1159 -0
- package/src/networks.ts +5 -0
- package/src/packageDetect.ts +14 -0
- package/src/packageInfo.ts +6 -0
- package/src/pbkdf2/encode.spec.ts +54 -0
- package/src/pbkdf2/encode.ts +29 -0
- package/src/pbkdf2/index.ts +4 -0
- package/src/random/asHex.spec.ts +38 -0
- package/src/random/asNumber.spec.ts +16 -0
- package/src/random/asNumber.ts +28 -0
- package/src/random/asU8a.spec.ts +36 -0
- package/src/random/asU8a.ts +30 -0
- package/src/random/index.ts +9 -0
- package/src/scrypt/defaults.ts +19 -0
- package/src/scrypt/encode.spec.ts +43 -0
- package/src/scrypt/encode.ts +30 -0
- package/src/scrypt/fromU8a.ts +44 -0
- package/src/scrypt/index.ts +6 -0
- package/src/scrypt/toU8a.ts +17 -0
- package/src/scrypt/types.ts +9 -0
- package/src/secp256k1/compress.spec.ts +47 -0
- package/src/secp256k1/compress.ts +21 -0
- package/src/secp256k1/deriveHard.ts +17 -0
- package/src/secp256k1/expand.spec.ts +47 -0
- package/src/secp256k1/expand.ts +30 -0
- package/src/secp256k1/hasher.spec.ts +24 -0
- package/src/secp256k1/hasher.ts +13 -0
- package/src/secp256k1/index.ts +10 -0
- package/src/secp256k1/pair/fromSeed.spec.ts +75 -0
- package/src/secp256k1/pair/fromSeed.ts +42 -0
- package/src/secp256k1/recover.spec.ts +35 -0
- package/src/secp256k1/recover.ts +36 -0
- package/src/secp256k1/sign.spec.ts +39 -0
- package/src/secp256k1/sign.ts +37 -0
- package/src/secp256k1/signVerify.spec.ts +94 -0
- package/src/secp256k1/tweakAdd.spec.ts +35 -0
- package/src/secp256k1/tweakAdd.ts +65 -0
- package/src/secp256k1/types.ts +4 -0
- package/src/secp256k1/verify.spec.ts +81 -0
- package/src/secp256k1/verify.ts +32 -0
- package/src/sha/asU8a.ts +30 -0
- package/src/sha/asU8a256.spec.ts +55 -0
- package/src/sha/asU8a512.spec.ts +33 -0
- package/src/sha/index.ts +8 -0
- package/src/signature/index.ts +8 -0
- package/src/signature/verify.spec.ts +230 -0
- package/src/signature/verify.ts +114 -0
- package/src/sr25519/agreement.spec.ts +31 -0
- package/src/sr25519/agreement.ts +23 -0
- package/src/sr25519/derive.ts +21 -0
- package/src/sr25519/deriveHard.ts +9 -0
- package/src/sr25519/derivePublic.ts +18 -0
- package/src/sr25519/deriveSoft.ts +9 -0
- package/src/sr25519/index.ts +12 -0
- package/src/sr25519/pair/fromSeed.spec.ts +35 -0
- package/src/sr25519/pair/fromSeed.ts +28 -0
- package/src/sr25519/pair/fromU8a.ts +23 -0
- package/src/sr25519/pair/testing.spec.ts +161 -0
- package/src/sr25519/pair/toU8a.ts +10 -0
- package/src/sr25519/sign.spec.ts +28 -0
- package/src/sr25519/sign.ts +22 -0
- package/src/sr25519/verify.spec.ts +42 -0
- package/src/sr25519/verify.ts +23 -0
- package/src/sr25519/vrfSign.ts +24 -0
- package/src/sr25519/vrfSignVerify.spec.ts +73 -0
- package/src/sr25519/vrfVerify.ts +25 -0
- package/src/test/index.ts +8 -0
- package/src/test/performance.ts +17 -0
- package/src/types.ts +33 -0
- package/src/xxhash/asHex.spec.ts +36 -0
- package/src/xxhash/asU8a.spec.ts +48 -0
- package/src/xxhash/asU8a.ts +45 -0
- package/src/xxhash/index.ts +8 -0
- package/src/xxhash/xxhash64.ts +155 -0
- package/tsconfig.build.json +18 -0
- package/tsconfig.spec.json +20 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@polkadot/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import { hexToU8a } from '@pezkuwi/util';
|
|
7
|
+
import { waitReady } from '@pezkuwi/wasm-crypto';
|
|
8
|
+
|
|
9
|
+
import { perfWasm } from '../test/index.js';
|
|
10
|
+
import { sha256AsU8a } from './index.js';
|
|
11
|
+
|
|
12
|
+
const TESTS = [
|
|
13
|
+
{
|
|
14
|
+
input: '0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
|
|
15
|
+
output: '0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456'
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
input: '0x7941cb07924fdc7b710e11d98d82850e89566e1c3cb980517ffe4b430f86dfd5',
|
|
19
|
+
output: '0xe668668fa102ccd4d3cf50e4472be8426e7dc52d6d355bee8c5e2177d1de81f7'
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
input: '0x5d9a905bc3ca7c153623af0a05231960eb3f5bdd5b8b7b55ede8b2deac689d65',
|
|
23
|
+
output: '0x6721bc38e80d03f4f45f1544819d17e0c33674eb6efcddf6c6192cd78194dd9f'
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
input: '0xb0cd6528ae4d5baf7c6f0d202e7f372b6488d22b2a5bd72f794f8f1e6031b31f',
|
|
27
|
+
output: '0x353f5a030af27885aed3571cd9e2cac9f4331c51d31cef496a586496aec32256'
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
input: '0x841267bd4110e1b634e17cd019abc6ae4f9a6dd097fb063000c1615a643b5463',
|
|
31
|
+
output: '0x8174a30d921978e7055516189872cca737b49468c6bcf7fdfe59d4a54c489a1f'
|
|
32
|
+
}
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
describe('sha256AsU8a', (): void => {
|
|
36
|
+
beforeEach(async (): Promise<void> => {
|
|
37
|
+
await waitReady();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
for (const onlyJs of [false, true]) {
|
|
41
|
+
describe(`onlyJs=${(onlyJs && 'true') || 'false'}`, (): void => {
|
|
42
|
+
for (const { input, output } of TESTS) {
|
|
43
|
+
it(`creates known sha-256 hash, ${output}`, (): void => {
|
|
44
|
+
expect(
|
|
45
|
+
sha256AsU8a(hexToU8a(input), onlyJs)
|
|
46
|
+
).toEqual(hexToU8a(output));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
perfWasm('sha256AsU8a', 128000, (input, onlyJs) =>
|
|
53
|
+
sha256AsU8a(input, onlyJs)
|
|
54
|
+
);
|
|
55
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@polkadot/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import { waitReady } from '@pezkuwi/wasm-crypto';
|
|
7
|
+
|
|
8
|
+
import { perfWasm } from '../test/index.js';
|
|
9
|
+
import { sha512AsU8a } from './index.js';
|
|
10
|
+
|
|
11
|
+
describe('sha512AsU8a', (): void => {
|
|
12
|
+
beforeEach(async (): Promise<void> => {
|
|
13
|
+
await waitReady();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
for (const onlyJs of [false, true]) {
|
|
17
|
+
describe(`onlyJs=${(onlyJs && 'true') || 'false'}`, (): void => {
|
|
18
|
+
it('creates a sha-512 hash', (): void => {
|
|
19
|
+
expect(
|
|
20
|
+
sha512AsU8a(Uint8Array.from([0x61, 0x62, 0x63, 0x64]), onlyJs)
|
|
21
|
+
).toEqual(
|
|
22
|
+
Uint8Array.from([
|
|
23
|
+
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
|
|
24
|
+
])
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
perfWasm('sha512AsU8a', 64000, (input, onlyJs) =>
|
|
31
|
+
sha512AsU8a(input, onlyJs)
|
|
32
|
+
);
|
|
33
|
+
});
|
package/src/sha/index.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @summary Implements Sha-256/512 hashing functions for a variety of input and outputs
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { sha256AsU8a, sha512AsU8a, shaAsU8a } from './asU8a.js';
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@polkadot/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import { hexToU8a, stringToU8a, u8aConcat, u8aToHex, u8aWrapBytes } from '@pezkuwi/util';
|
|
7
|
+
import { waitReady } from '@pezkuwi/wasm-crypto';
|
|
8
|
+
|
|
9
|
+
import { decodeAddress } from '../address/index.js';
|
|
10
|
+
import { secp256k1Sign } from '../secp256k1/sign.js';
|
|
11
|
+
import { signatureVerify } from './index.js';
|
|
12
|
+
|
|
13
|
+
const ADDR_ED = 'DxN4uvzwPzJLtn17yew6jEffPhXQfdKHTp2brufb98vGbPN';
|
|
14
|
+
const ADDR_SR = 'EK1bFgKm2FsghcttHT7TB7rNyXApFgs9fCbijMGQNyFGBQm';
|
|
15
|
+
const ADDR_SR_WRAP = 'J9nD3s7zssCX7bion1xctAF6xcVexcpy2uwy4jTm9JL8yuK';
|
|
16
|
+
const ADDR_EC = 'XyFVXiGaHxoBhXZkSh6NS2rjFyVaVNUo5UiZDqZbuSfUdji';
|
|
17
|
+
const ADDR_ET = '0x54Dab85EE2c7b9F7421100d7134eFb5DfA4239bF';
|
|
18
|
+
const MESSAGE = 'hello world';
|
|
19
|
+
const SIG_ED = '0x299d3bf4c8bb51af732f8067b3a3015c0862a5ff34721749d8ed6577ea2708365d1c5f76bd519009971e41156f12c70abc2533837ceb3bad9a05a99ab923de06';
|
|
20
|
+
const SIG_SR = '0xca01419b5a17219f7b78335658cab3b126db523a5df7be4bfc2bef76c2eb3b1dcf4ca86eb877d0a6cf6df12db5995c51d13b00e005d053b892bd09c594434288';
|
|
21
|
+
const SIG_SR_WRAP = '0x84b6afb1c8e54bbcb3f4872baf172580e21310e9387a53742627d6652d121447fa406b82805ed3184fb7bd519175cc9f99f283f97954d95cf966ee164df85489';
|
|
22
|
+
const SIG_EC = '0x994638ee586d2c5dbd9bacacbc35d9b7e9018de8f7892f00c900db63bc57b1283e2ee7bc51a9b1c1dae121ac4f4b9e2a41cd1d6bf4bb3e24d7fed6faf6d85e0501';
|
|
23
|
+
const SIG_ET = '0x4e35aad35793b71f08566615661c9b741d7c605bc8935ac08608dff685324d71b5704fbd14c9297d2f584ea0735f015dcf0def66b802b3f555e1db916eda4b7700';
|
|
24
|
+
const MUL_ED = u8aToHex(u8aConcat(new Uint8Array([0]), hexToU8a(SIG_ED)));
|
|
25
|
+
const MUL_SR = u8aToHex(u8aConcat(new Uint8Array([1]), hexToU8a(SIG_SR)));
|
|
26
|
+
const MUL_EC = u8aToHex(u8aConcat(new Uint8Array([2]), hexToU8a(SIG_EC)));
|
|
27
|
+
const MUL_ET = u8aToHex(u8aConcat(new Uint8Array([2]), hexToU8a(SIG_ET)));
|
|
28
|
+
|
|
29
|
+
describe('signatureVerify', (): void => {
|
|
30
|
+
beforeEach(async (): Promise<void> => {
|
|
31
|
+
await waitReady();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('throws on invalid signature length', (): void => {
|
|
35
|
+
expect(
|
|
36
|
+
() => signatureVerify(MESSAGE, new Uint8Array(32), ADDR_ED)
|
|
37
|
+
).toThrow('Invalid signature length, expected [64..66] bytes, found 32');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('verifyDetect', (): void => {
|
|
41
|
+
it('verifies ed25519 signature', (): void => {
|
|
42
|
+
expect(signatureVerify(MESSAGE, SIG_ED, ADDR_ED)).toEqual({
|
|
43
|
+
crypto: 'ed25519',
|
|
44
|
+
isValid: true,
|
|
45
|
+
isWrapped: false,
|
|
46
|
+
publicKey: decodeAddress(ADDR_ED)
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('verifies ecdsa signatures', (): void => {
|
|
51
|
+
expect(signatureVerify(MESSAGE, SIG_EC, ADDR_EC)).toEqual({
|
|
52
|
+
crypto: 'ecdsa',
|
|
53
|
+
isValid: true,
|
|
54
|
+
isWrapped: false,
|
|
55
|
+
publicKey: decodeAddress(ADDR_EC)
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('verifies an ethereum signature', (): void => {
|
|
60
|
+
expect(signatureVerify(MESSAGE, SIG_ET, ADDR_ET)).toEqual({
|
|
61
|
+
crypto: 'ethereum',
|
|
62
|
+
isValid: true,
|
|
63
|
+
isWrapped: false,
|
|
64
|
+
publicKey: hexToU8a(ADDR_ET)
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('verifies an ethereum signature (known)', (): void => {
|
|
69
|
+
const message = 'Pay KSMs to the Kusama account:88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee';
|
|
70
|
+
|
|
71
|
+
expect(signatureVerify(
|
|
72
|
+
`\x19Ethereum Signed Message:\n${message.length.toString()}${message}`,
|
|
73
|
+
'0x55bd020bdbbdc02de34e915effc9b18a99002f4c29f64e22e8dcbb69e722ea6c28e1bb53b9484063fbbfd205e49dcc1f620929f520c9c4c3695150f05a28f52a01',
|
|
74
|
+
'0x002309df96687e44280bb72c3818358faeeb699c'
|
|
75
|
+
)).toEqual({
|
|
76
|
+
crypto: 'ethereum',
|
|
77
|
+
isValid: true,
|
|
78
|
+
isWrapped: true,
|
|
79
|
+
publicKey: hexToU8a('0x002309df96687e44280bb72c3818358faeeb699c')
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('fails on invalid ethereum signature', (): void => {
|
|
84
|
+
expect(signatureVerify(MESSAGE, SIG_EC, ADDR_ET)).toEqual({
|
|
85
|
+
crypto: 'none',
|
|
86
|
+
isValid: false,
|
|
87
|
+
isWrapped: false,
|
|
88
|
+
publicKey: hexToU8a(ADDR_ET)
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('verifies an sr25519 signature', (): void => {
|
|
93
|
+
expect(signatureVerify(MESSAGE, SIG_SR, ADDR_SR)).toEqual({
|
|
94
|
+
crypto: 'sr25519',
|
|
95
|
+
isValid: true,
|
|
96
|
+
isWrapped: false,
|
|
97
|
+
publicKey: decodeAddress(ADDR_SR)
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('verifies an sr25519 signature (with msg wrapper, without wrapped sig)', (): void => {
|
|
102
|
+
expect(signatureVerify(u8aWrapBytes(MESSAGE), SIG_SR_WRAP, ADDR_SR_WRAP)).toEqual({
|
|
103
|
+
crypto: 'sr25519',
|
|
104
|
+
isValid: true,
|
|
105
|
+
isWrapped: true,
|
|
106
|
+
publicKey: decodeAddress(ADDR_SR_WRAP)
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('verifies an sr25519 signature (without msg wrapper, with wrapped sig)', (): void => {
|
|
111
|
+
expect(signatureVerify(MESSAGE, SIG_SR_WRAP, ADDR_SR_WRAP)).toEqual({
|
|
112
|
+
crypto: 'sr25519',
|
|
113
|
+
isValid: true,
|
|
114
|
+
isWrapped: false,
|
|
115
|
+
publicKey: decodeAddress(ADDR_SR_WRAP)
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('allows various inputs', (): void => {
|
|
120
|
+
expect(signatureVerify(stringToU8a(MESSAGE), hexToU8a(SIG_ED), decodeAddress(ADDR_ED))).toEqual({
|
|
121
|
+
crypto: 'ed25519',
|
|
122
|
+
isValid: true,
|
|
123
|
+
isWrapped: false,
|
|
124
|
+
publicKey: decodeAddress(ADDR_ED)
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('fails on an invalid signature', (): void => {
|
|
129
|
+
expect(signatureVerify(MESSAGE, SIG_SR, ADDR_ED)).toEqual({
|
|
130
|
+
crypto: 'none',
|
|
131
|
+
isValid: false,
|
|
132
|
+
isWrapped: false,
|
|
133
|
+
publicKey: decodeAddress(ADDR_ED)
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
describe('verifyMultisig', (): void => {
|
|
139
|
+
it('verifies an ed25519 signature', (): void => {
|
|
140
|
+
expect(signatureVerify(MESSAGE, MUL_ED, ADDR_ED)).toEqual({
|
|
141
|
+
crypto: 'ed25519',
|
|
142
|
+
isValid: true,
|
|
143
|
+
isWrapped: false,
|
|
144
|
+
publicKey: decodeAddress(ADDR_ED)
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('verifies an ecdsa signature', (): void => {
|
|
149
|
+
expect(signatureVerify(MESSAGE, MUL_EC, ADDR_EC)).toEqual({
|
|
150
|
+
crypto: 'ecdsa',
|
|
151
|
+
isValid: true,
|
|
152
|
+
isWrapped: false,
|
|
153
|
+
publicKey: decodeAddress(ADDR_EC)
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('verifies an ethereum signature', (): void => {
|
|
158
|
+
expect(signatureVerify(MESSAGE, MUL_ET, ADDR_ET)).toEqual({
|
|
159
|
+
crypto: 'ethereum',
|
|
160
|
+
isValid: true,
|
|
161
|
+
isWrapped: false,
|
|
162
|
+
publicKey: hexToU8a(ADDR_ET)
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('verifies an sr25519 signature', (): void => {
|
|
167
|
+
expect(signatureVerify(MESSAGE, MUL_SR, ADDR_SR)).toEqual({
|
|
168
|
+
crypto: 'sr25519',
|
|
169
|
+
isValid: true,
|
|
170
|
+
isWrapped: false,
|
|
171
|
+
publicKey: decodeAddress(ADDR_SR)
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('fails on an invalid signature', (): void => {
|
|
176
|
+
expect(signatureVerify(MESSAGE, MUL_SR, ADDR_ED)).toEqual({
|
|
177
|
+
crypto: 'none',
|
|
178
|
+
isValid: false,
|
|
179
|
+
isWrapped: false,
|
|
180
|
+
publicKey: new Uint8Array([61, 12, 55, 211, 0, 211, 97, 199, 4, 37, 17, 213, 81, 175, 166, 23, 251, 199, 144, 210, 19, 83, 186, 1, 196, 231, 14, 156, 171, 46, 141, 146])
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
/**
|
|
184
|
+
* ref: https://github.com/polkadot-js/common/issues/1898
|
|
185
|
+
*
|
|
186
|
+
* The following test ensures that we cover a reproduction that showed
|
|
187
|
+
* an inherent issue with verifying ecdsa signatures which is fixed in
|
|
188
|
+
* https://github.com/polkadot-js/common/pull/1973.
|
|
189
|
+
*
|
|
190
|
+
* It uses a random secretKey, and publicKey pair along with `secp256k1Sign`
|
|
191
|
+
* as the signer which is used for `ecdsa`.
|
|
192
|
+
*/
|
|
193
|
+
it('Ensure ecdsa can sign and verify 1000 messages', (): void => {
|
|
194
|
+
const verifyThousandMessages = () => {
|
|
195
|
+
const secretKey = new Uint8Array([
|
|
196
|
+
103, 97, 114, 98, 97, 103, 101, 32, 114, 105, 100,
|
|
197
|
+
103, 101, 32, 107, 105, 99, 107, 32, 114, 111, 115,
|
|
198
|
+
101, 32, 101, 110, 100, 32, 115, 113, 117, 101
|
|
199
|
+
]);
|
|
200
|
+
const publicKey = new Uint8Array([
|
|
201
|
+
2, 179, 102, 92, 246, 50, 172, 88,
|
|
202
|
+
81, 116, 8, 211, 192, 131, 154, 184,
|
|
203
|
+
122, 83, 180, 104, 4, 227, 214, 195,
|
|
204
|
+
140, 11, 82, 229, 49, 211, 185, 176,
|
|
205
|
+
63
|
|
206
|
+
]);
|
|
207
|
+
|
|
208
|
+
for (let i = 0; i < 1000; i++) {
|
|
209
|
+
const message = `message ${i}`;
|
|
210
|
+
const encodedMessage = stringToU8a(message);
|
|
211
|
+
const signature = secp256k1Sign(encodedMessage, { secretKey });
|
|
212
|
+
|
|
213
|
+
const { isValid: valid } = signatureVerify(
|
|
214
|
+
message,
|
|
215
|
+
signature,
|
|
216
|
+
publicKey
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
if (!valid) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return true;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
expect(verifyThousandMessages()).toEqual(true);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
});
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { KeypairType, VerifyResult } from '../types.js';
|
|
5
|
+
|
|
6
|
+
import { u8aIsWrapped, u8aToU8a, u8aUnwrapBytes, u8aWrapBytes } from '@pezkuwi/util';
|
|
7
|
+
|
|
8
|
+
import { decodeAddress } from '../address/decode.js';
|
|
9
|
+
import { ed25519Verify } from '../ed25519/verify.js';
|
|
10
|
+
import { secp256k1Verify } from '../secp256k1/verify.js';
|
|
11
|
+
import { sr25519Verify } from '../sr25519/verify.js';
|
|
12
|
+
|
|
13
|
+
interface VerifyInput {
|
|
14
|
+
message: Uint8Array;
|
|
15
|
+
publicKey: Uint8Array;
|
|
16
|
+
signature: Uint8Array;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type Verifier = [KeypairType, (message: Uint8Array | string, signature: Uint8Array, publicKey: Uint8Array) => boolean];
|
|
20
|
+
|
|
21
|
+
type VerifyFn = (result: VerifyResult, input: VerifyInput) => VerifyResult;
|
|
22
|
+
|
|
23
|
+
const secp256k1VerifyHasher = (hashType: 'blake2' | 'keccak') =>
|
|
24
|
+
(message: Uint8Array | string, signature: Uint8Array, publicKey: Uint8Array) =>
|
|
25
|
+
secp256k1Verify(message, signature, publicKey, hashType, true);
|
|
26
|
+
|
|
27
|
+
const VERIFIERS_ECDSA: Verifier[] = [
|
|
28
|
+
['ecdsa', secp256k1VerifyHasher('blake2')],
|
|
29
|
+
['ethereum', secp256k1VerifyHasher('keccak')]
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const VERIFIERS: Verifier[] = [
|
|
33
|
+
['ed25519', ed25519Verify],
|
|
34
|
+
['sr25519', sr25519Verify]
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
function verifyDetect (result: VerifyResult, { message, publicKey, signature }: VerifyInput, verifiers = [...VERIFIERS, ...VERIFIERS_ECDSA]): VerifyResult {
|
|
38
|
+
result.isValid = verifiers.some(([crypto, verify]): boolean => {
|
|
39
|
+
try {
|
|
40
|
+
if (verify(message, signature, publicKey)) {
|
|
41
|
+
result.crypto = crypto;
|
|
42
|
+
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
} catch {
|
|
46
|
+
// do nothing, result.isValid still set to false
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return false;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function verifyMultisig (result: VerifyResult, { message, publicKey, signature }: VerifyInput): VerifyResult {
|
|
56
|
+
if (![0, 1, 2].includes(signature[0]) || ![65, 66].includes(signature.length)) {
|
|
57
|
+
throw new Error(`Unknown crypto type, expected signature prefix [0..2], found ${signature[0]}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// If the signature is 66 bytes it must be an ecdsa signature
|
|
61
|
+
// containing: prefix [1 byte] + signature [65] bytes.
|
|
62
|
+
// Remove the and then verify
|
|
63
|
+
if (signature.length === 66) {
|
|
64
|
+
result = verifyDetect(result, { message, publicKey, signature: signature.subarray(1) }, VERIFIERS_ECDSA);
|
|
65
|
+
} else {
|
|
66
|
+
// The signature contains 65 bytes which is either
|
|
67
|
+
// - A ed25519 or sr25519 signature [1 byte prefix + 64 bytes]
|
|
68
|
+
// - An ecdsa signature [65 bytes]
|
|
69
|
+
result = verifyDetect(result, { message, publicKey, signature: signature.subarray(1) }, VERIFIERS);
|
|
70
|
+
|
|
71
|
+
if (!result.isValid) {
|
|
72
|
+
result = verifyDetect(result, { message, publicKey, signature }, VERIFIERS_ECDSA);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// If both failed, explicitly set crypto to 'none'
|
|
76
|
+
if (!result.isValid) {
|
|
77
|
+
result.crypto = 'none';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function getVerifyFn (signature: Uint8Array): VerifyFn {
|
|
85
|
+
return [0, 1, 2].includes(signature[0]) && [65, 66].includes(signature.length)
|
|
86
|
+
? verifyMultisig
|
|
87
|
+
: verifyDetect;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function signatureVerify (message: string | Uint8Array, signature: string | Uint8Array, addressOrPublicKey: string | Uint8Array): VerifyResult {
|
|
91
|
+
const signatureU8a = u8aToU8a(signature);
|
|
92
|
+
|
|
93
|
+
if (![64, 65, 66].includes(signatureU8a.length)) {
|
|
94
|
+
throw new Error(`Invalid signature length, expected [64..66] bytes, found ${signatureU8a.length}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const publicKey = decodeAddress(addressOrPublicKey);
|
|
98
|
+
const input = { message: u8aToU8a(message), publicKey, signature: signatureU8a };
|
|
99
|
+
const result: VerifyResult = { crypto: 'none', isValid: false, isWrapped: u8aIsWrapped(input.message, true), publicKey };
|
|
100
|
+
const isWrappedBytes = u8aIsWrapped(input.message, false);
|
|
101
|
+
const verifyFn = getVerifyFn(signatureU8a);
|
|
102
|
+
|
|
103
|
+
verifyFn(result, input);
|
|
104
|
+
|
|
105
|
+
if (result.crypto !== 'none' || (result.isWrapped && !isWrappedBytes)) {
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
input.message = isWrappedBytes
|
|
110
|
+
? u8aUnwrapBytes(input.message)
|
|
111
|
+
: u8aWrapBytes(input.message);
|
|
112
|
+
|
|
113
|
+
return verifyFn(result, input);
|
|
114
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@polkadot/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import type { Keypair } from '../types.js';
|
|
7
|
+
|
|
8
|
+
import { u8aToHex } from '@pezkuwi/util';
|
|
9
|
+
|
|
10
|
+
import { sr25519Agreement, sr25519PairFromSeed } from './index.js';
|
|
11
|
+
|
|
12
|
+
describe('agreement', (): void => {
|
|
13
|
+
let pairA: Keypair;
|
|
14
|
+
let pairB: Keypair;
|
|
15
|
+
|
|
16
|
+
beforeEach((): void => {
|
|
17
|
+
pairA = sr25519PairFromSeed('0x98b3d305d5a5eace562387e47e59badd4d77e3f72cabfb10a60f8a197059f0a8');
|
|
18
|
+
pairB = sr25519PairFromSeed('0x9732eea001851ff862d949a1699c9971f3a26edbede2ad7922cbbe9a0701f366');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('matches a known agreement (both ways)', (): void => {
|
|
22
|
+
const TEST = '0xb03a0b198c34c16f35cae933d88b16341b4cef3e84e851f20e664c6a30527f4e';
|
|
23
|
+
|
|
24
|
+
expect(
|
|
25
|
+
u8aToHex(sr25519Agreement(pairA.secretKey, pairB.publicKey))
|
|
26
|
+
).toEqual(TEST);
|
|
27
|
+
expect(
|
|
28
|
+
u8aToHex(sr25519Agreement(pairB.secretKey, pairA.publicKey))
|
|
29
|
+
).toEqual(TEST);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { getSharedSecret } from '@scure/sr25519';
|
|
5
|
+
|
|
6
|
+
import { u8aToU8a } from '@pezkuwi/util';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @name sr25519Agreement
|
|
10
|
+
* @description Key agreement between other's public key and self secret key
|
|
11
|
+
*/
|
|
12
|
+
export function sr25519Agreement (secretKey: string | Uint8Array, publicKey: string | Uint8Array): Uint8Array {
|
|
13
|
+
const secretKeyU8a = u8aToU8a(secretKey);
|
|
14
|
+
const publicKeyU8a = u8aToU8a(publicKey);
|
|
15
|
+
|
|
16
|
+
if (publicKeyU8a.length !== 32) {
|
|
17
|
+
throw new Error(`Invalid publicKey, received ${publicKeyU8a.length} bytes, expected 32`);
|
|
18
|
+
} else if (secretKeyU8a.length !== 64) {
|
|
19
|
+
throw new Error(`Invalid secretKey, received ${secretKeyU8a.length} bytes, expected 64`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return getSharedSecret(secretKeyU8a, publicKeyU8a);
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { Keypair } from '../types.js';
|
|
5
|
+
|
|
6
|
+
import * as sr25519 from '@scure/sr25519';
|
|
7
|
+
|
|
8
|
+
import { isU8a } from '@pezkuwi/util';
|
|
9
|
+
|
|
10
|
+
export function createDeriveFn (derive: (pair: Uint8Array, cc: Uint8Array) => Uint8Array): (keypair: Keypair, chainCode: Uint8Array) => Keypair {
|
|
11
|
+
return (keypair: Keypair, chainCode: Uint8Array): Keypair => {
|
|
12
|
+
if (!isU8a(chainCode) || chainCode.length !== 32) {
|
|
13
|
+
throw new Error('Invalid chainCode passed to derive');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const secretKey = derive(keypair.secretKey, chainCode);
|
|
17
|
+
const publicKey = sr25519.getPublicKey(secretKey);
|
|
18
|
+
|
|
19
|
+
return { publicKey, secretKey };
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import * as sr25519 from '@scure/sr25519';
|
|
5
|
+
|
|
6
|
+
import { createDeriveFn } from './derive.js';
|
|
7
|
+
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
9
|
+
export const sr25519DeriveHard = /*#__PURE__*/ createDeriveFn(sr25519.HDKD.secretHard);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import * as sr25519 from '@scure/sr25519';
|
|
5
|
+
|
|
6
|
+
import { isU8a, u8aToU8a } from '@pezkuwi/util';
|
|
7
|
+
|
|
8
|
+
export function sr25519DerivePublic (publicKey: string | Uint8Array, chainCode: Uint8Array): Uint8Array {
|
|
9
|
+
const publicKeyU8a = u8aToU8a(publicKey);
|
|
10
|
+
|
|
11
|
+
if (!isU8a(chainCode) || chainCode.length !== 32) {
|
|
12
|
+
throw new Error('Invalid chainCode passed to derive');
|
|
13
|
+
} else if (publicKeyU8a.length !== 32) {
|
|
14
|
+
throw new Error(`Invalid publicKey, received ${publicKeyU8a.length} bytes, expected 32`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return sr25519.HDKD.publicSoft(publicKeyU8a, chainCode);
|
|
18
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import * as sr25519 from '@scure/sr25519';
|
|
5
|
+
|
|
6
|
+
import { createDeriveFn } from './derive.js';
|
|
7
|
+
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
9
|
+
export const sr25519DeriveSoft = /*#__PURE__*/ createDeriveFn(sr25519.HDKD.secretSoft);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
export { sr25519Agreement } from './agreement.js';
|
|
5
|
+
export { sr25519DeriveHard } from './deriveHard.js';
|
|
6
|
+
export { sr25519DerivePublic } from './derivePublic.js';
|
|
7
|
+
export { sr25519DeriveSoft } from './deriveSoft.js';
|
|
8
|
+
export { sr25519PairFromSeed } from './pair/fromSeed.js';
|
|
9
|
+
export { sr25519Sign } from './sign.js';
|
|
10
|
+
export { sr25519Verify } from './verify.js';
|
|
11
|
+
export { sr25519VrfSign } from './vrfSign.js';
|
|
12
|
+
export { sr25519VrfVerify } from './vrfVerify.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@polkadot/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import { stringToU8a, u8aToHex } from '@pezkuwi/util';
|
|
7
|
+
|
|
8
|
+
import { mnemonicToMiniSecret } from '../../mnemonic/index.js';
|
|
9
|
+
import { sr25519PairFromSeed } from '../index.js';
|
|
10
|
+
import tests from './testing.spec.js';
|
|
11
|
+
|
|
12
|
+
describe('sr25519PairFromSeed', (): void => {
|
|
13
|
+
const TEST = stringToU8a('12345678901234567890123456789012');
|
|
14
|
+
const RESULT = {
|
|
15
|
+
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]),
|
|
16
|
+
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])
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
it('generates a valid publicKey/secretKey pair (u8a)', (): void => {
|
|
20
|
+
expect(
|
|
21
|
+
sr25519PairFromSeed(TEST)
|
|
22
|
+
).toEqual(RESULT);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
tests.forEach(([mnemonic, , , secret], index): void => {
|
|
26
|
+
it(`creates valid against known (${index})`, (): void => {
|
|
27
|
+
const seed = mnemonicToMiniSecret(mnemonic, 'Substrate');
|
|
28
|
+
const pair = sr25519PairFromSeed(seed);
|
|
29
|
+
|
|
30
|
+
expect(
|
|
31
|
+
u8aToHex(pair.secretKey)
|
|
32
|
+
).toEqual(secret);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { Keypair } from '../../types.js';
|
|
5
|
+
|
|
6
|
+
import * as sr25519 from '@scure/sr25519';
|
|
7
|
+
|
|
8
|
+
import { u8aToU8a } from '@pezkuwi/util';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @name sr25519PairFromSeed
|
|
12
|
+
* @description Returns a object containing a `publicKey` & `secretKey` generated from the supplied seed.
|
|
13
|
+
*/
|
|
14
|
+
export function sr25519PairFromSeed (seed: string | Uint8Array): Keypair {
|
|
15
|
+
const seedU8a = u8aToU8a(seed);
|
|
16
|
+
|
|
17
|
+
if (seedU8a.length !== 32) {
|
|
18
|
+
throw new Error(`Expected a seed matching 32 bytes, found ${seedU8a.length}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const sec = sr25519.secretFromSeed(seedU8a);
|
|
22
|
+
const pub = sr25519.getPublicKey(sec);
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
publicKey: pub,
|
|
26
|
+
secretKey: sec
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { Keypair } from '../../types.js';
|
|
5
|
+
|
|
6
|
+
import { u8aToU8a } from '@pezkuwi/util';
|
|
7
|
+
|
|
8
|
+
const SEC_LEN = 64;
|
|
9
|
+
const PUB_LEN = 32;
|
|
10
|
+
const TOT_LEN = SEC_LEN + PUB_LEN;
|
|
11
|
+
|
|
12
|
+
export function sr25519PairFromU8a (full: string | Uint8Array): Keypair {
|
|
13
|
+
const fullU8a = u8aToU8a(full);
|
|
14
|
+
|
|
15
|
+
if (fullU8a.length !== TOT_LEN) {
|
|
16
|
+
throw new Error(`Expected keypair with ${TOT_LEN} bytes, found ${fullU8a.length}`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
publicKey: fullU8a.slice(SEC_LEN, TOT_LEN),
|
|
21
|
+
secretKey: fullU8a.slice(0, SEC_LEN)
|
|
22
|
+
};
|
|
23
|
+
}
|