@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,42 @@
|
|
|
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 { ed25519PairFromSeed } from '../../ed25519/index.js';
|
|
7
|
+
import { mnemonicValidate } from '../../mnemonic/index.js';
|
|
8
|
+
import { HARDENED, hdValidatePath } from '../validatePath.js';
|
|
9
|
+
import { ledgerDerivePrivate } from './derivePrivate.js';
|
|
10
|
+
import { ledgerMaster } from './master.js';
|
|
11
|
+
|
|
12
|
+
export function hdLedger (_mnemonic: string, path: string): Keypair {
|
|
13
|
+
const words = _mnemonic
|
|
14
|
+
.split(' ')
|
|
15
|
+
.map((s) => s.trim())
|
|
16
|
+
.filter((s) => s);
|
|
17
|
+
|
|
18
|
+
if (![12, 24, 25].includes(words.length)) {
|
|
19
|
+
throw new Error('Expected a mnemonic with 24 words (or 25 including a password)');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const [mnemonic, password] = words.length === 25
|
|
23
|
+
? [words.slice(0, 24).join(' '), words[24]]
|
|
24
|
+
: [words.join(' '), ''];
|
|
25
|
+
|
|
26
|
+
if (!mnemonicValidate(mnemonic)) {
|
|
27
|
+
throw new Error('Invalid mnemonic passed to ledger derivation');
|
|
28
|
+
} else if (!hdValidatePath(path)) {
|
|
29
|
+
throw new Error('Invalid derivation path');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const parts = path.split('/').slice(1);
|
|
33
|
+
let seed = ledgerMaster(mnemonic, password);
|
|
34
|
+
|
|
35
|
+
for (const p of parts) {
|
|
36
|
+
const n = parseInt(p.replace(/'$/, ''), 10);
|
|
37
|
+
|
|
38
|
+
seed = ledgerDerivePrivate(seed, (n < HARDENED) ? (n + HARDENED) : n);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return ed25519PairFromSeed(seed.slice(0, 32));
|
|
42
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
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 { u8aToHex } from '@pezkuwi/util';
|
|
7
|
+
|
|
8
|
+
import { ledgerMaster } from './master.js';
|
|
9
|
+
|
|
10
|
+
const MNEMONIC = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
|
|
11
|
+
const XPRV = '0x402b03cd9c8bed9ba9f9bd6cd9c315ce9fcc59c7c25d37c85a36096617e69d418e35cb4a3b737afd007f0688618f21a8831643c0e6c77fc33c06026d2a0fc93832596435e70647d7d98ef102a32ea40319ca8fb6c851d7346d3bd8f9d1492658';
|
|
12
|
+
|
|
13
|
+
describe('ledgerDerive', (): void => {
|
|
14
|
+
it('derives a known master xprv', (): void => {
|
|
15
|
+
expect(u8aToHex(
|
|
16
|
+
ledgerMaster(MNEMONIC)
|
|
17
|
+
)).toEqual(XPRV);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { u8aConcat } from '@pezkuwi/util';
|
|
5
|
+
|
|
6
|
+
import { hmacShaAsU8a } from '../../hmac/index.js';
|
|
7
|
+
import { mnemonicToSeedSync } from '../../mnemonic/bip39.js';
|
|
8
|
+
|
|
9
|
+
const ED25519_CRYPTO = 'ed25519 seed';
|
|
10
|
+
|
|
11
|
+
// gets an xprv from a mnemonic
|
|
12
|
+
export function ledgerMaster (mnemonic: string, password?: string): Uint8Array {
|
|
13
|
+
const seed = mnemonicToSeedSync(mnemonic, password);
|
|
14
|
+
const chainCode = hmacShaAsU8a(ED25519_CRYPTO, new Uint8Array([1, ...seed]), 256);
|
|
15
|
+
let priv;
|
|
16
|
+
|
|
17
|
+
while (!priv || (priv[31] & 0b0010_0000)) {
|
|
18
|
+
priv = hmacShaAsU8a(ED25519_CRYPTO, priv || seed, 512);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
priv[0] &= 0b1111_1000;
|
|
22
|
+
priv[31] &= 0b0111_1111;
|
|
23
|
+
priv[31] |= 0b0100_0000;
|
|
24
|
+
|
|
25
|
+
return u8aConcat(priv, chainCode);
|
|
26
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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 { hdValidatePath } from './index.js';
|
|
7
|
+
|
|
8
|
+
const VECTORS: [string, boolean][] = [
|
|
9
|
+
["m/44'/60'/0'/0/0", true],
|
|
10
|
+
['m/0', true],
|
|
11
|
+
["m/123'", true],
|
|
12
|
+
["n/44'/60'/0'/0/0", false],
|
|
13
|
+
['m', false],
|
|
14
|
+
['m/', false],
|
|
15
|
+
["m/xyz'", false],
|
|
16
|
+
['m/123x', false],
|
|
17
|
+
['m/123"', false],
|
|
18
|
+
["m/123''", false],
|
|
19
|
+
["m/123'0'", false],
|
|
20
|
+
[`m/${0x80000000}`, false],
|
|
21
|
+
['m/-1', false]
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
describe('hdValidatePath', (): void => {
|
|
25
|
+
VECTORS.forEach(([path, result]): void => {
|
|
26
|
+
it(`validates ${path} as ${result.toString()}`, (): void => {
|
|
27
|
+
expect(hdValidatePath(path)).toEqual(result);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
export const HARDENED = 0x80000000;
|
|
5
|
+
|
|
6
|
+
export function hdValidatePath (path: string): boolean {
|
|
7
|
+
if (!path.startsWith('m/')) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const parts = path.split('/').slice(1);
|
|
12
|
+
|
|
13
|
+
for (const p of parts) {
|
|
14
|
+
const n = /^\d+'?$/.test(p)
|
|
15
|
+
? parseInt(p.replace(/'$/, ''), 10)
|
|
16
|
+
: Number.NaN;
|
|
17
|
+
|
|
18
|
+
if (isNaN(n) || (n >= HARDENED) || (n < 0)) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return true;
|
|
24
|
+
}
|
package/src/helpers.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { HexString } from '@pezkuwi/util/types';
|
|
5
|
+
|
|
6
|
+
import { hasBigInt, u8aToHex, u8aToU8a } from '@pezkuwi/util';
|
|
7
|
+
import { isReady } from '@pezkuwi/wasm-crypto';
|
|
8
|
+
|
|
9
|
+
// re-export so TS *.d.ts generation is correct
|
|
10
|
+
export type { HexString } from '@pezkuwi/util/types';
|
|
11
|
+
|
|
12
|
+
interface DualHash {
|
|
13
|
+
256: (u8a: Uint8Array) => Uint8Array;
|
|
14
|
+
512: (u8a: Uint8Array) => Uint8Array;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** @internal */
|
|
18
|
+
export function createAsHex <T extends (...args: never[]) => Uint8Array> (fn: T): (...args: Parameters<T>) => HexString {
|
|
19
|
+
return (...args: Parameters<T>): HexString =>
|
|
20
|
+
u8aToHex(fn(...args));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** @internal */
|
|
24
|
+
export function createBitHasher (bitLength: 256 | 512, fn: (data: string | Uint8Array, bitLength: 256 | 512, onlyJs?: boolean) => Uint8Array): (data: string | Uint8Array, onlyJs?: boolean) => Uint8Array {
|
|
25
|
+
return (data: string | Uint8Array, onlyJs?: boolean): Uint8Array =>
|
|
26
|
+
fn(data, bitLength, onlyJs);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** @internal */
|
|
30
|
+
export function createDualHasher (wa: DualHash, js: DualHash): (value: string | Uint8Array, bitLength?: 256 | 512, onlyJs?: boolean) => Uint8Array {
|
|
31
|
+
return (value: string | Uint8Array, bitLength: 256 | 512 = 256, onlyJs?: boolean): Uint8Array => {
|
|
32
|
+
const u8a = u8aToU8a(value);
|
|
33
|
+
|
|
34
|
+
return !hasBigInt || (!onlyJs && isReady())
|
|
35
|
+
? wa[bitLength](u8a)
|
|
36
|
+
: js[bitLength](u8a);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
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 } from '@pezkuwi/util';
|
|
7
|
+
import { waitReady } from '@pezkuwi/wasm-crypto';
|
|
8
|
+
|
|
9
|
+
import { perfWasm } from '../test/index.js';
|
|
10
|
+
import { hmacShaAsU8a } from './index.js';
|
|
11
|
+
|
|
12
|
+
describe('hmacShaAsU8a', (): void => {
|
|
13
|
+
beforeEach(async (): Promise<void> => {
|
|
14
|
+
await waitReady();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const key = stringToU8a('secret');
|
|
18
|
+
const data = stringToU8a('some message');
|
|
19
|
+
const output = {
|
|
20
|
+
256: hexToU8a(
|
|
21
|
+
'0xf28a70b41263840e5c059a0a733336e0957efba87902aa8cca11441d4b0c96d7'
|
|
22
|
+
),
|
|
23
|
+
512: hexToU8a(
|
|
24
|
+
'0x295832e97ed77be75a9fa98029497e4a722c4b9a2f21b39d34f1befa931a39ec520fd24711d6f5c03501384ea66b83066a01a82c57a0460f8cd1f471fcce5841'
|
|
25
|
+
)
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
for (const bitLength of [256, 512] as const) {
|
|
29
|
+
describe(`bitLength=${bitLength}`, (): void => {
|
|
30
|
+
for (const onlyJs of [false, true]) {
|
|
31
|
+
describe(`onlyJs=${(onlyJs && 'true') || 'false'}`, (): void => {
|
|
32
|
+
it('returns an hex representation (string)', (): void => {
|
|
33
|
+
expect(
|
|
34
|
+
hmacShaAsU8a(key, data, bitLength, onlyJs)
|
|
35
|
+
).toEqual(output[bitLength]);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
perfWasm(`hmacShaAsU8a, bitLength=${bitLength}`, 16000, (input, onlyJs) =>
|
|
42
|
+
hmacShaAsU8a(input, input, bitLength, onlyJs)
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { hmac } from '@noble/hashes/hmac';
|
|
5
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
6
|
+
import { sha512 } from '@noble/hashes/sha512';
|
|
7
|
+
|
|
8
|
+
import { hasBigInt, u8aToU8a } from '@pezkuwi/util';
|
|
9
|
+
import { hmacSha256, hmacSha512, isReady } from '@pezkuwi/wasm-crypto';
|
|
10
|
+
|
|
11
|
+
const JS_HASH = {
|
|
12
|
+
256: sha256,
|
|
13
|
+
512: sha512
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const WA_MHAC = {
|
|
17
|
+
256: hmacSha256,
|
|
18
|
+
512: hmacSha512
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function createSha (bitLength: 256 | 512): (key: Uint8Array | string, data: Uint8Array, onlyJs?: boolean) => Uint8Array {
|
|
22
|
+
return (key: Uint8Array | string, data: Uint8Array, onlyJs?: boolean): Uint8Array =>
|
|
23
|
+
hmacShaAsU8a(key, data, bitLength, onlyJs);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @name hmacShaAsU8a
|
|
28
|
+
* @description creates a Hmac Sha (256/512) Uint8Array from the key & data
|
|
29
|
+
*/
|
|
30
|
+
export function hmacShaAsU8a (key: Uint8Array | string, data: Uint8Array, bitLength: 256 | 512 = 256, onlyJs?: boolean): Uint8Array {
|
|
31
|
+
const u8aKey = u8aToU8a(key);
|
|
32
|
+
|
|
33
|
+
return !hasBigInt || (!onlyJs && isReady())
|
|
34
|
+
? WA_MHAC[bitLength](u8aKey, data)
|
|
35
|
+
: hmac(JS_HASH[bitLength], u8aKey, data);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @name hmacSha256AsU8a
|
|
40
|
+
* @description creates a Hmac Sha256 Uint8Array from the key & data
|
|
41
|
+
*/
|
|
42
|
+
export const hmacSha256AsU8a = /*#__PURE__*/ createSha(256);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @name hmacSha512AsU8a
|
|
46
|
+
* @description creates a Hmac Sha512 Uint8Array from the key & data
|
|
47
|
+
*/
|
|
48
|
+
export const hmacSha512AsU8a = /*#__PURE__*/ createSha(512);
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { EncryptedJsonEncoding, EncryptedJsonVersion } from './types.js';
|
|
5
|
+
|
|
6
|
+
export const ENCODING: EncryptedJsonEncoding[] = ['scrypt', 'xsalsa20-poly1305'];
|
|
7
|
+
export const ENCODING_NONE: EncryptedJsonEncoding[] = ['none'];
|
|
8
|
+
export const ENCODING_VERSION: EncryptedJsonVersion = '3';
|
|
9
|
+
|
|
10
|
+
export const NONCE_LENGTH = 24;
|
|
11
|
+
export const SCRYPT_LENGTH = 32 + (3 * 4);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { EncryptedJson } from './types.js';
|
|
5
|
+
|
|
6
|
+
import { hexToU8a, isHex } from '@pezkuwi/util';
|
|
7
|
+
|
|
8
|
+
import { base64Decode } from '../base64/index.js';
|
|
9
|
+
import { jsonDecryptData } from './decryptData.js';
|
|
10
|
+
|
|
11
|
+
export function jsonDecrypt ({ encoded, encoding }: EncryptedJson, passphrase?: string | null): Uint8Array {
|
|
12
|
+
if (!encoded) {
|
|
13
|
+
throw new Error('No encrypted data available to decode');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return jsonDecryptData(
|
|
17
|
+
isHex(encoded)
|
|
18
|
+
? hexToU8a(encoded)
|
|
19
|
+
: base64Decode(encoded),
|
|
20
|
+
passphrase,
|
|
21
|
+
Array.isArray(encoding.type)
|
|
22
|
+
? encoding.type
|
|
23
|
+
: [encoding.type]
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { EncryptedJsonEncoding } from './types.js';
|
|
5
|
+
|
|
6
|
+
import { stringToU8a, u8aFixLength } from '@pezkuwi/util';
|
|
7
|
+
|
|
8
|
+
import { naclDecrypt } from '../nacl/index.js';
|
|
9
|
+
import { scryptEncode, scryptFromU8a } from '../scrypt/index.js';
|
|
10
|
+
import { ENCODING, NONCE_LENGTH, SCRYPT_LENGTH } from './constants.js';
|
|
11
|
+
|
|
12
|
+
export function jsonDecryptData (encrypted?: Uint8Array | null, passphrase?: string | null, encType: EncryptedJsonEncoding[] = ENCODING): Uint8Array {
|
|
13
|
+
if (!encrypted) {
|
|
14
|
+
throw new Error('No encrypted data available to decode');
|
|
15
|
+
} else if (encType.includes('xsalsa20-poly1305') && !passphrase) {
|
|
16
|
+
throw new Error('Password required to decode encrypted data');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let encoded: Uint8Array | null = encrypted;
|
|
20
|
+
|
|
21
|
+
if (passphrase) {
|
|
22
|
+
let password: Uint8Array;
|
|
23
|
+
|
|
24
|
+
if (encType.includes('scrypt')) {
|
|
25
|
+
const { params, salt } = scryptFromU8a(encrypted);
|
|
26
|
+
|
|
27
|
+
password = scryptEncode(passphrase, salt, params).password;
|
|
28
|
+
encrypted = encrypted.subarray(SCRYPT_LENGTH);
|
|
29
|
+
} else {
|
|
30
|
+
password = stringToU8a(passphrase);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
encoded = naclDecrypt(
|
|
34
|
+
encrypted.subarray(NONCE_LENGTH),
|
|
35
|
+
encrypted.subarray(0, NONCE_LENGTH),
|
|
36
|
+
u8aFixLength(password, 256, true)
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!encoded) {
|
|
41
|
+
throw new Error('Unable to decode using the supplied passphrase');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return encoded;
|
|
45
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { EncryptedJson } from './types.js';
|
|
5
|
+
|
|
6
|
+
import { u8aConcat } from '@pezkuwi/util';
|
|
7
|
+
|
|
8
|
+
import { naclEncrypt } from '../nacl/index.js';
|
|
9
|
+
import { scryptEncode, scryptToU8a } from '../scrypt/index.js';
|
|
10
|
+
import { jsonEncryptFormat } from './encryptFormat.js';
|
|
11
|
+
|
|
12
|
+
export function jsonEncrypt (data: Uint8Array, contentType: string[], passphrase?: string | null): EncryptedJson {
|
|
13
|
+
let isEncrypted = false;
|
|
14
|
+
let encoded = data;
|
|
15
|
+
|
|
16
|
+
if (passphrase) {
|
|
17
|
+
const { params, password, salt } = scryptEncode(passphrase);
|
|
18
|
+
const { encrypted, nonce } = naclEncrypt(encoded, password.subarray(0, 32));
|
|
19
|
+
|
|
20
|
+
isEncrypted = true;
|
|
21
|
+
encoded = u8aConcat(scryptToU8a(salt, params), nonce, encrypted);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return jsonEncryptFormat(encoded, contentType, isEncrypted);
|
|
25
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { EncryptedJson } from './types.js';
|
|
5
|
+
|
|
6
|
+
import { base64Encode } from '../base64/index.js';
|
|
7
|
+
import { ENCODING, ENCODING_NONE, ENCODING_VERSION } from './constants.js';
|
|
8
|
+
|
|
9
|
+
export function jsonEncryptFormat (encoded: Uint8Array, contentType: string[], isEncrypted: boolean): EncryptedJson {
|
|
10
|
+
return {
|
|
11
|
+
encoded: base64Encode(encoded),
|
|
12
|
+
encoding: {
|
|
13
|
+
content: contentType,
|
|
14
|
+
type: isEncrypted
|
|
15
|
+
? ENCODING
|
|
16
|
+
: ENCODING_NONE,
|
|
17
|
+
version: ENCODING_VERSION
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
export { jsonDecrypt } from './decrypt.js';
|
|
5
|
+
export { jsonDecryptData } from './decryptData.js';
|
|
6
|
+
export { jsonEncrypt } from './encrypt.js';
|
|
7
|
+
export { jsonEncryptFormat } from './encryptFormat.js';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
export type EncryptedJsonVersion = '0' | '1' | '2' | '3';
|
|
5
|
+
|
|
6
|
+
export type EncryptedJsonEncoding = 'none' | 'scrypt' | 'xsalsa20-poly1305';
|
|
7
|
+
|
|
8
|
+
export interface EncryptedJsonDescriptor {
|
|
9
|
+
/** Descriptor for the content */
|
|
10
|
+
content: string[];
|
|
11
|
+
/** The encoding (in current/latest versions this is always an array) */
|
|
12
|
+
type: EncryptedJsonEncoding | EncryptedJsonEncoding[];
|
|
13
|
+
/** The version of encoding applied */
|
|
14
|
+
version: EncryptedJsonVersion;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface EncryptedJson {
|
|
18
|
+
/** The encoded string */
|
|
19
|
+
encoded: string;
|
|
20
|
+
/** The encoding used */
|
|
21
|
+
encoding: EncryptedJsonDescriptor;
|
|
22
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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 { keccakAsHex } from './index.js';
|
|
9
|
+
|
|
10
|
+
const BITS: (256 | 512)[] = [256, 512];
|
|
11
|
+
|
|
12
|
+
const value = 'test';
|
|
13
|
+
const result = {
|
|
14
|
+
256: '9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658',
|
|
15
|
+
512: '1e2e9fc2002b002d75198b7503210c05a1baac4560916a3c6d93bcce3a50d7f00fd395bf1647b9abb8d1afcc9c76c289b0c9383ba386a956da4b38934417789e'
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
describe('keccakAsHex', (): void => {
|
|
19
|
+
beforeEach(async (): Promise<void> => {
|
|
20
|
+
await waitReady();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
BITS.forEach((bitLength): void => {
|
|
24
|
+
it('returns a prefixed hex representation', (): void => {
|
|
25
|
+
expect(
|
|
26
|
+
keccakAsHex(value, bitLength)
|
|
27
|
+
).toEqual(`0x${result[bitLength]}`);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
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 } from '@pezkuwi/util';
|
|
7
|
+
import { waitReady } from '@pezkuwi/wasm-crypto';
|
|
8
|
+
|
|
9
|
+
import { perfWasm } from '../test/index.js';
|
|
10
|
+
import { keccakAsU8a } from './index.js';
|
|
11
|
+
|
|
12
|
+
describe('keccakAsU8a', (): void => {
|
|
13
|
+
beforeEach(async (): Promise<void> => {
|
|
14
|
+
await waitReady();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const input = 'test value';
|
|
18
|
+
const output = {
|
|
19
|
+
256: hexToU8a(
|
|
20
|
+
'0x2d07364b5c231c56ce63d49430e085ea3033c750688ba532b24029124c26ca5e'
|
|
21
|
+
),
|
|
22
|
+
512: hexToU8a(
|
|
23
|
+
'0xc1b50cc57f85ccd968a9d7c7a809dcebd140a548c8e0b67f3afcdd6fc14cca2b1d04187aef24ba0081b74f2ec362431e425760febe94a5607790854cafe5b197'
|
|
24
|
+
)
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
for (const bitLength of [256, 512] as const) {
|
|
28
|
+
describe(`bitLength=${bitLength}`, (): void => {
|
|
29
|
+
for (const onlyJs of [false, true]) {
|
|
30
|
+
describe(`onlyJs=${(onlyJs && 'true') || 'false'}`, (): void => {
|
|
31
|
+
it('returns an hex representation (string)', (): void => {
|
|
32
|
+
expect(
|
|
33
|
+
keccakAsU8a(input, bitLength, onlyJs)
|
|
34
|
+
).toEqual(output[bitLength]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('returns an hex representation (Buffer)', (): void => {
|
|
38
|
+
expect(
|
|
39
|
+
keccakAsU8a(Buffer.from(input), bitLength, onlyJs)
|
|
40
|
+
).toEqual(output[bitLength]);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('returns an hex representation (Uint8Array)', (): void => {
|
|
44
|
+
expect(
|
|
45
|
+
keccakAsU8a(stringToU8a(input), bitLength, onlyJs)
|
|
46
|
+
).toEqual(output[bitLength]);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
perfWasm(`keccakAsU8a, bitLength=${bitLength}`, 128000, (input, onlyJs) =>
|
|
52
|
+
keccakAsU8a(input, bitLength, onlyJs)
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { keccak_256 as keccak256Js, keccak_512 as keccak512Js } from '@noble/hashes/sha3';
|
|
5
|
+
|
|
6
|
+
import { keccak256, keccak512 } from '@pezkuwi/wasm-crypto';
|
|
7
|
+
|
|
8
|
+
import { createAsHex, createBitHasher, createDualHasher } from '../helpers.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @name keccakAsU8a
|
|
12
|
+
* @summary Creates a keccak Uint8Array from the input.
|
|
13
|
+
* @description
|
|
14
|
+
* From either a `string` or a `Buffer` input, create the keccak and return the result as a `Uint8Array`.
|
|
15
|
+
* @example
|
|
16
|
+
* <BR>
|
|
17
|
+
*
|
|
18
|
+
* ```javascript
|
|
19
|
+
* import { keccakAsU8a } from '@pezkuwi/util-crypto';
|
|
20
|
+
*
|
|
21
|
+
* keccakAsU8a('123'); // => Uint8Array
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export const keccakAsU8a = /*#__PURE__*/ createDualHasher(
|
|
25
|
+
{ 256: keccak256, 512: keccak512 },
|
|
26
|
+
{ 256: keccak256Js, 512: keccak512Js }
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @name keccak256AsU8a
|
|
31
|
+
* @description Creates a keccak256 Uint8Array from the input.
|
|
32
|
+
*/
|
|
33
|
+
export const keccak256AsU8a = /*#__PURE__*/ createBitHasher(256, keccakAsU8a);
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @name keccak512AsU8a
|
|
37
|
+
* @description Creates a keccak512 Uint8Array from the input.
|
|
38
|
+
*/
|
|
39
|
+
export const keccak512AsU8a = /*#__PURE__*/ createBitHasher(512, keccakAsU8a);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @name keccakAsHex
|
|
43
|
+
* @description Creates a keccak hex string from the input.
|
|
44
|
+
*/
|
|
45
|
+
export const keccakAsHex = /*#__PURE__*/ createAsHex(keccakAsU8a);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util-crypto authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @summary Create Keccak256/512 values as hex & Uint8Array output
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { keccak256AsU8a, keccak512AsU8a, keccakAsHex, keccakAsU8a } from './asU8a.js';
|