ox 1.0.5 → 1.1.2

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 (337) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/dist/core/Base64.d.ts +10 -21
  3. package/dist/core/Base64.d.ts.map +1 -1
  4. package/dist/core/Base64.js +8 -127
  5. package/dist/core/Base64.js.map +1 -1
  6. package/dist/core/BinaryStateTree.d.ts.map +1 -1
  7. package/dist/core/BinaryStateTree.js +2 -2
  8. package/dist/core/BinaryStateTree.js.map +1 -1
  9. package/dist/core/Bls.d.ts.map +1 -1
  10. package/dist/core/Bls.js +19 -44
  11. package/dist/core/Bls.js.map +1 -1
  12. package/dist/core/Ed25519.d.ts.map +1 -1
  13. package/dist/core/Ed25519.js +7 -6
  14. package/dist/core/Ed25519.js.map +1 -1
  15. package/dist/core/Engine.d.ts +156 -0
  16. package/dist/core/Engine.d.ts.map +1 -0
  17. package/dist/core/Engine.js +210 -0
  18. package/dist/core/Engine.js.map +1 -0
  19. package/dist/core/Hash.d.ts +4 -4
  20. package/dist/core/Hash.d.ts.map +1 -1
  21. package/dist/core/Hash.js +9 -12
  22. package/dist/core/Hash.js.map +1 -1
  23. package/dist/core/Keystore.d.ts.map +1 -1
  24. package/dist/core/Keystore.js +15 -10
  25. package/dist/core/Keystore.js.map +1 -1
  26. package/dist/core/Mnemonic.d.ts.map +1 -1
  27. package/dist/core/Mnemonic.js +3 -2
  28. package/dist/core/Mnemonic.js.map +1 -1
  29. package/dist/core/P256.d.ts.map +1 -1
  30. package/dist/core/P256.js +8 -9
  31. package/dist/core/P256.js.map +1 -1
  32. package/dist/core/Secp256k1.d.ts.map +1 -1
  33. package/dist/core/Secp256k1.js +8 -9
  34. package/dist/core/Secp256k1.js.map +1 -1
  35. package/dist/core/WebCryptoP256.d.ts.map +1 -1
  36. package/dist/core/WebCryptoP256.js +2 -2
  37. package/dist/core/WebCryptoP256.js.map +1 -1
  38. package/dist/core/X25519.d.ts.map +1 -1
  39. package/dist/core/X25519.js +4 -3
  40. package/dist/core/X25519.js.map +1 -1
  41. package/dist/core/internal/bls.d.ts +12 -0
  42. package/dist/core/internal/bls.d.ts.map +1 -0
  43. package/dist/core/internal/bls.js +79 -0
  44. package/dist/core/internal/bls.js.map +1 -0
  45. package/dist/core/internal/codec/base64.d.ts +84 -0
  46. package/dist/core/internal/codec/base64.d.ts.map +1 -0
  47. package/dist/core/internal/codec/base64.js +177 -0
  48. package/dist/core/internal/codec/base64.js.map +1 -0
  49. package/dist/core/internal/codec/hex.d.ts +49 -4
  50. package/dist/core/internal/codec/hex.d.ts.map +1 -1
  51. package/dist/core/internal/codec/hex.js +109 -35
  52. package/dist/core/internal/codec/hex.js.map +1 -1
  53. package/dist/core/internal/curves.d.ts +17 -0
  54. package/dist/core/internal/curves.d.ts.map +1 -0
  55. package/dist/core/internal/curves.js +17 -0
  56. package/dist/core/internal/curves.js.map +1 -0
  57. package/dist/core/internal/ed25519.d.ts +14 -0
  58. package/dist/core/internal/ed25519.d.ts.map +1 -0
  59. package/dist/core/internal/ed25519.js +29 -0
  60. package/dist/core/internal/ed25519.js.map +1 -0
  61. package/dist/core/internal/engine.d.ts +278 -0
  62. package/dist/core/internal/engine.d.ts.map +1 -0
  63. package/dist/core/internal/engine.js +131 -0
  64. package/dist/core/internal/engine.js.map +1 -0
  65. package/dist/core/internal/hash.d.ts +12 -0
  66. package/dist/core/internal/hash.d.ts.map +1 -0
  67. package/dist/core/internal/hash.js +30 -0
  68. package/dist/core/internal/hash.js.map +1 -0
  69. package/dist/core/internal/keystore.d.ts +14 -0
  70. package/dist/core/internal/keystore.d.ts.map +1 -0
  71. package/dist/core/internal/keystore.js +32 -0
  72. package/dist/core/internal/keystore.js.map +1 -0
  73. package/dist/core/internal/mnemonic.d.ts +4 -0
  74. package/dist/core/internal/mnemonic.d.ts.map +1 -0
  75. package/dist/core/internal/mnemonic.js +14 -0
  76. package/dist/core/internal/mnemonic.js.map +1 -0
  77. package/dist/core/internal/p256.d.ts +14 -0
  78. package/dist/core/internal/p256.d.ts.map +1 -0
  79. package/dist/core/internal/p256.js +36 -0
  80. package/dist/core/internal/p256.js.map +1 -0
  81. package/dist/core/internal/secp256k1.d.ts +14 -0
  82. package/dist/core/internal/secp256k1.d.ts.map +1 -0
  83. package/dist/core/internal/secp256k1.js +36 -0
  84. package/dist/core/internal/secp256k1.js.map +1 -0
  85. package/dist/core/internal/x25519.d.ts +8 -0
  86. package/dist/core/internal/x25519.d.ts.map +1 -0
  87. package/dist/core/internal/x25519.js +20 -0
  88. package/dist/core/internal/x25519.js.map +1 -0
  89. package/dist/index.d.ts +38 -0
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.docs.d.ts +2 -0
  92. package/dist/index.docs.d.ts.map +1 -1
  93. package/dist/index.docs.js +2 -0
  94. package/dist/index.docs.js.map +1 -1
  95. package/dist/index.js +38 -0
  96. package/dist/index.js.map +1 -1
  97. package/dist/node/Ed25519.d.ts +33 -0
  98. package/dist/node/Ed25519.d.ts.map +1 -0
  99. package/dist/node/Ed25519.js +67 -0
  100. package/dist/node/Ed25519.js.map +1 -0
  101. package/dist/node/Engine.d.ts +68 -0
  102. package/dist/node/Engine.d.ts.map +1 -0
  103. package/dist/node/Engine.js +75 -0
  104. package/dist/node/Engine.js.map +1 -0
  105. package/dist/node/Hash.d.ts +37 -0
  106. package/dist/node/Hash.d.ts.map +1 -0
  107. package/dist/node/Hash.js +35 -0
  108. package/dist/node/Hash.js.map +1 -0
  109. package/dist/node/Keystore.d.ts +36 -0
  110. package/dist/node/Keystore.d.ts.map +1 -0
  111. package/dist/node/Keystore.js +72 -0
  112. package/dist/node/Keystore.js.map +1 -0
  113. package/dist/node/Mnemonic.d.ts +35 -0
  114. package/dist/node/Mnemonic.d.ts.map +1 -0
  115. package/dist/node/Mnemonic.js +46 -0
  116. package/dist/node/Mnemonic.js.map +1 -0
  117. package/dist/node/P256.d.ts +32 -0
  118. package/dist/node/P256.d.ts.map +1 -0
  119. package/dist/node/P256.js +34 -0
  120. package/dist/node/P256.js.map +1 -0
  121. package/dist/node/X25519.d.ts +31 -0
  122. package/dist/node/X25519.d.ts.map +1 -0
  123. package/dist/node/X25519.js +71 -0
  124. package/dist/node/X25519.js.map +1 -0
  125. package/dist/node/index.d.ts +126 -0
  126. package/dist/node/index.d.ts.map +1 -0
  127. package/dist/node/index.js +126 -0
  128. package/dist/node/index.js.map +1 -0
  129. package/dist/tempo/VirtualMaster.d.ts +2 -0
  130. package/dist/tempo/VirtualMaster.d.ts.map +1 -1
  131. package/dist/tempo/VirtualMaster.js +19 -5
  132. package/dist/tempo/VirtualMaster.js.map +1 -1
  133. package/dist/tempo/internal/mine.wasm.d.ts +2 -4
  134. package/dist/tempo/internal/mine.wasm.d.ts.map +1 -1
  135. package/dist/tempo/internal/mine.wasm.js +7 -12
  136. package/dist/tempo/internal/mine.wasm.js.map +1 -1
  137. package/dist/tempo/internal/virtualMasterPool.js +4 -1
  138. package/dist/tempo/internal/virtualMasterPool.js.map +1 -1
  139. package/dist/wasm/Ed25519.d.ts +35 -0
  140. package/dist/wasm/Ed25519.d.ts.map +1 -0
  141. package/dist/wasm/Ed25519.js +88 -0
  142. package/dist/wasm/Ed25519.js.map +1 -0
  143. package/dist/wasm/Engine.d.ts +71 -0
  144. package/dist/wasm/Engine.d.ts.map +1 -0
  145. package/dist/wasm/Engine.js +76 -0
  146. package/dist/wasm/Engine.js.map +1 -0
  147. package/dist/wasm/Hash.d.ts +43 -0
  148. package/dist/wasm/Hash.d.ts.map +1 -0
  149. package/dist/wasm/Hash.js +64 -0
  150. package/dist/wasm/Hash.js.map +1 -0
  151. package/dist/wasm/Keystore.d.ts +37 -0
  152. package/dist/wasm/Keystore.d.ts.map +1 -0
  153. package/dist/wasm/Keystore.js +34 -0
  154. package/dist/wasm/Keystore.js.map +1 -0
  155. package/dist/wasm/Mnemonic.d.ts +33 -0
  156. package/dist/wasm/Mnemonic.d.ts.map +1 -0
  157. package/dist/wasm/Mnemonic.js +30 -0
  158. package/dist/wasm/Mnemonic.js.map +1 -0
  159. package/dist/wasm/X25519.d.ts +33 -0
  160. package/dist/wasm/X25519.d.ts.map +1 -0
  161. package/dist/wasm/X25519.js +53 -0
  162. package/dist/wasm/X25519.js.map +1 -0
  163. package/dist/wasm/index.d.ts +115 -0
  164. package/dist/wasm/index.d.ts.map +1 -0
  165. package/dist/wasm/index.js +115 -0
  166. package/dist/wasm/index.js.map +1 -0
  167. package/dist/wasm/internal/blake3.d.ts +11 -0
  168. package/dist/wasm/internal/blake3.d.ts.map +1 -0
  169. package/dist/wasm/internal/blake3.js +31 -0
  170. package/dist/wasm/internal/blake3.js.map +1 -0
  171. package/dist/wasm/internal/blake3.wasm.d.ts +3 -0
  172. package/dist/wasm/internal/blake3.wasm.d.ts.map +1 -0
  173. package/dist/wasm/internal/blake3.wasm.js +10 -0
  174. package/dist/wasm/internal/blake3.wasm.js.map +1 -0
  175. package/dist/wasm/internal/crypto25519.d.ts +16 -0
  176. package/dist/wasm/internal/crypto25519.d.ts.map +1 -0
  177. package/dist/wasm/internal/crypto25519.js +5 -0
  178. package/dist/wasm/internal/crypto25519.js.map +1 -0
  179. package/dist/wasm/internal/crypto25519.wasm.d.ts +3 -0
  180. package/dist/wasm/internal/crypto25519.wasm.d.ts.map +1 -0
  181. package/dist/wasm/internal/crypto25519.wasm.js +10 -0
  182. package/dist/wasm/internal/crypto25519.wasm.js.map +1 -0
  183. package/dist/wasm/internal/ed25519.d.ts +4 -0
  184. package/dist/wasm/internal/ed25519.d.ts.map +1 -0
  185. package/dist/wasm/internal/ed25519.js +21 -0
  186. package/dist/wasm/internal/ed25519.js.map +1 -0
  187. package/dist/wasm/internal/hash.d.ts +9 -0
  188. package/dist/wasm/internal/hash.d.ts.map +1 -0
  189. package/dist/wasm/internal/hash.js +26 -0
  190. package/dist/wasm/internal/hash.js.map +1 -0
  191. package/dist/wasm/internal/hashes.d.ts +12 -0
  192. package/dist/wasm/internal/hashes.d.ts.map +1 -0
  193. package/dist/wasm/internal/hashes.js +8 -0
  194. package/dist/wasm/internal/hashes.js.map +1 -0
  195. package/dist/wasm/internal/hashes.wasm.d.ts +7 -0
  196. package/dist/wasm/internal/hashes.wasm.d.ts.map +1 -0
  197. package/dist/wasm/internal/hashes.wasm.js +14 -0
  198. package/dist/wasm/internal/hashes.wasm.js.map +1 -0
  199. package/dist/wasm/internal/instantiate.d.ts +56 -0
  200. package/dist/wasm/internal/instantiate.d.ts.map +1 -0
  201. package/dist/wasm/internal/instantiate.js +92 -0
  202. package/dist/wasm/internal/instantiate.js.map +1 -0
  203. package/dist/wasm/internal/mnemonic.d.ts +4 -0
  204. package/dist/wasm/internal/mnemonic.d.ts.map +1 -0
  205. package/dist/wasm/internal/mnemonic.js +45 -0
  206. package/dist/wasm/internal/mnemonic.js.map +1 -0
  207. package/dist/wasm/internal/pbkdf2.d.ts +12 -0
  208. package/dist/wasm/internal/pbkdf2.d.ts.map +1 -0
  209. package/dist/wasm/internal/pbkdf2.js +51 -0
  210. package/dist/wasm/internal/pbkdf2.js.map +1 -0
  211. package/dist/wasm/internal/x25519.d.ts +4 -0
  212. package/dist/wasm/internal/x25519.d.ts.map +1 -0
  213. package/dist/wasm/internal/x25519.js +21 -0
  214. package/dist/wasm/internal/x25519.js.map +1 -0
  215. package/dist/zod/TypedData.d.ts +12 -12
  216. package/package.json +81 -1
  217. package/src/core/Base64.ts +19 -166
  218. package/src/core/BinaryStateTree.ts +2 -3
  219. package/src/core/Bls.ts +27 -77
  220. package/src/core/Ed25519.ts +7 -7
  221. package/src/core/Engine.ts +308 -0
  222. package/src/core/Hash.ts +9 -12
  223. package/src/core/Keystore.ts +17 -17
  224. package/src/core/Mnemonic.ts +3 -6
  225. package/src/core/P256.ts +15 -24
  226. package/src/core/Rlp_tx.bench.ts +2 -4
  227. package/src/core/Secp256k1.ts +9 -14
  228. package/src/core/TxEnvelopeEip1559.bench.ts +0 -5
  229. package/src/core/WebCryptoP256.ts +2 -2
  230. package/src/core/X25519.ts +4 -3
  231. package/src/core/_test/AbiParameters.adversarial.fuzz.ts +1 -2
  232. package/src/core/_test/AbiParameters.fuzz.ts +1 -2
  233. package/src/core/_test/Base.fuzz.ts +1 -2
  234. package/src/core/_test/Cbor.fuzz.ts +1 -2
  235. package/src/core/_test/Engine.fuzz.ts +293 -0
  236. package/src/core/_test/Engine.test-d.ts +140 -0
  237. package/src/core/_test/Engine.test.ts +618 -0
  238. package/src/core/_test/Hash.vectors.test.ts +64 -0
  239. package/src/core/_test/Hex.fuzz.ts +1 -2
  240. package/src/core/_test/Rlp.fuzz.ts +1 -2
  241. package/src/core/_test/Signature.fuzz.ts +1 -2
  242. package/src/core/_test/curves.test.ts +7 -0
  243. package/src/core/_test/index.test.ts +1 -0
  244. package/src/core/internal/bls.ts +121 -0
  245. package/src/core/internal/codec/_test/base64.conformance.ts +156 -0
  246. package/src/core/internal/codec/_test/hex.conformance.ts +204 -0
  247. package/src/core/internal/codec/_test/hex.fuzz.ts +234 -0
  248. package/src/core/internal/codec/_test/hex.test.ts +124 -0
  249. package/src/core/internal/codec/base64.ts +222 -0
  250. package/src/core/internal/codec/hex.ts +115 -34
  251. package/src/core/internal/curves.ts +18 -0
  252. package/src/core/internal/ed25519.ts +64 -0
  253. package/src/core/internal/engine.ts +410 -0
  254. package/src/core/internal/hash.ts +48 -0
  255. package/src/core/internal/keystore.ts +107 -0
  256. package/src/core/internal/mnemonic.ts +18 -0
  257. package/src/core/internal/p256.ts +91 -0
  258. package/src/core/internal/secp256k1.ts +91 -0
  259. package/src/core/internal/x25519.ts +40 -0
  260. package/src/index.docs.ts +2 -0
  261. package/src/index.ts +39 -0
  262. package/src/node/Ed25519.ts +87 -0
  263. package/src/node/Engine.ts +125 -0
  264. package/src/node/Hash.ts +51 -0
  265. package/src/node/Keystore.ts +103 -0
  266. package/src/node/Mnemonic.ts +68 -0
  267. package/src/node/P256.ts +48 -0
  268. package/src/node/X25519.ts +93 -0
  269. package/src/node/_test/Curves.fuzz.ts +76 -0
  270. package/src/node/_test/Ed25519.test-d.ts +35 -0
  271. package/src/node/_test/Ed25519.test.ts +220 -0
  272. package/src/node/_test/Engine.test-d.ts +28 -0
  273. package/src/node/_test/Engine.test.ts +102 -0
  274. package/src/node/_test/Hash.test-d.ts +32 -0
  275. package/src/node/_test/Hash.test.ts +101 -0
  276. package/src/node/_test/Keystore.fuzz.ts +58 -0
  277. package/src/node/_test/Keystore.test-d.ts +43 -0
  278. package/src/node/_test/Keystore.test.ts +198 -0
  279. package/src/node/_test/Mnemonic.fuzz.ts +31 -0
  280. package/src/node/_test/Mnemonic.test-d.ts +21 -0
  281. package/src/node/_test/Mnemonic.test.ts +98 -0
  282. package/src/node/_test/P256.test-d.ts +29 -0
  283. package/src/node/_test/P256.test.ts +102 -0
  284. package/src/node/_test/X25519.test-d.ts +28 -0
  285. package/src/node/_test/X25519.test.ts +239 -0
  286. package/src/node/index.ts +132 -0
  287. package/src/tempo/VirtualMaster.test.ts +75 -0
  288. package/src/tempo/VirtualMaster.ts +28 -6
  289. package/src/tempo/internal/mine.wasm.ts +7 -13
  290. package/src/tempo/internal/virtualMasterPool.ts +4 -1
  291. package/src/tsconfig.json +2 -1
  292. package/src/version.ts +1 -1
  293. package/src/wasm/Ed25519.ts +114 -0
  294. package/src/wasm/Engine.ts +121 -0
  295. package/src/wasm/Hash.bench.ts +60 -0
  296. package/src/wasm/Hash.ts +88 -0
  297. package/src/wasm/Keystore.ts +48 -0
  298. package/src/wasm/Mnemonic.ts +44 -0
  299. package/src/wasm/X25519.ts +70 -0
  300. package/src/wasm/_test/Crypto25519.conformance.ts +57 -0
  301. package/src/wasm/_test/Crypto25519.fuzz.ts +187 -0
  302. package/src/wasm/_test/Ed25519.test-d.ts +28 -0
  303. package/src/wasm/_test/Ed25519.test.ts +168 -0
  304. package/src/wasm/_test/Ed25519.vectors.test.ts +73 -0
  305. package/src/wasm/_test/Engine.test-d.ts +28 -0
  306. package/src/wasm/_test/Engine.test.ts +96 -0
  307. package/src/wasm/_test/Hash.browser.test.ts +54 -0
  308. package/src/wasm/_test/Hash.fuzz.ts +223 -0
  309. package/src/wasm/_test/Hash.test-d.ts +33 -0
  310. package/src/wasm/_test/Hash.test.ts +311 -0
  311. package/src/wasm/_test/Hash.vectors.test.ts +124 -0
  312. package/src/wasm/_test/Keystore.browser.test.ts +42 -0
  313. package/src/wasm/_test/Keystore.fuzz.ts +113 -0
  314. package/src/wasm/_test/Keystore.test-d.ts +33 -0
  315. package/src/wasm/_test/Keystore.test.ts +192 -0
  316. package/src/wasm/_test/Keystore.vectors.test.ts +21 -0
  317. package/src/wasm/_test/Mnemonic.test-d.ts +17 -0
  318. package/src/wasm/_test/Mnemonic.test.ts +110 -0
  319. package/src/wasm/_test/Runtime.test.ts +21 -0
  320. package/src/wasm/_test/X25519.test-d.ts +21 -0
  321. package/src/wasm/_test/X25519.test.ts +194 -0
  322. package/src/wasm/_test/fixtures.ts +4 -0
  323. package/src/wasm/_test/runtime.wasm.ts +11 -0
  324. package/src/wasm/index.ts +120 -0
  325. package/src/wasm/internal/blake3.ts +45 -0
  326. package/src/wasm/internal/blake3.wasm.ts +11 -0
  327. package/src/wasm/internal/crypto25519.ts +43 -0
  328. package/src/wasm/internal/crypto25519.wasm.ts +11 -0
  329. package/src/wasm/internal/ed25519.ts +31 -0
  330. package/src/wasm/internal/hash.ts +50 -0
  331. package/src/wasm/internal/hashes.ts +29 -0
  332. package/src/wasm/internal/hashes.wasm.ts +17 -0
  333. package/src/wasm/internal/instantiate.ts +135 -0
  334. package/src/wasm/internal/mnemonic.ts +56 -0
  335. package/src/wasm/internal/pbkdf2.ts +86 -0
  336. package/src/wasm/internal/x25519.ts +29 -0
  337. package/src/tempo/internal/mine.c +0 -182
@@ -0,0 +1,98 @@
1
+ import { mnemonicToSeedSync } from '@scure/bip39'
2
+ import { Hex } from 'ox'
3
+ import { describe, expect, test } from 'vp/test'
4
+ import * as bip39 from '../../../test/vectors/bip39/index.js'
5
+ import * as Mnemonic from '../Mnemonic.js'
6
+
7
+ describe('engine', () => {
8
+ test('behavior: matches the BIP-39 English vector', async () => {
9
+ const { toSeed } = await Mnemonic.engine()
10
+ const { mnemonic, passphrase, seed } = bip39.vectors.english
11
+
12
+ expect(Hex.fromBytes(toSeed(mnemonic, passphrase))).toBe(`0x${seed}`)
13
+ })
14
+
15
+ test('behavior: matches the BIP-39 Japanese Unicode vector', async () => {
16
+ const { toSeed } = await Mnemonic.engine()
17
+ const { mnemonic, passphrase, seed } = bip39.vectors.japanese
18
+
19
+ expect(Hex.fromBytes(toSeed(mnemonic, passphrase))).toBe(`0x${seed}`)
20
+ })
21
+
22
+ test('behavior: applies BIP-39 NFKD normalization', async () => {
23
+ const { toSeed } = await Mnemonic.engine()
24
+ const composed = Array.from({ length: 12 }, () => 'café').join(' ')
25
+ const decomposed = Array.from({ length: 12 }, () => 'cafe\u0301').join(' ')
26
+
27
+ expect(toSeed(composed, 'pássphrase')).toEqual(
28
+ toSeed(decomposed, 'pa\u0301ssphrase'),
29
+ )
30
+ expect(toSeed(composed, 'pássphrase')).toEqual(
31
+ mnemonicToSeedSync(composed, 'pássphrase'),
32
+ )
33
+ })
34
+
35
+ test('behavior: accepts every supported phrase length', async () => {
36
+ const { toSeed } = await Mnemonic.engine()
37
+
38
+ expect(
39
+ [12, 15, 18, 21, 24].map(
40
+ (length) =>
41
+ toSeed(Array.from({ length }, () => 'word').join(' ')).length,
42
+ ),
43
+ ).toMatchInlineSnapshot(`
44
+ [
45
+ 64,
46
+ 64,
47
+ 64,
48
+ 64,
49
+ 64,
50
+ ]
51
+ `)
52
+ })
53
+
54
+ test('behavior: rejects unsupported phrase lengths', async () => {
55
+ const { toSeed } = await Mnemonic.engine()
56
+
57
+ for (const length of [0, 1, 11, 13, 23, 25])
58
+ expect(() =>
59
+ toSeed(Array.from({ length }, () => 'word').join(' ')),
60
+ ).toThrowErrorMatchingInlineSnapshot(`[Error: Invalid mnemonic]`)
61
+ })
62
+
63
+ test('behavior: agrees with the default for localized input', async () => {
64
+ const { toSeed } = await Mnemonic.engine()
65
+ const mnemonic = Array.from({ length: 12 }, () => 'あおぞら').join(' ')
66
+ const passphrase = '㍍ガバヴァぱばぐゞちぢ十人十色'
67
+
68
+ expect(toSeed(mnemonic, passphrase)).toEqual(
69
+ mnemonicToSeedSync(mnemonic, passphrase),
70
+ )
71
+ })
72
+
73
+ test('behavior: rejects non-string mnemonics like the default', async () => {
74
+ const { toSeed } = await Mnemonic.engine()
75
+
76
+ expect(() => toSeed(1 as never)).toThrowErrorMatchingInlineSnapshot(
77
+ `[TypeError: invalid mnemonic type: number]`,
78
+ )
79
+ })
80
+
81
+ test('behavior: returns owned Uint8Array values', async () => {
82
+ const { toSeed } = await Mnemonic.engine()
83
+ const mnemonic = Array.from({ length: 12 }, () => 'word').join(' ')
84
+ const first = toSeed(mnemonic)
85
+ const second = toSeed(mnemonic)
86
+
87
+ expect(first.constructor === Uint8Array).toMatchInlineSnapshot('true')
88
+ expect(first === second).toMatchInlineSnapshot('false')
89
+ expect(first).toEqual(second)
90
+ })
91
+
92
+ test('behavior: returns a fresh engine', async () => {
93
+ const first = await Mnemonic.engine()
94
+ const second = await Mnemonic.engine()
95
+
96
+ expect(first === second).toMatchInlineSnapshot('false')
97
+ })
98
+ })
@@ -0,0 +1,29 @@
1
+ import { expectTypeOf, test } from 'vp/test'
2
+ import type * as Engine from '../../core/Engine.js'
3
+ import * as core_P256 from '../../core/P256.js'
4
+ import * as NodeP256 from '../P256.js'
5
+
6
+ type Slot = Awaited<ReturnType<typeof NodeP256.engine>>
7
+
8
+ test('public-key derivation is present', () => {
9
+ expectTypeOf<Slot['getPublicKey']>().toEqualTypeOf<
10
+ (privateKey: Uint8Array) => Uint8Array
11
+ >()
12
+ })
13
+
14
+ test('unsupported primitives are absent', () => {
15
+ expectTypeOf<Slot>().not.toHaveProperty('getSharedSecret')
16
+ expectTypeOf<Slot>().not.toHaveProperty('randomSecretKey')
17
+ expectTypeOf<Slot>().not.toHaveProperty('recoverPublicKey')
18
+ expectTypeOf<Slot>().not.toHaveProperty('sign')
19
+ expectTypeOf<Slot>().not.toHaveProperty('verify')
20
+ })
21
+
22
+ test('the result is the raw slot', () => {
23
+ expectTypeOf<{ P256: Slot }>().toExtend<Engine.Engine>()
24
+ })
25
+
26
+ test('the Node namespace exposes the public P256 API', () => {
27
+ expectTypeOf(NodeP256.getPublicKey).toEqualTypeOf(core_P256.getPublicKey)
28
+ expectTypeOf<typeof NodeP256>().not.toHaveProperty('create')
29
+ })
@@ -0,0 +1,102 @@
1
+ import { p256 } from '@noble/curves/nist.js'
2
+ import { Hex } from 'ox'
3
+ import { describe, expect, test } from 'vp/test'
4
+ import * as P256 from '../P256.js'
5
+
6
+ const order = 'ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'
7
+
8
+ describe('engine', () => {
9
+ test('behavior: exposes only public-key derivation', async () => {
10
+ const engine = await P256.engine()
11
+
12
+ expect(Object.keys(engine)).toMatchInlineSnapshot(`
13
+ [
14
+ "getPublicKey",
15
+ ]
16
+ `)
17
+ })
18
+
19
+ test('behavior: matches the SEC 2 generator vector', async () => {
20
+ const engine = await P256.engine()
21
+ const privateKey = new Uint8Array(32)
22
+ privateKey[31] = 1
23
+
24
+ expect(
25
+ Hex.fromBytes(engine.getPublicKey(privateKey)),
26
+ ).toMatchInlineSnapshot(
27
+ `"0x046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"`,
28
+ )
29
+ })
30
+
31
+ test('behavior: matches the default across valid scalars', async () => {
32
+ const engine = await P256.engine()
33
+ const privateKeys = [
34
+ `${'00'.repeat(31)}01`,
35
+ `${'00'.repeat(31)}02`,
36
+ '7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
37
+ 'dde57ae9b9ed6f76fa5358c24d5ca2057ebc1ece18b7273121450a29c96ec8e5',
38
+ 'ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550',
39
+ ]
40
+
41
+ for (const privateKey of privateKeys) {
42
+ const bytes = fromHex(privateKey)
43
+ expect(engine.getPublicKey(bytes)).toEqual(
44
+ p256.getPublicKey(bytes, false),
45
+ )
46
+ }
47
+ })
48
+
49
+ test('behavior: respects typed-array offsets without mutating inputs', async () => {
50
+ const engine = await P256.engine()
51
+ const privateKey = offsetView(
52
+ fromHex(
53
+ 'dde57ae9b9ed6f76fa5358c24d5ca2057ebc1ece18b7273121450a29c96ec8e5',
54
+ ),
55
+ )
56
+ const before = privateKey.slice()
57
+
58
+ expect(engine.getPublicKey(privateKey)).toEqual(
59
+ p256.getPublicKey(privateKey, false),
60
+ )
61
+ expect(privateKey).toEqual(before)
62
+ })
63
+
64
+ test('behavior: rejects malformed and out-of-range private keys', async () => {
65
+ const engine = await P256.engine()
66
+
67
+ for (const size of [0, 1, 31, 33, 64])
68
+ expect(() => engine.getPublicKey(new Uint8Array(size))).toThrowError(
69
+ `P256 private key must be 32 bytes, got ${size}`,
70
+ )
71
+
72
+ expect(() => engine.getPublicKey(new Uint8Array(32))).toThrowError()
73
+ expect(() => engine.getPublicKey(fromHex(order))).toThrowError()
74
+ })
75
+
76
+ test('behavior: returns owned Uint8Array values', async () => {
77
+ const engine = await P256.engine()
78
+ const privateKey = fromHex(`${'00'.repeat(31)}01`)
79
+ const first = engine.getPublicKey(privateKey)
80
+ const second = engine.getPublicKey(privateKey)
81
+
82
+ expect(first.constructor === Uint8Array).toMatchInlineSnapshot('true')
83
+ expect(first === second).toMatchInlineSnapshot('false')
84
+ })
85
+
86
+ test('behavior: returns a fresh engine', async () => {
87
+ const first = await P256.engine()
88
+ const second = await P256.engine()
89
+
90
+ expect(first === second).toMatchInlineSnapshot('false')
91
+ })
92
+ })
93
+
94
+ function fromHex(value: string): Uint8Array {
95
+ return Hex.toBytes(`0x${value}`)
96
+ }
97
+
98
+ function offsetView(value: Uint8Array): Uint8Array {
99
+ const bytes = new Uint8Array(value.length + 4).fill(0xff)
100
+ bytes.set(value, 2)
101
+ return bytes.subarray(2, -2)
102
+ }
@@ -0,0 +1,28 @@
1
+ import { expectTypeOf, test } from 'vp/test'
2
+ import type * as Engine from '../../core/Engine.js'
3
+ import * as core_X25519 from '../../core/X25519.js'
4
+ import * as NodeX25519 from '../X25519.js'
5
+
6
+ type Slot = Awaited<ReturnType<typeof NodeX25519.engine>>
7
+
8
+ test('every implemented primitive is present', () => {
9
+ expectTypeOf<Slot['getPublicKey']>().toEqualTypeOf<
10
+ (privateKey: Uint8Array) => Uint8Array
11
+ >()
12
+ expectTypeOf<Slot['getSharedSecret']>().toEqualTypeOf<
13
+ (privateKey: Uint8Array, publicKey: Uint8Array) => Uint8Array
14
+ >()
15
+ })
16
+
17
+ test('unsupported primitives are absent', () => {
18
+ expectTypeOf<Slot>().not.toHaveProperty('randomSecretKey')
19
+ })
20
+
21
+ test('the result is the raw slot', () => {
22
+ expectTypeOf<{ X25519: Slot }>().toExtend<Engine.Engine>()
23
+ })
24
+
25
+ test('the Node namespace exposes the public X25519 API', () => {
26
+ expectTypeOf(NodeX25519.getPublicKey).toEqualTypeOf(core_X25519.getPublicKey)
27
+ expectTypeOf<typeof NodeX25519>().not.toHaveProperty('create')
28
+ })
@@ -0,0 +1,239 @@
1
+ import * as fs from 'node:fs'
2
+ import { x25519 } from '@noble/curves/ed25519.js'
3
+ import { Hex } from 'ox'
4
+ import { describe, expect, test } from 'vp/test'
5
+ import * as X25519 from '../X25519.js'
6
+
7
+ type LowOrderVector = {
8
+ name: string
9
+ publicKey: string
10
+ }
11
+
12
+ const alicePrivateKey =
13
+ '77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a'
14
+ const bobPrivateKey =
15
+ '5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb'
16
+
17
+ const lowOrderPublicKeys = JSON.parse(
18
+ fs.readFileSync(
19
+ new URL('../../../test/vectors/x25519/low-order.json', import.meta.url),
20
+ 'utf8',
21
+ ),
22
+ ) as readonly LowOrderVector[]
23
+
24
+ describe('engine', () => {
25
+ test('behavior: exposes only the supported primitives', async () => {
26
+ const engine = await X25519.engine()
27
+
28
+ expect(Object.keys(engine).sort()).toMatchInlineSnapshot(`
29
+ [
30
+ "getPublicKey",
31
+ "getSharedSecret",
32
+ ]
33
+ `)
34
+ })
35
+
36
+ test('behavior: matches RFC 7748 key-agreement vectors', async () => {
37
+ const engine = await X25519.engine()
38
+ const alicePublicKey = engine.getPublicKey(fromHex(alicePrivateKey))
39
+ const bobPublicKey = engine.getPublicKey(fromHex(bobPrivateKey))
40
+
41
+ expect({
42
+ alicePublicKey: Hex.fromBytes(alicePublicKey),
43
+ bobPublicKey: Hex.fromBytes(bobPublicKey),
44
+ sharedSecret: Hex.fromBytes(
45
+ engine.getSharedSecret(fromHex(alicePrivateKey), bobPublicKey),
46
+ ),
47
+ }).toMatchInlineSnapshot(`
48
+ {
49
+ "alicePublicKey": "0x8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a",
50
+ "bobPublicKey": "0xde9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f",
51
+ "sharedSecret": "0x4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742",
52
+ }
53
+ `)
54
+ })
55
+
56
+ test('behavior: matches RFC 7748 arbitrary-point vectors', async () => {
57
+ const engine = await X25519.engine()
58
+ const vectors = [
59
+ {
60
+ privateKey:
61
+ 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4',
62
+ publicKey:
63
+ 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c',
64
+ },
65
+ {
66
+ privateKey:
67
+ '4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d',
68
+ publicKey:
69
+ 'e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493',
70
+ },
71
+ ] as const
72
+
73
+ expect(
74
+ vectors.map(({ privateKey, publicKey }) =>
75
+ Hex.fromBytes(
76
+ engine.getSharedSecret(fromHex(privateKey), fromHex(publicKey)),
77
+ ),
78
+ ),
79
+ ).toMatchInlineSnapshot(`
80
+ [
81
+ "0xc3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552",
82
+ "0x95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957",
83
+ ]
84
+ `)
85
+ })
86
+
87
+ test('behavior: matches the default across private keys', async () => {
88
+ const engine = await X25519.engine()
89
+ const privateKeys = [
90
+ fromHex(alicePrivateKey),
91
+ fromHex(bobPrivateKey),
92
+ new Uint8Array(32),
93
+ new Uint8Array(32).fill(0xff),
94
+ Uint8Array.from({ length: 32 }, (_, index) => index),
95
+ ]
96
+
97
+ for (const [index, privateKey] of privateKeys.entries()) {
98
+ const peerPrivateKey = Uint8Array.from(
99
+ { length: 32 },
100
+ (_, offset) => (offset * 17 + index + 1) % 251,
101
+ )
102
+ const publicKey = x25519.getPublicKey(peerPrivateKey)
103
+ expect(engine.getPublicKey(privateKey)).toEqual(
104
+ x25519.getPublicKey(privateKey),
105
+ )
106
+ expect(engine.getSharedSecret(privateKey, publicKey)).toEqual(
107
+ x25519.getSharedSecret(privateKey, publicKey),
108
+ )
109
+ }
110
+ })
111
+
112
+ test('behavior: masks the public u-coordinate high bit', async () => {
113
+ const engine = await X25519.engine()
114
+ const privateKey = fromHex(alicePrivateKey)
115
+ const publicKey = x25519.getPublicKey(fromHex(bobPrivateKey))
116
+ const highBitPublicKey = publicKey.slice()
117
+ highBitPublicKey[31]! |= 0x80
118
+ const expected = x25519.getSharedSecret(privateKey, publicKey)
119
+
120
+ expect(x25519.getSharedSecret(privateKey, highBitPublicKey)).toEqual(
121
+ expected,
122
+ )
123
+ expect(engine.getSharedSecret(privateKey, highBitPublicKey)).toEqual(
124
+ expected,
125
+ )
126
+ })
127
+
128
+ test('behavior: reduces noncanonical public u-coordinates', async () => {
129
+ const engine = await X25519.engine()
130
+ const privateKey = fromHex(alicePrivateKey)
131
+ // 2^255 - 19 + 9 encodes the base point modulo the field prime.
132
+ const publicKey = fromHex(`f6${'ff'.repeat(30)}7f`)
133
+ const expected = x25519.getPublicKey(privateKey)
134
+
135
+ expect(x25519.getSharedSecret(privateKey, publicKey)).toEqual(expected)
136
+ expect(engine.getSharedSecret(privateKey, publicKey)).toEqual(expected)
137
+ })
138
+
139
+ test('behavior: rejects the complete published low-order set', async () => {
140
+ const engine = await X25519.engine()
141
+ const privateKey = fromHex(alicePrivateKey)
142
+
143
+ expect(lowOrderPublicKeys).toHaveLength(7)
144
+ for (const vector of lowOrderPublicKeys) {
145
+ const publicKey = fromHex(vector.publicKey)
146
+ const highBitPublicKey = publicKey.slice()
147
+ highBitPublicKey[31]! |= 0x80
148
+
149
+ for (const [name, value] of [
150
+ ['published', publicKey],
151
+ ['top-bit alias', highBitPublicKey],
152
+ ] as const) {
153
+ expect(
154
+ () => x25519.getSharedSecret(privateKey, value),
155
+ `${vector.name} (${name})`,
156
+ ).toThrowError()
157
+ expect(
158
+ () => engine.getSharedSecret(privateKey, value),
159
+ `${vector.name} (${name})`,
160
+ ).toThrowError()
161
+ }
162
+ }
163
+ })
164
+
165
+ test('behavior: respects typed-array offsets without mutating inputs', async () => {
166
+ const engine = await X25519.engine()
167
+ const privateKey = offsetView(fromHex(alicePrivateKey))
168
+ const publicKey = offsetView(x25519.getPublicKey(fromHex(bobPrivateKey)))
169
+ const privateKeyBefore = privateKey.slice()
170
+ const publicKeyBefore = publicKey.slice()
171
+
172
+ expect(engine.getPublicKey(privateKey)).toEqual(
173
+ x25519.getPublicKey(privateKey),
174
+ )
175
+ expect(engine.getSharedSecret(privateKey, publicKey)).toEqual(
176
+ x25519.getSharedSecret(privateKey, publicKey),
177
+ )
178
+ expect({ privateKey, publicKey }).toEqual({
179
+ privateKey: privateKeyBefore,
180
+ publicKey: publicKeyBefore,
181
+ })
182
+ })
183
+
184
+ test('behavior: rejects malformed key lengths', async () => {
185
+ const engine = await X25519.engine()
186
+ const privateKey = fromHex(alicePrivateKey)
187
+ const publicKey = x25519.getPublicKey(fromHex(bobPrivateKey))
188
+
189
+ for (const size of [0, 1, 31, 33, 64]) {
190
+ expect(() => engine.getPublicKey(new Uint8Array(size))).toThrowError(
191
+ `X25519 private key must be 32 bytes, got ${size}`,
192
+ )
193
+ expect(() =>
194
+ engine.getSharedSecret(new Uint8Array(size), publicKey),
195
+ ).toThrowError(`X25519 private key must be 32 bytes, got ${size}`)
196
+ expect(() =>
197
+ engine.getSharedSecret(privateKey, new Uint8Array(size)),
198
+ ).toThrowError(`X25519 public key must be 32 bytes, got ${size}`)
199
+ }
200
+ })
201
+
202
+ test('behavior: returns owned Uint8Array values', async () => {
203
+ const engine = await X25519.engine()
204
+ const privateKey = fromHex(alicePrivateKey)
205
+ const publicKey = x25519.getPublicKey(fromHex(bobPrivateKey))
206
+ const outputs = [
207
+ engine.getPublicKey(privateKey),
208
+ engine.getSharedSecret(privateKey, publicKey),
209
+ ]
210
+
211
+ expect(outputs.map((output) => output.constructor === Uint8Array))
212
+ .toMatchInlineSnapshot(`
213
+ [
214
+ true,
215
+ true,
216
+ ]
217
+ `)
218
+ expect(
219
+ engine.getPublicKey(privateKey) === engine.getPublicKey(privateKey),
220
+ ).toMatchInlineSnapshot('false')
221
+ })
222
+
223
+ test('behavior: returns a fresh engine', async () => {
224
+ const first = await X25519.engine()
225
+ const second = await X25519.engine()
226
+
227
+ expect(first === second).toMatchInlineSnapshot('false')
228
+ })
229
+ })
230
+
231
+ function fromHex(value: string): Uint8Array {
232
+ return Hex.toBytes(`0x${value}`)
233
+ }
234
+
235
+ function offsetView(value: Uint8Array): Uint8Array {
236
+ const bytes = new Uint8Array(value.length + 4).fill(0xff)
237
+ bytes.set(value, 2)
238
+ return bytes.subarray(2, -2)
239
+ }
@@ -0,0 +1,132 @@
1
+ /** @entrypointCategory Node */
2
+
3
+ /**
4
+ * Node.js implementations of Ox's supported cryptographic primitives, backed
5
+ * by `node:crypto`.
6
+ *
7
+ * Import this entrypoint only in Node.js. Its static `node:crypto` dependency
8
+ * is intentionally kept outside Ox's runtime-neutral entrypoint.
9
+ *
10
+ * @example
11
+ * ```ts twoslash
12
+ * // @noErrors
13
+ * import { Engine, Hash } from 'ox/node'
14
+ *
15
+ * await Engine.install()
16
+ *
17
+ * Hash.sha256('0xdeadbeef')
18
+ * ```
19
+ *
20
+ * @category Crypto
21
+ */
22
+ export * as Engine from './Engine.js'
23
+
24
+ /**
25
+ * Ox's Ed25519 API and its supported Node.js engine primitives.
26
+ *
27
+ * @example
28
+ * ```ts twoslash
29
+ * // @noErrors
30
+ * import { Engine } from 'ox'
31
+ * import { Ed25519 } from 'ox/node'
32
+ *
33
+ * await Engine.install({ Ed25519: Ed25519.engine() })
34
+ *
35
+ * Ed25519.getPublicKey({ privateKey: '0x...' })
36
+ * ```
37
+ *
38
+ * @category Crypto
39
+ */
40
+ export * as Ed25519 from './Ed25519.js'
41
+
42
+ /**
43
+ * Ox's hash API and its supported Node.js engine primitives.
44
+ *
45
+ * @example
46
+ * ```ts twoslash
47
+ * // @noErrors
48
+ * import { Engine } from 'ox'
49
+ * import { Hash } from 'ox/node'
50
+ *
51
+ * await Engine.install({ Hash: Hash.engine() })
52
+ *
53
+ * Hash.sha256('0xdeadbeef')
54
+ * ```
55
+ *
56
+ * @category Crypto
57
+ */
58
+ export * as Hash from './Hash.js'
59
+
60
+ /**
61
+ * Ox's keystore API and its supported Node.js engine primitives.
62
+ *
63
+ * @example
64
+ * ```ts twoslash
65
+ * // @noErrors
66
+ * import { Engine } from 'ox'
67
+ * import { Keystore } from 'ox/node'
68
+ *
69
+ * await Engine.install({ Keystore: Keystore.engine() })
70
+ *
71
+ * Keystore.pbkdf2({ password: 'testpassword' })
72
+ * ```
73
+ *
74
+ * @category Crypto
75
+ */
76
+ export * as Keystore from './Keystore.js'
77
+
78
+ /**
79
+ * Ox's mnemonic API and its Node.js BIP-39 seed engine primitive.
80
+ *
81
+ * @example
82
+ * ```ts twoslash
83
+ * // @noErrors
84
+ * import { Engine } from 'ox'
85
+ * import { Mnemonic } from 'ox/node'
86
+ *
87
+ * await Engine.install({ Mnemonic: Mnemonic.engine() })
88
+ *
89
+ * Mnemonic.toSeed(
90
+ * 'test test test test test test test test test test test junk'
91
+ * )
92
+ * ```
93
+ *
94
+ * @category Crypto
95
+ */
96
+ export * as Mnemonic from './Mnemonic.js'
97
+
98
+ /**
99
+ * Ox's P256 API and its Node.js public-key derivation engine primitive.
100
+ *
101
+ * @example
102
+ * ```ts twoslash
103
+ * // @noErrors
104
+ * import { Engine } from 'ox'
105
+ * import { P256 } from 'ox/node'
106
+ *
107
+ * await Engine.install({ P256: P256.engine() })
108
+ *
109
+ * P256.getPublicKey({ privateKey: '0x...' })
110
+ * ```
111
+ *
112
+ * @category Crypto
113
+ */
114
+ export * as P256 from './P256.js'
115
+
116
+ /**
117
+ * Ox's X25519 API and its supported Node.js engine primitives.
118
+ *
119
+ * @example
120
+ * ```ts twoslash
121
+ * // @noErrors
122
+ * import { Engine } from 'ox'
123
+ * import { X25519 } from 'ox/node'
124
+ *
125
+ * await Engine.install({ X25519: X25519.engine() })
126
+ *
127
+ * X25519.getPublicKey({ privateKey: '0x...' })
128
+ * ```
129
+ *
130
+ * @category Crypto
131
+ */
132
+ export * as X25519 from './X25519.js'