@reallyme/crypto 0.3.9 → 0.3.11

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 (66) hide show
  1. package/README.md +10 -11
  2. package/dist/aead.js +1 -1
  3. package/dist/aesKw.js +1 -1
  4. package/dist/algorithms.js +1 -1
  5. package/dist/argon2id.js +1 -1
  6. package/dist/bip340Schnorr.js +1 -1
  7. package/dist/cryptoFacade.d.ts +60 -81
  8. package/dist/cryptoFacade.js +12 -408
  9. package/dist/cryptoFacadeAsymmetric.d.ts +20 -0
  10. package/dist/cryptoFacadeAsymmetric.js +252 -0
  11. package/dist/cryptoFacadeSymmetric.d.ts +27 -0
  12. package/dist/cryptoFacadeSymmetric.js +166 -0
  13. package/dist/digest.js +1 -1
  14. package/dist/ed25519.d.ts +2 -0
  15. package/dist/ed25519.js +45 -4
  16. package/dist/encodeEcdsaDer.js +1 -1
  17. package/dist/errors.js +1 -1
  18. package/dist/hkdf.js +1 -1
  19. package/dist/hmac.d.ts +3 -3
  20. package/dist/hmac.js +8 -5
  21. package/dist/hpke.d.ts +1 -1
  22. package/dist/hpke.js +4 -2
  23. package/dist/index.js +1 -1
  24. package/dist/jwaConcatKdf.js +1 -1
  25. package/dist/jwk.js +46 -11
  26. package/dist/kmac.js +1 -1
  27. package/dist/memory.js +1 -1
  28. package/dist/mlDsa.js +1 -1
  29. package/dist/mlKem.js +1 -1
  30. package/dist/operationResponse.js +1 -1
  31. package/dist/p256Ecdh.js +1 -1
  32. package/dist/p256Ecdsa.js +1 -1
  33. package/dist/p384Ecdh.js +1 -1
  34. package/dist/p384Ecdsa.js +1 -1
  35. package/dist/p521Ecdh.js +1 -1
  36. package/dist/p521Ecdsa.js +1 -1
  37. package/dist/pbkdf2.js +12 -4
  38. package/dist/proto/generated/reallyme/crypto/v1/crypto_pb.js +1 -1
  39. package/dist/proto.d.ts +8 -117
  40. package/dist/proto.js +6 -1085
  41. package/dist/protoAlgorithms.d.ts +21 -0
  42. package/dist/protoAlgorithms.js +323 -0
  43. package/dist/protoErrors.d.ts +27 -0
  44. package/dist/protoErrors.js +275 -0
  45. package/dist/protoIdentifiers.d.ts +14 -0
  46. package/dist/protoIdentifiers.js +112 -0
  47. package/dist/protoJwk.d.ts +10 -0
  48. package/dist/protoJwk.js +204 -0
  49. package/dist/protoValues.d.ts +63 -0
  50. package/dist/protoValues.js +228 -0
  51. package/dist/providerCatalog.js +1 -1
  52. package/dist/rsa.js +1 -1
  53. package/dist/secp256k1.js +1 -1
  54. package/dist/slhDsa.js +1 -1
  55. package/dist/validateBytes.js +1 -1
  56. package/dist/verifyBundledWasmModule.d.ts +63 -0
  57. package/dist/verifyBundledWasmModule.js +80 -0
  58. package/dist/wasm/reallyme_crypto_wasm.d.ts +383 -0
  59. package/dist/wasm/reallyme_crypto_wasm.js +8 -8
  60. package/dist/wasm/reallyme_crypto_wasm_bg.wasm +0 -0
  61. package/dist/wasmModuleTypes.js +1 -1
  62. package/dist/wasmProvider.d.ts +5 -0
  63. package/dist/wasmProvider.js +61 -3
  64. package/dist/x25519.js +1 -1
  65. package/dist/xWing.js +1 -1
  66. package/package.json +6 -5
@@ -1,8 +1,19 @@
1
- // SPDX-FileCopyrightText: Copyright © 2026 ReallyMe LLC. All rights reserved
1
+ // SPDX-FileCopyrightText: 2026 ReallyMe LLC
2
2
  //
3
3
  // SPDX-License-Identifier: MIT OR Apache-2.0
4
4
  import { ReallyMeCryptoError } from "./errors.js";
5
+ import { bundledWasmFunctions, verifyBundledWasmModule } from "./verifyBundledWasmModule.js";
5
6
  let installedProvider;
7
+ const poisonedModules = new WeakSet();
8
+ const trustedProviders = new WeakSet();
9
+ const isWasmRuntimeError = (error) => {
10
+ const wasm = Reflect.get(globalThis, "WebAssembly");
11
+ if (typeof wasm !== "object" || wasm === null) {
12
+ return false;
13
+ }
14
+ const runtimeError = Reflect.get(wasm, "RuntimeError");
15
+ return typeof runtimeError === "function" && error instanceof runtimeError;
16
+ };
6
17
  const requireObject = (module) => {
7
18
  if (typeof module !== "object" || module === null) {
8
19
  throw new ReallyMeCryptoError("provider-failure");
@@ -10,15 +21,30 @@ const requireObject = (module) => {
10
21
  return module;
11
22
  };
12
23
  const requireFunction = (module, name) => {
13
- const candidate = Reflect.get(module, name);
24
+ let candidate;
25
+ try {
26
+ const descriptor = Object.getOwnPropertyDescriptor(module, name);
27
+ candidate = descriptor?.get === undefined ? descriptor?.value : Reflect.get(module, name);
28
+ }
29
+ catch {
30
+ throw new ReallyMeCryptoError("provider-failure");
31
+ }
14
32
  if (typeof candidate !== "function") {
15
33
  throw new ReallyMeCryptoError("provider-failure");
16
34
  }
17
35
  return (...args) => {
36
+ if (poisonedModules.has(module)) {
37
+ throw new ReallyMeCryptoError("provider-failure");
38
+ }
18
39
  try {
19
40
  return candidate(...args);
20
41
  }
21
42
  catch (error) {
43
+ if (isWasmRuntimeError(error)) {
44
+ // A trap can leave WASM state inconsistent. All wrappers built from
45
+ // that module fail closed for the remainder of the process.
46
+ poisonedModules.add(module);
47
+ }
22
48
  throw new ReallyMeCryptoError(wasmErrorCode(error));
23
49
  }
24
50
  };
@@ -86,7 +112,8 @@ const rsaPssVerifyFunction = (module, name) => {
86
112
  const callable = requireFunction(module, name);
87
113
  return (publicKeyDer, publicKeyEncoding, messageHashSuite, mgf1HashSuite, saltLength, message, signature) => callable(publicKeyDer, publicKeyEncoding, messageHashSuite, mgf1HashSuite, saltLength, message, signature);
88
114
  };
89
- export const createReallyMeWasmProvider = (module) => {
115
+ /** Bind callables after the caller establishes module ownership; tests exercise this boundary directly. */
116
+ export const createWasmProviderFromModule = (module) => {
90
117
  const providerModule = requireObject(module);
91
118
  return {
92
119
  processOperationResponse: function1(providerModule, "processOperationResponse"),
@@ -149,6 +176,37 @@ export const createReallyMeWasmProvider = (module) => {
149
176
  xWing768Decapsulate: function2(providerModule, "xWing768Decapsulate"),
150
177
  };
151
178
  };
179
+ /** Build a provider only from the package-owned and initialized WASM module. */
180
+ export const createReallyMeWasmProvider = (module) => {
181
+ const providerModule = requireObject(module);
182
+ // Static named imports keep the package-owned glue in the bundler graph.
183
+ // Compare every callable before global installation so a structural copy
184
+ // cannot replace a verification hook with a no-op.
185
+ if (!verifyBundledWasmModule(providerModule)) {
186
+ throw new ReallyMeCryptoError("provider-failure");
187
+ }
188
+ try {
189
+ // A data-independent call rejects an uninitialized WASM instance before
190
+ // the install-once slot becomes visible to package-global facades.
191
+ requireFunction(bundledWasmFunctions, "aes128GcmOpen")(new Uint8Array(0), new Uint8Array(0), new Uint8Array(0), new Uint8Array(0));
192
+ }
193
+ catch (error) {
194
+ if (error instanceof ReallyMeCryptoError && error.code === "invalid-input") {
195
+ const provider = Object.freeze(createWasmProviderFromModule(bundledWasmFunctions));
196
+ trustedProviders.add(provider);
197
+ return provider;
198
+ }
199
+ throw new ReallyMeCryptoError("provider-failure");
200
+ }
201
+ throw new ReallyMeCryptoError("provider-failure");
202
+ };
203
+ /** A structural copy cannot be used as an explicit facade provider. */
204
+ export const requireTrustedReallyMeWasmProvider = (provider) => {
205
+ if (!trustedProviders.has(provider)) {
206
+ throw new ReallyMeCryptoError("provider-failure");
207
+ }
208
+ return provider;
209
+ };
152
210
  export const installReallyMeWasmProvider = (module) => {
153
211
  if (installedProvider !== undefined) {
154
212
  throw new ReallyMeCryptoError("provider-failure");
package/dist/x25519.js CHANGED
@@ -1,4 +1,4 @@
1
- // SPDX-FileCopyrightText: Copyright © 2026 ReallyMe LLC. All rights reserved
1
+ // SPDX-FileCopyrightText: 2026 ReallyMe LLC
2
2
  //
3
3
  // SPDX-License-Identifier: MIT OR Apache-2.0
4
4
  import { x25519 } from "@noble/curves/ed25519.js";
package/dist/xWing.js CHANGED
@@ -1,4 +1,4 @@
1
- // SPDX-FileCopyrightText: Copyright © 2026 ReallyMe LLC. All rights reserved
1
+ // SPDX-FileCopyrightText: 2026 ReallyMe LLC
2
2
  //
3
3
  // SPDX-License-Identifier: MIT OR Apache-2.0
4
4
  import { ReallyMeCryptoError } from "./errors.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reallyme/crypto",
3
- "version": "0.3.9",
3
+ "version": "0.3.11",
4
4
  "description": "ReallyMe crypto SDK for TypeScript/JavaScript with an explicit, pinned provider set.",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "repository": {
@@ -48,14 +48,15 @@
48
48
  "pack:check": "node scripts/check-pack.mjs",
49
49
  "prepack": "npm run build",
50
50
  "prepublishOnly": "npm test && npm run pack:check",
51
- "typecheck": "tsc --noEmit",
52
- "test": "npm run build && node --test \"test/*.test.mjs\""
51
+ "typecheck": "npm run build:wasm && tsc --noEmit",
52
+ "test": "npm run build && node --test \"test/*.test.mjs\"",
53
+ "test:browser": "npm run build && node scripts/browser-wasm-test.mjs"
53
54
  },
54
55
  "dependencies": {
55
- "@bufbuild/protobuf": "2.14.1",
56
+ "@bufbuild/protobuf": "2.16.0",
56
57
  "@noble/curves": "2.4.0",
57
58
  "@noble/hashes": "2.4.0",
58
- "@reallyme/codec": "0.2.3"
59
+ "@reallyme/codec": "0.3.0"
59
60
  },
60
61
  "devDependencies": {
61
62
  "typescript": "7.0.2"