@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.
Files changed (234) hide show
  1. package/README.md +17 -0
  2. package/package.json +45 -0
  3. package/src/address/addressToEvm.spec.ts +16 -0
  4. package/src/address/addressToEvm.ts +12 -0
  5. package/src/address/check.spec.ts +44 -0
  6. package/src/address/check.ts +34 -0
  7. package/src/address/checksum.spec.ts +45 -0
  8. package/src/address/checksum.ts +25 -0
  9. package/src/address/decode.spec.ts +138 -0
  10. package/src/address/decode.ts +41 -0
  11. package/src/address/defaults.ts +12 -0
  12. package/src/address/derive.spec.ts +26 -0
  13. package/src/address/derive.ts +36 -0
  14. package/src/address/encode.spec.ts +177 -0
  15. package/src/address/encode.ts +43 -0
  16. package/src/address/encodeDerived.spec.ts +14 -0
  17. package/src/address/encodeDerived.ts +19 -0
  18. package/src/address/encodeMulti.spec.ts +18 -0
  19. package/src/address/encodeMulti.ts +18 -0
  20. package/src/address/eq.spec.ts +45 -0
  21. package/src/address/eq.ts +24 -0
  22. package/src/address/evmToAddress.spec.ts +20 -0
  23. package/src/address/evmToAddress.ts +24 -0
  24. package/src/address/index.ts +21 -0
  25. package/src/address/is.spec.ts +113 -0
  26. package/src/address/is.ts +14 -0
  27. package/src/address/keyDerived.spec.ts +24 -0
  28. package/src/address/keyDerived.ts +22 -0
  29. package/src/address/keyMulti.spec.ts +20 -0
  30. package/src/address/keyMulti.ts +23 -0
  31. package/src/address/setSS58Format.spec.ts +21 -0
  32. package/src/address/setSS58Format.ts +20 -0
  33. package/src/address/sort.spec.ts +22 -0
  34. package/src/address/sort.ts +17 -0
  35. package/src/address/sshash.ts +12 -0
  36. package/src/address/types.ts +6 -0
  37. package/src/address/util.ts +8 -0
  38. package/src/address/validate.spec.ts +113 -0
  39. package/src/address/validate.ts +10 -0
  40. package/src/base32/bs32.ts +53 -0
  41. package/src/base32/decode.spec.ts +34 -0
  42. package/src/base32/encode.spec.ts +30 -0
  43. package/src/base32/helpers.ts +93 -0
  44. package/src/base32/index.ts +8 -0
  45. package/src/base32/is.spec.ts +32 -0
  46. package/src/base32/validate.spec.ts +44 -0
  47. package/src/base58/bs58.ts +43 -0
  48. package/src/base58/decode.spec.ts +31 -0
  49. package/src/base58/encode.spec.ts +26 -0
  50. package/src/base58/index.ts +8 -0
  51. package/src/base58/validate.spec.ts +20 -0
  52. package/src/base64/bs64.ts +43 -0
  53. package/src/base64/decode.spec.ts +42 -0
  54. package/src/base64/encode.spec.ts +14 -0
  55. package/src/base64/index.ts +10 -0
  56. package/src/base64/pad.spec.ts +14 -0
  57. package/src/base64/pad.ts +10 -0
  58. package/src/base64/trim.spec.ts +14 -0
  59. package/src/base64/trim.ts +14 -0
  60. package/src/base64/validate.spec.ts +32 -0
  61. package/src/blake2/asHex.spec.ts +57 -0
  62. package/src/blake2/asU8a.spec.ts +74 -0
  63. package/src/blake2/asU8a.ts +40 -0
  64. package/src/blake2/index.ts +8 -0
  65. package/src/bn.ts +15 -0
  66. package/src/bundle.ts +33 -0
  67. package/src/bundleInit.ts +11 -0
  68. package/src/crypto.spec.ts +18 -0
  69. package/src/crypto.ts +18 -0
  70. package/src/ed25519/deriveHard.ts +18 -0
  71. package/src/ed25519/index.ts +13 -0
  72. package/src/ed25519/pair/fromRandom.spec.ts +28 -0
  73. package/src/ed25519/pair/fromRandom.ts +25 -0
  74. package/src/ed25519/pair/fromSecret.spec.ts +33 -0
  75. package/src/ed25519/pair/fromSecret.ts +29 -0
  76. package/src/ed25519/pair/fromSeed.spec.ts +42 -0
  77. package/src/ed25519/pair/fromSeed.ts +41 -0
  78. package/src/ed25519/pair/fromString.spec.ts +17 -0
  79. package/src/ed25519/pair/fromString.ts +31 -0
  80. package/src/ed25519/sign.spec.ts +40 -0
  81. package/src/ed25519/sign.ts +38 -0
  82. package/src/ed25519/verify.spec.ts +84 -0
  83. package/src/ed25519/verify.ts +41 -0
  84. package/src/ethereum/encode.spec.ts +59 -0
  85. package/src/ethereum/encode.ts +39 -0
  86. package/src/ethereum/index.ts +6 -0
  87. package/src/ethereum/isAddress.spec.ts +34 -0
  88. package/src/ethereum/isAddress.ts +16 -0
  89. package/src/ethereum/isChecksum.ts +27 -0
  90. package/src/ethereum/isCheksum.spec.ts +30 -0
  91. package/src/hd/ethereum/index.spec.ts +54 -0
  92. package/src/hd/ethereum/index.ts +69 -0
  93. package/src/hd/index.ts +6 -0
  94. package/src/hd/ledger/derivePrivate.ts +34 -0
  95. package/src/hd/ledger/index.spec.ts +64 -0
  96. package/src/hd/ledger/index.ts +42 -0
  97. package/src/hd/ledger/master.spec.ts +19 -0
  98. package/src/hd/ledger/master.ts +26 -0
  99. package/src/hd/validatePath.spec.ts +30 -0
  100. package/src/hd/validatePath.ts +24 -0
  101. package/src/helpers.ts +38 -0
  102. package/src/hmac/index.ts +4 -0
  103. package/src/hmac/shaAsU8a.spec.ts +45 -0
  104. package/src/hmac/shaAsU8a.ts +48 -0
  105. package/src/index.ts +6 -0
  106. package/src/json/constants.ts +11 -0
  107. package/src/json/decrypt.ts +25 -0
  108. package/src/json/decryptData.ts +45 -0
  109. package/src/json/encrypt.ts +25 -0
  110. package/src/json/encryptFormat.ts +20 -0
  111. package/src/json/index.ts +7 -0
  112. package/src/json/types.ts +22 -0
  113. package/src/keccak/asHex.spec.ts +30 -0
  114. package/src/keccak/asU8a.spec.ts +56 -0
  115. package/src/keccak/asU8a.ts +45 -0
  116. package/src/keccak/index.ts +8 -0
  117. package/src/key/DeriveJunction.ts +79 -0
  118. package/src/key/extractPath.spec.ts +51 -0
  119. package/src/key/extractPath.ts +37 -0
  120. package/src/key/extractSuri.spec.ts +147 -0
  121. package/src/key/extractSuri.ts +40 -0
  122. package/src/key/fromPath.ts +28 -0
  123. package/src/key/hdkdDerive.ts +17 -0
  124. package/src/key/hdkdEcdsa.ts +8 -0
  125. package/src/key/hdkdEd25519.ts +7 -0
  126. package/src/key/hdkdSr25519.ts +14 -0
  127. package/src/key/index.ts +12 -0
  128. package/src/mnemonic/bip39.spec.ts +80 -0
  129. package/src/mnemonic/bip39.ts +127 -0
  130. package/src/mnemonic/generate.spec.ts +58 -0
  131. package/src/mnemonic/generate.ts +25 -0
  132. package/src/mnemonic/index.ts +11 -0
  133. package/src/mnemonic/toEntropy.spec.ts +36 -0
  134. package/src/mnemonic/toEntropy.ts +13 -0
  135. package/src/mnemonic/toLegacySeed.spec.ts +52 -0
  136. package/src/mnemonic/toLegacySeed.ts +39 -0
  137. package/src/mnemonic/toMiniSecret.spec.ts +67 -0
  138. package/src/mnemonic/toMiniSecret.ts +23 -0
  139. package/src/mnemonic/toMiniSecretCmp.spec.ts +64 -0
  140. package/src/mnemonic/validate.spec.ts +39 -0
  141. package/src/mnemonic/validate.ts +26 -0
  142. package/src/mnemonic/wordlists/en.ts +7 -0
  143. package/src/mnemonic/wordlists/es.ts +7 -0
  144. package/src/mnemonic/wordlists/fr.ts +7 -0
  145. package/src/mnemonic/wordlists/index.ts +11 -0
  146. package/src/mnemonic/wordlists/it.ts +7 -0
  147. package/src/mnemonic/wordlists/jp.ts +7 -0
  148. package/src/mnemonic/wordlists/ko.ts +7 -0
  149. package/src/mnemonic/wordlists/zh-s.ts +7 -0
  150. package/src/mnemonic/wordlists/zh-t.ts +7 -0
  151. package/src/mod.ts +4 -0
  152. package/src/nacl/decrypt.spec.ts +26 -0
  153. package/src/nacl/decrypt.ts +22 -0
  154. package/src/nacl/encrypt.spec.ts +20 -0
  155. package/src/nacl/encrypt.ts +31 -0
  156. package/src/nacl/index.ts +8 -0
  157. package/src/nacl/tweetnacl-secretbox-data.spec.ts +4629 -0
  158. package/src/nacl/tweetnacl-secretbox.spec.ts +161 -0
  159. package/src/nacl/tweetnacl.ts +1159 -0
  160. package/src/networks.ts +5 -0
  161. package/src/packageDetect.ts +14 -0
  162. package/src/packageInfo.ts +6 -0
  163. package/src/pbkdf2/encode.spec.ts +54 -0
  164. package/src/pbkdf2/encode.ts +29 -0
  165. package/src/pbkdf2/index.ts +4 -0
  166. package/src/random/asHex.spec.ts +38 -0
  167. package/src/random/asNumber.spec.ts +16 -0
  168. package/src/random/asNumber.ts +28 -0
  169. package/src/random/asU8a.spec.ts +36 -0
  170. package/src/random/asU8a.ts +30 -0
  171. package/src/random/index.ts +9 -0
  172. package/src/scrypt/defaults.ts +19 -0
  173. package/src/scrypt/encode.spec.ts +43 -0
  174. package/src/scrypt/encode.ts +30 -0
  175. package/src/scrypt/fromU8a.ts +44 -0
  176. package/src/scrypt/index.ts +6 -0
  177. package/src/scrypt/toU8a.ts +17 -0
  178. package/src/scrypt/types.ts +9 -0
  179. package/src/secp256k1/compress.spec.ts +47 -0
  180. package/src/secp256k1/compress.ts +21 -0
  181. package/src/secp256k1/deriveHard.ts +17 -0
  182. package/src/secp256k1/expand.spec.ts +47 -0
  183. package/src/secp256k1/expand.ts +30 -0
  184. package/src/secp256k1/hasher.spec.ts +24 -0
  185. package/src/secp256k1/hasher.ts +13 -0
  186. package/src/secp256k1/index.ts +10 -0
  187. package/src/secp256k1/pair/fromSeed.spec.ts +75 -0
  188. package/src/secp256k1/pair/fromSeed.ts +42 -0
  189. package/src/secp256k1/recover.spec.ts +35 -0
  190. package/src/secp256k1/recover.ts +36 -0
  191. package/src/secp256k1/sign.spec.ts +39 -0
  192. package/src/secp256k1/sign.ts +37 -0
  193. package/src/secp256k1/signVerify.spec.ts +94 -0
  194. package/src/secp256k1/tweakAdd.spec.ts +35 -0
  195. package/src/secp256k1/tweakAdd.ts +65 -0
  196. package/src/secp256k1/types.ts +4 -0
  197. package/src/secp256k1/verify.spec.ts +81 -0
  198. package/src/secp256k1/verify.ts +32 -0
  199. package/src/sha/asU8a.ts +30 -0
  200. package/src/sha/asU8a256.spec.ts +55 -0
  201. package/src/sha/asU8a512.spec.ts +33 -0
  202. package/src/sha/index.ts +8 -0
  203. package/src/signature/index.ts +8 -0
  204. package/src/signature/verify.spec.ts +230 -0
  205. package/src/signature/verify.ts +114 -0
  206. package/src/sr25519/agreement.spec.ts +31 -0
  207. package/src/sr25519/agreement.ts +23 -0
  208. package/src/sr25519/derive.ts +21 -0
  209. package/src/sr25519/deriveHard.ts +9 -0
  210. package/src/sr25519/derivePublic.ts +18 -0
  211. package/src/sr25519/deriveSoft.ts +9 -0
  212. package/src/sr25519/index.ts +12 -0
  213. package/src/sr25519/pair/fromSeed.spec.ts +35 -0
  214. package/src/sr25519/pair/fromSeed.ts +28 -0
  215. package/src/sr25519/pair/fromU8a.ts +23 -0
  216. package/src/sr25519/pair/testing.spec.ts +161 -0
  217. package/src/sr25519/pair/toU8a.ts +10 -0
  218. package/src/sr25519/sign.spec.ts +28 -0
  219. package/src/sr25519/sign.ts +22 -0
  220. package/src/sr25519/verify.spec.ts +42 -0
  221. package/src/sr25519/verify.ts +23 -0
  222. package/src/sr25519/vrfSign.ts +24 -0
  223. package/src/sr25519/vrfSignVerify.spec.ts +73 -0
  224. package/src/sr25519/vrfVerify.ts +25 -0
  225. package/src/test/index.ts +8 -0
  226. package/src/test/performance.ts +17 -0
  227. package/src/types.ts +33 -0
  228. package/src/xxhash/asHex.spec.ts +36 -0
  229. package/src/xxhash/asU8a.spec.ts +48 -0
  230. package/src/xxhash/asU8a.ts +45 -0
  231. package/src/xxhash/index.ts +8 -0
  232. package/src/xxhash/xxhash64.ts +155 -0
  233. package/tsconfig.build.json +18 -0
  234. 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,4 @@
1
+ // Copyright 2017-2025 @polkadot/util-crypto authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export { hmacSha256AsU8a, hmacSha512AsU8a, hmacShaAsU8a } from './shaAsU8a.js';
@@ -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,6 @@
1
+ // Copyright 2017-2025 @polkadot/util-crypto authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import './packageDetect.js';
5
+
6
+ export * from './bundle.js';
@@ -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';