@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
@@ -0,0 +1,252 @@
1
+ // SPDX-FileCopyrightText: 2026 ReallyMe LLC
2
+ //
3
+ // SPDX-License-Identifier: MIT OR Apache-2.0
4
+ import { ReallyMeBip340Schnorr } from "./bip340Schnorr.js";
5
+ import { ReallyMeEd25519 } from "./ed25519.js";
6
+ import { ReallyMeCryptoError } from "./errors.js";
7
+ import { ReallyMeHpke } from "./hpke.js";
8
+ import { ReallyMeMlDsa } from "./mlDsa.js";
9
+ import { ReallyMeMlKem } from "./mlKem.js";
10
+ import { ReallyMeP256Ecdh } from "./p256Ecdh.js";
11
+ import { ReallyMeP256Ecdsa } from "./p256Ecdsa.js";
12
+ import { ReallyMeP384Ecdh } from "./p384Ecdh.js";
13
+ import { ReallyMeP384Ecdsa } from "./p384Ecdsa.js";
14
+ import { ReallyMeP521Ecdh } from "./p521Ecdh.js";
15
+ import { ReallyMeP521Ecdsa } from "./p521Ecdsa.js";
16
+ import { ReallyMeRsa } from "./rsa.js";
17
+ import { ReallyMeSecp256k1 } from "./secp256k1.js";
18
+ import { ReallyMeSlhDsa } from "./slhDsa.js";
19
+ import { ReallyMeX25519 } from "./x25519.js";
20
+ import { ReallyMeXWing } from "./xWing.js";
21
+ const SECP256K1_ECDSA = "ECDSA-secp256k1-SHA256";
22
+ const P256_ECDSA = "ECDSA-P256-SHA256";
23
+ const P384_ECDSA = "ECDSA-P384-SHA384";
24
+ const P521_ECDSA = "ECDSA-P521-SHA512";
25
+ const BIP340_SCHNORR = "BIP340-Schnorr-secp256k1-SHA256";
26
+ const ED25519 = "Ed25519";
27
+ export const createReallyMeAsymmetricFacade = (resolveWasmProvider) => ({
28
+ generateKeyPair(algorithm) {
29
+ if (algorithm === ED25519) {
30
+ return ReallyMeEd25519.generateKeyPair();
31
+ }
32
+ switch (algorithm) {
33
+ case P256_ECDSA:
34
+ return ReallyMeP256Ecdsa.generateKeyPair();
35
+ case P384_ECDSA:
36
+ return ReallyMeP384Ecdsa.generateKeyPair();
37
+ case P521_ECDSA:
38
+ return ReallyMeP521Ecdsa.generateKeyPair();
39
+ case SECP256K1_ECDSA:
40
+ return ReallyMeSecp256k1.generateKeyPair();
41
+ case BIP340_SCHNORR:
42
+ return ReallyMeBip340Schnorr.generateKeyPair();
43
+ case "ML-DSA-44":
44
+ case "ML-DSA-65":
45
+ case "ML-DSA-87":
46
+ return ReallyMeMlDsa.generateKeyPairWithProvider(resolveWasmProvider(), algorithm);
47
+ case "SLH-DSA-SHA2-128s":
48
+ return ReallyMeSlhDsa.generateKeyPairWithProvider(resolveWasmProvider(), algorithm);
49
+ default:
50
+ throw new ReallyMeCryptoError("unsupported-algorithm");
51
+ }
52
+ },
53
+ deriveKeyPair(algorithm, secretKey) {
54
+ // Import an existing secret and reconstruct its public key. Do not use
55
+ // this as key generation from passwords or other low-entropy input; use
56
+ // generateKeyPair for new keys, or a protocol-approved KDF before import.
57
+ if (algorithm === ED25519) {
58
+ return ReallyMeEd25519.deriveKeyPair(secretKey);
59
+ }
60
+ switch (algorithm) {
61
+ case P256_ECDSA:
62
+ return ReallyMeP256Ecdsa.deriveKeyPair(secretKey);
63
+ case P384_ECDSA:
64
+ return ReallyMeP384Ecdsa.deriveKeyPair(secretKey);
65
+ case P521_ECDSA:
66
+ return ReallyMeP521Ecdsa.deriveKeyPair(secretKey);
67
+ case SECP256K1_ECDSA:
68
+ return ReallyMeSecp256k1.deriveKeyPair(secretKey);
69
+ case BIP340_SCHNORR:
70
+ return ReallyMeBip340Schnorr.deriveKeyPair(secretKey);
71
+ case "ML-DSA-44":
72
+ case "ML-DSA-65":
73
+ case "ML-DSA-87":
74
+ return ReallyMeMlDsa.deriveKeyPairWithProvider(resolveWasmProvider(), algorithm, secretKey);
75
+ case "SLH-DSA-SHA2-128s":
76
+ // SLH-DSA deterministic derivation uses three FIPS seed components,
77
+ // so it deliberately does not fit this single-secret import shape.
78
+ throw new ReallyMeCryptoError("unsupported-algorithm");
79
+ default:
80
+ throw new ReallyMeCryptoError("unsupported-algorithm");
81
+ }
82
+ },
83
+ sign(algorithm, message, secretKey) {
84
+ if (algorithm === ED25519) {
85
+ return ReallyMeEd25519.sign(message, secretKey);
86
+ }
87
+ switch (algorithm) {
88
+ case P256_ECDSA:
89
+ return ReallyMeP256Ecdsa.sign(message, secretKey);
90
+ case P384_ECDSA:
91
+ return ReallyMeP384Ecdsa.sign(message, secretKey);
92
+ case P521_ECDSA:
93
+ return ReallyMeP521Ecdsa.sign(message, secretKey);
94
+ case SECP256K1_ECDSA:
95
+ return ReallyMeSecp256k1.sign(message, secretKey);
96
+ case "ML-DSA-44":
97
+ case "ML-DSA-65":
98
+ case "ML-DSA-87":
99
+ return ReallyMeMlDsa.signWithProvider(resolveWasmProvider(), algorithm, message, secretKey);
100
+ case "SLH-DSA-SHA2-128s":
101
+ return ReallyMeSlhDsa.signWithProvider(resolveWasmProvider(), algorithm, message, secretKey);
102
+ default:
103
+ throw new ReallyMeCryptoError("unsupported-algorithm");
104
+ }
105
+ },
106
+ signBip340Schnorr(message32, secretKey, auxRand32) {
107
+ return ReallyMeBip340Schnorr.sign(message32, secretKey, auxRand32);
108
+ },
109
+ verify(algorithm, signature, message, publicKey) {
110
+ if (algorithm === ED25519) {
111
+ ReallyMeEd25519.verify(signature, message, publicKey);
112
+ return;
113
+ }
114
+ switch (algorithm) {
115
+ case P256_ECDSA:
116
+ ReallyMeP256Ecdsa.verify(signature, message, publicKey);
117
+ return;
118
+ case P384_ECDSA:
119
+ ReallyMeP384Ecdsa.verify(signature, message, publicKey);
120
+ return;
121
+ case P521_ECDSA:
122
+ ReallyMeP521Ecdsa.verify(signature, message, publicKey);
123
+ return;
124
+ case SECP256K1_ECDSA:
125
+ ReallyMeSecp256k1.verify(signature, message, publicKey);
126
+ return;
127
+ case BIP340_SCHNORR:
128
+ ReallyMeBip340Schnorr.verify(signature, message, publicKey);
129
+ return;
130
+ case "ML-DSA-44":
131
+ case "ML-DSA-65":
132
+ case "ML-DSA-87":
133
+ ReallyMeMlDsa.verifyWithProvider(resolveWasmProvider(), algorithm, signature, message, publicKey);
134
+ return;
135
+ case "SLH-DSA-SHA2-128s":
136
+ ReallyMeSlhDsa.verifyWithProvider(resolveWasmProvider(), algorithm, signature, message, publicKey);
137
+ return;
138
+ default:
139
+ throw new ReallyMeCryptoError("unsupported-algorithm");
140
+ }
141
+ },
142
+ verifyRsa(algorithm, signature, message, publicKeyDer, publicKeyEncoding) {
143
+ switch (algorithm) {
144
+ case "RSA-PKCS1v15-SHA1":
145
+ case "RSA-PKCS1v15-SHA256":
146
+ case "RSA-PKCS1v15-SHA384":
147
+ case "RSA-PKCS1v15-SHA512":
148
+ case "RSA-PSS-SHA1-MGF1-SHA1":
149
+ case "RSA-PSS-SHA256-MGF1-SHA256":
150
+ case "RSA-PSS-SHA384-MGF1-SHA384":
151
+ case "RSA-PSS-SHA512-MGF1-SHA512":
152
+ ReallyMeRsa.verifyWithProvider(resolveWasmProvider(), algorithm, signature, message, publicKeyDer, publicKeyEncoding);
153
+ return;
154
+ default:
155
+ throw new ReallyMeCryptoError("unsupported-algorithm");
156
+ }
157
+ },
158
+ deriveSharedSecret(algorithm, publicKey, secretKey) {
159
+ switch (algorithm) {
160
+ case "X25519":
161
+ return ReallyMeX25519.deriveSharedSecret(publicKey, secretKey);
162
+ case "P-256-ECDH":
163
+ return ReallyMeP256Ecdh.deriveSharedSecret(publicKey, secretKey);
164
+ case "P-384-ECDH":
165
+ return ReallyMeP384Ecdh.deriveSharedSecret(publicKey, secretKey);
166
+ case "P-521-ECDH":
167
+ return ReallyMeP521Ecdh.deriveSharedSecret(publicKey, secretKey);
168
+ default:
169
+ throw new ReallyMeCryptoError("unsupported-algorithm");
170
+ }
171
+ },
172
+ deriveKeyAgreementKeyPair(algorithm, secretKey) {
173
+ switch (algorithm) {
174
+ case "X25519":
175
+ return ReallyMeX25519.deriveKeyPair(secretKey);
176
+ case "P-256-ECDH":
177
+ return ReallyMeP256Ecdh.deriveKeyPair(secretKey);
178
+ case "P-384-ECDH":
179
+ return ReallyMeP384Ecdh.deriveKeyPair(secretKey);
180
+ case "P-521-ECDH":
181
+ return ReallyMeP521Ecdh.deriveKeyPair(secretKey);
182
+ default:
183
+ throw new ReallyMeCryptoError("unsupported-algorithm");
184
+ }
185
+ },
186
+ generateKemKeyPair(algorithm) {
187
+ switch (algorithm) {
188
+ case "X-Wing-768":
189
+ return ReallyMeXWing.generateKeyPairWithProvider(resolveWasmProvider(), algorithm);
190
+ case "ML-KEM-512":
191
+ case "ML-KEM-768":
192
+ case "ML-KEM-1024":
193
+ return ReallyMeMlKem.generateKeyPairWithProvider(resolveWasmProvider(), algorithm);
194
+ default:
195
+ throw new ReallyMeCryptoError("unsupported-algorithm");
196
+ }
197
+ },
198
+ deriveKemKeyPair(algorithm, secretKey) {
199
+ switch (algorithm) {
200
+ case "X-Wing-768":
201
+ return ReallyMeXWing.deriveKeyPairWithProvider(resolveWasmProvider(), algorithm, secretKey);
202
+ case "ML-KEM-512":
203
+ case "ML-KEM-768":
204
+ case "ML-KEM-1024":
205
+ return ReallyMeMlKem.deriveKeyPairWithProvider(resolveWasmProvider(), algorithm, secretKey);
206
+ default:
207
+ throw new ReallyMeCryptoError("unsupported-algorithm");
208
+ }
209
+ },
210
+ encapsulate(algorithm, publicKey) {
211
+ switch (algorithm) {
212
+ case "X-Wing-768":
213
+ return ReallyMeXWing.encapsulateWithProvider(resolveWasmProvider(), algorithm, publicKey);
214
+ case "ML-KEM-512":
215
+ case "ML-KEM-768":
216
+ case "ML-KEM-1024":
217
+ return ReallyMeMlKem.encapsulateWithProvider(resolveWasmProvider(), algorithm, publicKey);
218
+ default:
219
+ throw new ReallyMeCryptoError("unsupported-algorithm");
220
+ }
221
+ },
222
+ decapsulate(algorithm, ciphertext, secretKey) {
223
+ switch (algorithm) {
224
+ case "X-Wing-768":
225
+ return ReallyMeXWing.decapsulateWithProvider(resolveWasmProvider(), algorithm, ciphertext, secretKey);
226
+ case "ML-KEM-512":
227
+ case "ML-KEM-768":
228
+ case "ML-KEM-1024":
229
+ return ReallyMeMlKem.decapsulateWithProvider(resolveWasmProvider(), algorithm, ciphertext, secretKey);
230
+ default:
231
+ throw new ReallyMeCryptoError("unsupported-algorithm");
232
+ }
233
+ },
234
+ sealHpke(suite, recipientPublicKey, info, aad, plaintext) {
235
+ switch (suite) {
236
+ case "DHKEM-P256-HKDF-SHA256-HKDF-SHA256-AES-256-GCM":
237
+ case "DHKEM-X25519-HKDF-SHA256-HKDF-SHA256-CHACHA20-POLY1305":
238
+ return ReallyMeHpke.sealBaseWithProvider(resolveWasmProvider(), suite, recipientPublicKey, info, aad, plaintext);
239
+ default:
240
+ throw new ReallyMeCryptoError("unsupported-algorithm");
241
+ }
242
+ },
243
+ openHpke(suite, recipientSecretKey, encapsulatedKey, info, aad, ciphertext) {
244
+ switch (suite) {
245
+ case "DHKEM-P256-HKDF-SHA256-HKDF-SHA256-AES-256-GCM":
246
+ case "DHKEM-X25519-HKDF-SHA256-HKDF-SHA256-CHACHA20-POLY1305":
247
+ return ReallyMeHpke.openBaseWithProvider(resolveWasmProvider(), suite, recipientSecretKey, encapsulatedKey, info, aad, ciphertext);
248
+ default:
249
+ throw new ReallyMeCryptoError("unsupported-algorithm");
250
+ }
251
+ },
252
+ });
@@ -0,0 +1,27 @@
1
+ import type { ReallyMeAeadAlgorithm, ReallyMeHashAlgorithm, ReallyMeHkdfAlgorithm, ReallyMeJwaConcatKdfAlgorithm, ReallyMeKeyWrapAlgorithm, ReallyMeKmacKdfAlgorithm, ReallyMeMacAlgorithm, ReallyMePbkdf2Algorithm } from "./algorithms.js";
2
+ import type { ReallyMeWasmProvider } from "./wasmProvider.js";
3
+ export declare const createReallyMeSymmetricFacade: (resolveWasmProvider: () => ReallyMeWasmProvider) => {
4
+ /**
5
+ * Executes a generated binary request and returns a binary
6
+ * `CryptoOperationResponse`.
7
+ */
8
+ processOperationResponse(request: Uint8Array): Uint8Array;
9
+ /**
10
+ * Executes a permitted non-secret generated ProtoJSON request and returns
11
+ * the same binary `CryptoOperationResponse`. Secret-bearing selectors fail
12
+ * before JSON value deserialization.
13
+ */
14
+ processOperationResponseJson(requestJson: Uint8Array): Uint8Array;
15
+ hash(algorithm: ReallyMeHashAlgorithm, bytes: Uint8Array): Uint8Array;
16
+ seal(algorithm: ReallyMeAeadAlgorithm, key: Uint8Array, nonce: Uint8Array, aad: Uint8Array, plaintext: Uint8Array): Uint8Array;
17
+ open(algorithm: ReallyMeAeadAlgorithm, key: Uint8Array, nonce: Uint8Array, aad: Uint8Array, ciphertextWithTag: Uint8Array): Uint8Array;
18
+ authenticate(algorithm: ReallyMeMacAlgorithm, key: Uint8Array, message: Uint8Array): Uint8Array;
19
+ verifyMac(algorithm: ReallyMeMacAlgorithm, tag: Uint8Array, key: Uint8Array, message: Uint8Array): void;
20
+ deriveArgon2id(kdfVersion: number, secret: Uint8Array, salt: Uint8Array): Uint8Array;
21
+ deriveKey(algorithm: ReallyMePbkdf2Algorithm, password: Uint8Array, salt: Uint8Array, iterations: number, outputLength: number): Uint8Array;
22
+ deriveHkdf(algorithm: ReallyMeHkdfAlgorithm, inputKeyMaterial: Uint8Array, salt: Uint8Array, info: Uint8Array, outputLength: number): Uint8Array;
23
+ deriveJwaConcatKdfSha256(algorithm: ReallyMeJwaConcatKdfAlgorithm, sharedSecret: Uint8Array, algorithmId: Uint8Array, partyUInfo: Uint8Array, partyVInfo: Uint8Array, outputLength: number): Uint8Array;
24
+ deriveKmac256(algorithm: ReallyMeKmacKdfAlgorithm, key: Uint8Array, context: Uint8Array, customization: Uint8Array, outputLength: number): Uint8Array;
25
+ wrapKey(algorithm: ReallyMeKeyWrapAlgorithm, wrappingKey: Uint8Array, keyToWrap: Uint8Array): Uint8Array;
26
+ unwrapKey(algorithm: ReallyMeKeyWrapAlgorithm, wrappingKey: Uint8Array, wrappedKey: Uint8Array): Uint8Array;
27
+ };
@@ -0,0 +1,166 @@
1
+ // SPDX-FileCopyrightText: 2026 ReallyMe LLC
2
+ //
3
+ // SPDX-License-Identifier: MIT OR Apache-2.0
4
+ import { ReallyMeAead } from "./aead.js";
5
+ import { ReallyMeAesKw } from "./aesKw.js";
6
+ import { ReallyMeArgon2id } from "./argon2id.js";
7
+ import { ReallyMeDigest } from "./digest.js";
8
+ import { ReallyMeCryptoError } from "./errors.js";
9
+ import { ReallyMeHkdf } from "./hkdf.js";
10
+ import { ReallyMeHmac } from "./hmac.js";
11
+ import { ReallyMeJwaConcatKdf } from "./jwaConcatKdf.js";
12
+ import { ReallyMeKmac } from "./kmac.js";
13
+ import { processOperationResponseJsonWithProvider, processOperationResponseWithProvider, } from "./operationResponse.js";
14
+ import { ReallyMePbkdf2 } from "./pbkdf2.js";
15
+ import { ensureByteArray } from "./validateBytes.js";
16
+ export const createReallyMeSymmetricFacade = (resolveWasmProvider) => ({
17
+ /**
18
+ * Executes a generated binary request and returns a binary
19
+ * `CryptoOperationResponse`.
20
+ */
21
+ processOperationResponse(request) {
22
+ ensureByteArray(request);
23
+ return processOperationResponseWithProvider(resolveWasmProvider(), request);
24
+ },
25
+ /**
26
+ * Executes a permitted non-secret generated ProtoJSON request and returns
27
+ * the same binary `CryptoOperationResponse`. Secret-bearing selectors fail
28
+ * before JSON value deserialization.
29
+ */
30
+ processOperationResponseJson(requestJson) {
31
+ ensureByteArray(requestJson);
32
+ return processOperationResponseJsonWithProvider(resolveWasmProvider(), requestJson);
33
+ },
34
+ hash(algorithm, bytes) {
35
+ switch (algorithm) {
36
+ case "SHA2-256":
37
+ return ReallyMeDigest.sha256(bytes);
38
+ case "SHA2-384":
39
+ return ReallyMeDigest.sha384(bytes);
40
+ case "SHA2-512":
41
+ return ReallyMeDigest.sha512(bytes);
42
+ case "SHA3-224":
43
+ return ReallyMeDigest.sha3_224(bytes);
44
+ case "SHA3-256":
45
+ return ReallyMeDigest.sha3_256(bytes);
46
+ case "SHA3-384":
47
+ return ReallyMeDigest.sha3_384(bytes);
48
+ case "SHA3-512":
49
+ return ReallyMeDigest.sha3_512(bytes);
50
+ default:
51
+ throw new ReallyMeCryptoError("unsupported-algorithm");
52
+ }
53
+ },
54
+ seal(algorithm, key, nonce, aad, plaintext) {
55
+ switch (algorithm) {
56
+ case "AES-128-GCM":
57
+ case "AES-192-GCM":
58
+ case "AES-256-GCM":
59
+ case "AES-256-GCM-SIV":
60
+ case "ChaCha20-Poly1305":
61
+ case "XChaCha20-Poly1305":
62
+ return ReallyMeAead.sealWithProvider(resolveWasmProvider(), algorithm, key, nonce, aad, plaintext);
63
+ default:
64
+ throw new ReallyMeCryptoError("unsupported-algorithm");
65
+ }
66
+ },
67
+ open(algorithm, key, nonce, aad, ciphertextWithTag) {
68
+ switch (algorithm) {
69
+ case "AES-128-GCM":
70
+ case "AES-192-GCM":
71
+ case "AES-256-GCM":
72
+ case "AES-256-GCM-SIV":
73
+ case "ChaCha20-Poly1305":
74
+ case "XChaCha20-Poly1305":
75
+ return ReallyMeAead.openWithProvider(resolveWasmProvider(), algorithm, key, nonce, aad, ciphertextWithTag);
76
+ default:
77
+ throw new ReallyMeCryptoError("unsupported-algorithm");
78
+ }
79
+ },
80
+ authenticate(algorithm, key, message) {
81
+ switch (algorithm) {
82
+ case "HMAC-SHA-256":
83
+ return ReallyMeHmac.authenticateSha256(key, message);
84
+ case "HMAC-SHA-384":
85
+ return ReallyMeHmac.authenticateSha384(key, message);
86
+ case "HMAC-SHA-512":
87
+ return ReallyMeHmac.authenticateSha512(key, message);
88
+ default:
89
+ throw new ReallyMeCryptoError("unsupported-algorithm");
90
+ }
91
+ },
92
+ verifyMac(algorithm, tag, key, message) {
93
+ switch (algorithm) {
94
+ case "HMAC-SHA-256":
95
+ ReallyMeHmac.verifySha256(tag, key, message);
96
+ return;
97
+ case "HMAC-SHA-384":
98
+ ReallyMeHmac.verifySha384(tag, key, message);
99
+ return;
100
+ case "HMAC-SHA-512":
101
+ ReallyMeHmac.verifySha512(tag, key, message);
102
+ return;
103
+ default:
104
+ throw new ReallyMeCryptoError("unsupported-algorithm");
105
+ }
106
+ },
107
+ deriveArgon2id(kdfVersion, secret, salt) {
108
+ return ReallyMeArgon2id.deriveKeyWithProvider(resolveWasmProvider(), kdfVersion, secret, salt);
109
+ },
110
+ deriveKey(algorithm, password, salt, iterations, outputLength) {
111
+ switch (algorithm) {
112
+ case "PBKDF2-HMAC-SHA-256":
113
+ return ReallyMePbkdf2.deriveHmacSha256(password, salt, iterations, outputLength);
114
+ case "PBKDF2-HMAC-SHA-512":
115
+ return ReallyMePbkdf2.deriveHmacSha512(password, salt, iterations, outputLength);
116
+ default:
117
+ throw new ReallyMeCryptoError("unsupported-algorithm");
118
+ }
119
+ },
120
+ deriveHkdf(algorithm, inputKeyMaterial, salt, info, outputLength) {
121
+ switch (algorithm) {
122
+ case "HKDF-SHA256":
123
+ return ReallyMeHkdf.deriveSha256(inputKeyMaterial, salt, info, outputLength);
124
+ case "HKDF-SHA384":
125
+ return ReallyMeHkdf.deriveSha384(inputKeyMaterial, salt, info, outputLength);
126
+ default:
127
+ throw new ReallyMeCryptoError("unsupported-algorithm");
128
+ }
129
+ },
130
+ deriveJwaConcatKdfSha256(algorithm, sharedSecret, algorithmId, partyUInfo, partyVInfo, outputLength) {
131
+ switch (algorithm) {
132
+ case "JWA-CONCAT-KDF-SHA256":
133
+ return ReallyMeJwaConcatKdf.deriveSha256(sharedSecret, algorithmId, partyUInfo, partyVInfo, outputLength);
134
+ default:
135
+ throw new ReallyMeCryptoError("unsupported-algorithm");
136
+ }
137
+ },
138
+ deriveKmac256(algorithm, key, context, customization, outputLength) {
139
+ switch (algorithm) {
140
+ case "KMAC256":
141
+ return ReallyMeKmac.deriveKmac256WithProvider(resolveWasmProvider(), key, context, customization, outputLength);
142
+ default:
143
+ throw new ReallyMeCryptoError("unsupported-algorithm");
144
+ }
145
+ },
146
+ wrapKey(algorithm, wrappingKey, keyToWrap) {
147
+ switch (algorithm) {
148
+ case "AES-128-KW":
149
+ case "AES-192-KW":
150
+ case "AES-256-KW":
151
+ return ReallyMeAesKw.wrapKeyWithProvider(algorithm, resolveWasmProvider(), wrappingKey, keyToWrap);
152
+ default:
153
+ throw new ReallyMeCryptoError("unsupported-algorithm");
154
+ }
155
+ },
156
+ unwrapKey(algorithm, wrappingKey, wrappedKey) {
157
+ switch (algorithm) {
158
+ case "AES-128-KW":
159
+ case "AES-192-KW":
160
+ case "AES-256-KW":
161
+ return ReallyMeAesKw.unwrapKeyWithProvider(algorithm, resolveWasmProvider(), wrappingKey, wrappedKey);
162
+ default:
163
+ throw new ReallyMeCryptoError("unsupported-algorithm");
164
+ }
165
+ },
166
+ });
package/dist/digest.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 { sha256 as nobleSha256, sha384 as nobleSha384, sha512 as nobleSha512 } from "@noble/hashes/sha2.js";
package/dist/ed25519.d.ts CHANGED
@@ -10,6 +10,8 @@
10
10
  export declare const ED25519_SECRET_KEY_LENGTH = 32;
11
11
  export declare const ED25519_PUBLIC_KEY_LENGTH = 32;
12
12
  export declare const ED25519_SIGNATURE_LENGTH = 64;
13
+ /** Require one canonical prime-subgroup encoding for an Ed25519 identity. */
14
+ export declare const validateEd25519PublicKeyIdentity: (publicKey: Uint8Array) => void;
13
15
  export declare const ReallyMeEd25519: {
14
16
  /** Generates a random Ed25519 keypair: 32-byte public key, 32-byte seed. */
15
17
  readonly generateKeyPair: () => {
package/dist/ed25519.js CHANGED
@@ -1,7 +1,9 @@
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 { ed25519 } from "@noble/curves/ed25519.js";
5
+ import { bytesToNumberLE, concatBytes } from "@noble/curves/utils.js";
6
+ import { sha512 } from "@noble/hashes/sha2.js";
5
7
  import { ReallyMeCryptoError } from "./errors.js";
6
8
  import { ensureByteArray } from "./validateBytes.js";
7
9
  /**
@@ -16,6 +18,25 @@ import { ensureByteArray } from "./validateBytes.js";
16
18
  export const ED25519_SECRET_KEY_LENGTH = 32;
17
19
  export const ED25519_PUBLIC_KEY_LENGTH = 32;
18
20
  export const ED25519_SIGNATURE_LENGTH = 64;
21
+ /** Require one canonical prime-subgroup encoding for an Ed25519 identity. */
22
+ export const validateEd25519PublicKeyIdentity = (publicKey) => {
23
+ ensureByteArray(publicKey);
24
+ if (publicKey.length !== ED25519_PUBLIC_KEY_LENGTH) {
25
+ throw new ReallyMeCryptoError("invalid-input");
26
+ }
27
+ try {
28
+ const point = ed25519.Point.fromBytes(publicKey, false);
29
+ const canonical = point.toBytes();
30
+ if (!point.isTorsionFree() ||
31
+ point.isSmallOrder() ||
32
+ canonical.some((byte, index) => byte !== publicKey[index])) {
33
+ throw new ReallyMeCryptoError("invalid-input");
34
+ }
35
+ }
36
+ catch {
37
+ throw new ReallyMeCryptoError("invalid-input");
38
+ }
39
+ };
19
40
  export const ReallyMeEd25519 = {
20
41
  /** Generates a random Ed25519 keypair: 32-byte public key, 32-byte seed. */
21
42
  generateKeyPair() {
@@ -78,13 +99,33 @@ export const ReallyMeEd25519 = {
78
99
  publicKey.length !== ED25519_PUBLIC_KEY_LENGTH) {
79
100
  throw new ReallyMeCryptoError("invalid-input");
80
101
  }
102
+ let point;
81
103
  try {
82
- ed25519.Point.fromBytes(publicKey, false);
104
+ point = ed25519.Point.fromBytes(publicKey, false);
83
105
  }
84
106
  catch {
85
- throw new ReallyMeCryptoError("invalid-input");
107
+ throw new ReallyMeCryptoError("invalid-signature");
108
+ }
109
+ try {
110
+ const rBytes = signature.subarray(0, ED25519_PUBLIC_KEY_LENGTH);
111
+ const rPoint = ed25519.Point.fromBytes(rBytes, false);
112
+ const scalar = bytesToNumberLE(signature.subarray(ED25519_PUBLIC_KEY_LENGTH));
113
+ const order = ed25519.Point.Fn.ORDER;
114
+ if (scalar >= order ||
115
+ !point.isTorsionFree() ||
116
+ !rPoint.isTorsionFree() ||
117
+ point.isSmallOrder() ||
118
+ rPoint.isSmallOrder()) {
119
+ throw new ReallyMeCryptoError("invalid-signature");
120
+ }
121
+ // Noble's ordinary verify uses a cofactored equation. Rust's verify_strict
122
+ // compares the full Edwards equation, including any torsion component.
123
+ const challenge = bytesToNumberLE(sha512(concatBytes(rBytes, publicKey, message))) % order;
124
+ if (!ed25519.Point.BASE.multiplyUnsafe(scalar).equals(rPoint.add(point.multiplyUnsafe(challenge)))) {
125
+ throw new ReallyMeCryptoError("invalid-signature");
126
+ }
86
127
  }
87
- if (!ed25519.verify(signature, message, publicKey, { zip215: false })) {
128
+ catch {
88
129
  throw new ReallyMeCryptoError("invalid-signature");
89
130
  }
90
131
  },
@@ -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/dist/errors.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
  export class ReallyMeCryptoError extends Error {
package/dist/hkdf.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 { hkdf } from "@noble/hashes/hkdf.js";
package/dist/hmac.d.ts CHANGED
@@ -6,7 +6,7 @@ export declare const ReallyMeHmac: {
6
6
  readonly authenticateSha256: (key: Uint8Array, message: Uint8Array) => Uint8Array;
7
7
  readonly authenticateSha384: (key: Uint8Array, message: Uint8Array) => Uint8Array;
8
8
  readonly authenticateSha512: (key: Uint8Array, message: Uint8Array) => Uint8Array;
9
- readonly verifySha256: (tag: Uint8Array, key: Uint8Array, message: Uint8Array) => boolean;
10
- readonly verifySha384: (tag: Uint8Array, key: Uint8Array, message: Uint8Array) => boolean;
11
- readonly verifySha512: (tag: Uint8Array, key: Uint8Array, message: Uint8Array) => boolean;
9
+ readonly verifySha256: (tag: Uint8Array, key: Uint8Array, message: Uint8Array) => void;
10
+ readonly verifySha384: (tag: Uint8Array, key: Uint8Array, message: Uint8Array) => void;
11
+ readonly verifySha512: (tag: Uint8Array, key: Uint8Array, message: Uint8Array) => void;
12
12
  };
package/dist/hmac.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 { hmac } from "@noble/hashes/hmac.js";
@@ -30,21 +30,21 @@ export const ReallyMeHmac = {
30
30
  if (tag.length !== HMAC_SHA256_TAG_LENGTH) {
31
31
  throw new ReallyMeCryptoError("invalid-input");
32
32
  }
33
- return verifyAndClearExpectedTag(tag, ReallyMeHmac.authenticateSha256(key, message));
33
+ verifyAndClearExpectedTag(tag, ReallyMeHmac.authenticateSha256(key, message));
34
34
  },
35
35
  verifySha384(tag, key, message) {
36
36
  ensureByteArray(tag);
37
37
  if (tag.length !== HMAC_SHA384_TAG_LENGTH) {
38
38
  throw new ReallyMeCryptoError("invalid-input");
39
39
  }
40
- return verifyAndClearExpectedTag(tag, ReallyMeHmac.authenticateSha384(key, message));
40
+ verifyAndClearExpectedTag(tag, ReallyMeHmac.authenticateSha384(key, message));
41
41
  },
42
42
  verifySha512(tag, key, message) {
43
43
  ensureByteArray(tag);
44
44
  if (tag.length !== HMAC_SHA512_TAG_LENGTH) {
45
45
  throw new ReallyMeCryptoError("invalid-input");
46
46
  }
47
- return verifyAndClearExpectedTag(tag, ReallyMeHmac.authenticateSha512(key, message));
47
+ verifyAndClearExpectedTag(tag, ReallyMeHmac.authenticateSha512(key, message));
48
48
  },
49
49
  };
50
50
  function validateKey(key) {
@@ -70,7 +70,10 @@ function constantTimeEquals(left, right) {
70
70
  }
71
71
  function verifyAndClearExpectedTag(tag, expectedTag) {
72
72
  try {
73
- return constantTimeEquals(tag, expectedTag);
73
+ if (!constantTimeEquals(tag, expectedTag)) {
74
+ // Verification must fail even when a caller ignores the return value.
75
+ throw new ReallyMeCryptoError("authentication-failed");
76
+ }
74
77
  }
75
78
  finally {
76
79
  // Noble returns a new typed array. Clear it immediately so verification
package/dist/hpke.d.ts CHANGED
@@ -5,7 +5,7 @@ export declare const HPKE_P256_PUBLIC_KEY_LENGTH = 65;
5
5
  export declare const HPKE_X25519_PRIVATE_KEY_LENGTH = 32;
6
6
  export declare const HPKE_X25519_PUBLIC_KEY_LENGTH = 32;
7
7
  export declare const HPKE_AEAD_TAG_LENGTH = 16;
8
- export declare const HPKE_INFO_MAX_LENGTH = 65530;
8
+ export declare const HPKE_INFO_MAX_LENGTH = 1048576;
9
9
  export type ReallyMeHpkeSealedMessage = Readonly<{
10
10
  encapsulatedKey: Uint8Array;
11
11
  ciphertext: Uint8Array;
package/dist/hpke.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";
@@ -9,7 +9,9 @@ export const HPKE_P256_PUBLIC_KEY_LENGTH = 65;
9
9
  export const HPKE_X25519_PRIVATE_KEY_LENGTH = 32;
10
10
  export const HPKE_X25519_PUBLIC_KEY_LENGTH = 32;
11
11
  export const HPKE_AEAD_TAG_LENGTH = 16;
12
- export const HPKE_INFO_MAX_LENGTH = 65_530;
12
+ // HKDF-based HPKE suites accept info beyond a u16 length; the package-wide
13
+ // input limit is the resource boundary for this public parameter.
14
+ export const HPKE_INFO_MAX_LENGTH = MAX_CRYPTO_INPUT_LENGTH;
13
15
  const hpkeSuite = (suite) => {
14
16
  switch (suite) {
15
17
  case "DHKEM-P256-HKDF-SHA256-HKDF-SHA256-AES-256-GCM":
package/dist/index.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
  export { ReallyMeCryptoError } from "./errors.js";
@@ -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 { sha256 } from "@noble/hashes/sha2.js";