@fgv/ts-extras 5.1.0-27 → 5.1.0-28

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 (53) hide show
  1. package/dist/packlets/crypto-utils/converters.js +24 -4
  2. package/dist/packlets/crypto-utils/converters.js.map +1 -1
  3. package/dist/packlets/crypto-utils/hpkeProvider.js +333 -0
  4. package/dist/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  5. package/dist/packlets/crypto-utils/index.browser.js +3 -0
  6. package/dist/packlets/crypto-utils/index.browser.js.map +1 -1
  7. package/dist/packlets/crypto-utils/index.js +2 -0
  8. package/dist/packlets/crypto-utils/index.js.map +1 -1
  9. package/dist/packlets/crypto-utils/keystore/converters.js +2 -2
  10. package/dist/packlets/crypto-utils/keystore/converters.js.map +1 -1
  11. package/dist/packlets/crypto-utils/keystore/keyStore.js +108 -3
  12. package/dist/packlets/crypto-utils/keystore/keyStore.js.map +1 -1
  13. package/dist/packlets/crypto-utils/keystore/model.js.map +1 -1
  14. package/dist/packlets/crypto-utils/model.js +21 -0
  15. package/dist/packlets/crypto-utils/model.js.map +1 -1
  16. package/dist/packlets/crypto-utils/nodeCryptoProvider.js +74 -0
  17. package/dist/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -1
  18. package/dist/ts-extras.d.ts +434 -18
  19. package/dist/tsdoc-metadata.json +1 -1
  20. package/lib/packlets/crypto-utils/converters.d.ts +12 -1
  21. package/lib/packlets/crypto-utils/converters.d.ts.map +1 -1
  22. package/lib/packlets/crypto-utils/converters.js +25 -5
  23. package/lib/packlets/crypto-utils/converters.js.map +1 -1
  24. package/lib/packlets/crypto-utils/hpkeProvider.d.ts +142 -0
  25. package/lib/packlets/crypto-utils/hpkeProvider.d.ts.map +1 -0
  26. package/lib/packlets/crypto-utils/hpkeProvider.js +337 -0
  27. package/lib/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  28. package/lib/packlets/crypto-utils/index.browser.d.ts +1 -0
  29. package/lib/packlets/crypto-utils/index.browser.d.ts.map +1 -1
  30. package/lib/packlets/crypto-utils/index.browser.js +5 -1
  31. package/lib/packlets/crypto-utils/index.browser.js.map +1 -1
  32. package/lib/packlets/crypto-utils/index.d.ts +1 -0
  33. package/lib/packlets/crypto-utils/index.d.ts.map +1 -1
  34. package/lib/packlets/crypto-utils/index.js +4 -1
  35. package/lib/packlets/crypto-utils/index.js.map +1 -1
  36. package/lib/packlets/crypto-utils/keystore/converters.js +1 -1
  37. package/lib/packlets/crypto-utils/keystore/converters.js.map +1 -1
  38. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts +32 -2
  39. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts.map +1 -1
  40. package/lib/packlets/crypto-utils/keystore/keyStore.js +116 -11
  41. package/lib/packlets/crypto-utils/keystore/keyStore.js.map +1 -1
  42. package/lib/packlets/crypto-utils/keystore/model.d.ts +21 -3
  43. package/lib/packlets/crypto-utils/keystore/model.d.ts.map +1 -1
  44. package/lib/packlets/crypto-utils/keystore/model.js.map +1 -1
  45. package/lib/packlets/crypto-utils/model.d.ts +165 -9
  46. package/lib/packlets/crypto-utils/model.d.ts.map +1 -1
  47. package/lib/packlets/crypto-utils/model.js +22 -1
  48. package/lib/packlets/crypto-utils/model.js.map +1 -1
  49. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts +39 -0
  50. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts.map +1 -1
  51. package/lib/packlets/crypto-utils/nodeCryptoProvider.js +74 -0
  52. package/lib/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -1
  53. package/package.json +7 -7
@@ -317,6 +317,25 @@ declare const allProviderIds: ReadonlyArray<AiProviderId>;
317
317
  */
318
318
  declare type AnthropicThinkingModelNames = 'claude-sonnet-4-5' | 'claude-sonnet-4-6' | 'claude-opus-4-6' | 'claude-opus-4-7';
319
319
 
320
+ /**
321
+ * Recommended OWASP 2023 minimum Argon2id parameters.
322
+ * Suitable for recovery-row key derivation (high-entropy inputs).
323
+ * @public
324
+ */
325
+ declare const ARGON2ID_OWASP_MIN: IArgon2idParams;
326
+
327
+ /**
328
+ * Stronger Argon2id parameters suitable for user-typed passphrases.
329
+ * @public
330
+ */
331
+ declare const ARGON2ID_PASSPHRASE: IArgon2idParams;
332
+
333
+ /**
334
+ * Converter for {@link CryptoUtils.IArgon2idKeyDerivationParams | Argon2id key derivation parameters}.
335
+ * @public
336
+ */
337
+ declare const argon2idKeyDerivationParams: Converter<IArgon2idKeyDerivationParams>;
338
+
320
339
  /**
321
340
  * Converter for base64 strings (validates format).
322
341
  * @public
@@ -481,6 +500,8 @@ declare namespace Converters_3 {
481
500
  encryptedFileFormat,
482
501
  encryptedFileErrorMode,
483
502
  keyDerivationFunction,
503
+ pbkdf2KeyDerivationParams,
504
+ argon2idKeyDerivationParams,
484
505
  keyDerivationParams,
485
506
  base64String,
486
507
  uint8ArrayFromBase64,
@@ -534,6 +555,8 @@ declare namespace CryptoUtils {
534
555
  importPublicKeyFromMultibaseSpki,
535
556
  multibaseBase64UrlDecode,
536
557
  multibaseBase64UrlEncode,
558
+ HpkeProvider,
559
+ IHpkeSealResult,
537
560
  isEncryptedFile,
538
561
  EncryptionAlgorithm,
539
562
  EncryptedFileFormat,
@@ -544,7 +567,13 @@ declare namespace CryptoUtils {
544
567
  IWrappedBytes,
545
568
  allKeyPairAlgorithms,
546
569
  KeyDerivationFunction,
570
+ IPbkdf2KeyDerivationParams,
571
+ IArgon2idKeyDerivationParams,
547
572
  IKeyDerivationParams,
573
+ IArgon2idParams,
574
+ ARGON2ID_OWASP_MIN,
575
+ ARGON2ID_PASSPHRASE,
576
+ IArgon2idProvider,
548
577
  IEncryptedFile,
549
578
  ICryptoProvider,
550
579
  IEncryptionProvider,
@@ -1035,6 +1064,128 @@ declare namespace Hash {
1035
1064
  }
1036
1065
  export { Hash }
1037
1066
 
1067
+ /**
1068
+ * HPKE base mode (RFC 9180) — `DHKEM(X25519, HKDF-SHA256) + HKDF-SHA256 + AES-256-GCM`.
1069
+ *
1070
+ * Class-based provider that captures a `SubtleCrypto` instance at construction,
1071
+ * matching the existing `NodeCryptoProvider` / `BrowserCryptoProvider` / `KeyStore`
1072
+ * factory pattern used throughout `@fgv/ts-extras/crypto-utils`.
1073
+ *
1074
+ * **Node.js usage:**
1075
+ * ```typescript
1076
+ * import * as crypto from 'crypto';
1077
+ * const hpke = HpkeProvider.create(crypto.webcrypto.subtle).orThrow();
1078
+ * ```
1079
+ *
1080
+ * **Browser usage:**
1081
+ * ```typescript
1082
+ * const hpke = HpkeProvider.create(globalThis.crypto.subtle).orThrow();
1083
+ * ```
1084
+ *
1085
+ * **Runtime requirements:** Node.js 20+ (X25519 in `crypto.webcrypto`);
1086
+ * Chrome 113+, Safari 16.4+, Firefox 118+ (X25519 added to Web Crypto in 2023).
1087
+ * @public
1088
+ */
1089
+ declare class HpkeProvider {
1090
+ private readonly _subtle;
1091
+ private constructor();
1092
+ /**
1093
+ * Creates an `HpkeProvider` bound to the given `SubtleCrypto` instance.
1094
+ *
1095
+ * @param subtle - Web Crypto SubtleCrypto instance.
1096
+ * Node.js: `(await import('crypto')).webcrypto.subtle`.
1097
+ * Browser: `globalThis.crypto.subtle`.
1098
+ * @returns `Success` with the provider, or `Failure` if construction fails.
1099
+ */
1100
+ static create(subtle: SubtleCrypto): Result<HpkeProvider>;
1101
+ /**
1102
+ * HPKE base-mode seal (sender side). RFC 9180 §6.1.
1103
+ *
1104
+ * Generates a fresh ephemeral X25519 keypair, runs DHKEM Encap to produce a
1105
+ * shared secret and `enc` (32-byte raw ephemeral public key), derives the AEAD
1106
+ * key and nonce deterministically via the RFC 9180 key schedule, then encrypts
1107
+ * `plaintext` with AES-256-GCM.
1108
+ *
1109
+ * @param recipientPublicKey - Recipient's X25519 public `CryptoKey`
1110
+ * (`algorithm.name === 'X25519'`, `type === 'public'`, **`extractable: true`**).
1111
+ * Must be extractable — DHKEM Encap calls `exportKey('raw', ...)` on this key to
1112
+ * build the KEM shared-secret context. Keys imported with `extractable: false` will
1113
+ * cause this method to return a `Failure`.
1114
+ * @param info - Context-binding bytes. **Load-bearing — no default.**
1115
+ * Binds this ciphertext to a specific application context, preventing replay
1116
+ * across different contexts sharing the same recipient keypair.
1117
+ * Use `new TextEncoder().encode('myapp/v1/use-case\x00' + contextId)` pattern.
1118
+ * Never pass an empty array in production: empty `info` provides no context binding.
1119
+ * @param aad - Additional authenticated data. Integrity-protected but not encrypted.
1120
+ * `new Uint8Array(0)` is valid when no AAD is needed.
1121
+ * @param plaintext - Bytes to encrypt. `new Uint8Array(0)` is valid.
1122
+ * @returns `Success` with `{ enc, ciphertext }`, or `Failure` with error context.
1123
+ */
1124
+ sealBase(recipientPublicKey: CryptoKey, info: Uint8Array, aad: Uint8Array, plaintext: Uint8Array): Promise<Result<IHpkeSealResult>>;
1125
+ /**
1126
+ * HPKE base-mode open (recipient side). RFC 9180 §6.1.
1127
+ *
1128
+ * Decapsulates `enc` using the recipient's X25519 private key, derives the same
1129
+ * AEAD key and nonce from the shared secret and `info`, then authenticates and
1130
+ * decrypts `ciphertext` with AES-256-GCM.
1131
+ *
1132
+ * Returns `Failure` on any of:
1133
+ * - Wrong private key (different DH output → different key derivation)
1134
+ * - Wrong `info` (different key schedule context → different AEAD key)
1135
+ * - Wrong `aad` (AES-GCM authentication fails)
1136
+ * - Tampered `ciphertext` or `enc` (authentication fails or DH fails)
1137
+ * - `enc` not exactly 32 bytes
1138
+ * - `ciphertext` shorter than 16 bytes (no room for authentication tag)
1139
+ *
1140
+ * @param recipientPrivateKey - Recipient's X25519 private `CryptoKey`
1141
+ * (`algorithm.name === 'X25519'`, `type === 'private'`, `usages` includes `'deriveBits'`).
1142
+ * **Must be extractable** (`extractable: true`) — the recipient's public key bytes
1143
+ * are recovered from the JWK `x` field during Decap.
1144
+ * @param info - Context-binding bytes. Must exactly match `info` from `sealBase`.
1145
+ * @param aad - Must exactly match `aad` from `sealBase`.
1146
+ * @param enc - The encapsulated key from `sealBase` — exactly 32 bytes.
1147
+ * @param ciphertext - The ciphertext from `sealBase` — `plaintext.length + 16` bytes.
1148
+ * @returns `Success` with decrypted plaintext bytes, or `Failure` with error context.
1149
+ */
1150
+ openBase(recipientPrivateKey: CryptoKey, info: Uint8Array, aad: Uint8Array, enc: Uint8Array, ciphertext: Uint8Array): Promise<Result<Uint8Array>>;
1151
+ /**
1152
+ * HKDF-SHA256 key derivation (RFC 5869). Extract-then-Expand using SHA-256.
1153
+ *
1154
+ * This is raw RFC 5869 HKDF — it does **not** use RFC 9180's labeled variants.
1155
+ * The HPKE key schedule internally uses labeled HKDF; this method is the unlabeled
1156
+ * version for callers that need standalone key derivation.
1157
+ *
1158
+ * @param secret - Input keying material (IKM). Any length.
1159
+ * @param salt - Optional salt. Use `new Uint8Array(0)` if no salt is available
1160
+ * (RFC 5869: 32 zero bytes are used internally when salt is empty).
1161
+ * @param info - Context / application-binding bytes. Any length.
1162
+ * @param length - Number of output bytes to derive. Maximum 8160 bytes (255 × 32).
1163
+ * @returns `Success` with derived bytes, or `Failure` with error context.
1164
+ */
1165
+ hkdf(secret: Uint8Array, salt: Uint8Array, info: Uint8Array, length: number): Promise<Result<Uint8Array>>;
1166
+ /**
1167
+ * Encodes an {@link IHpkeSealResult} as a single contiguous byte array for wire transport.
1168
+ *
1169
+ * Format: `enc` (32 bytes, fixed) || `ciphertext` (variable length).
1170
+ * The 32-byte `enc` length is fixed for X25519; the split point is unambiguous.
1171
+ *
1172
+ * @param result - The output of {@link HpkeProvider.sealBase}.
1173
+ * @returns Concatenated bytes: `enc || ciphertext`.
1174
+ */
1175
+ static encodeEnvelope(result: IHpkeSealResult): Uint8Array;
1176
+ /**
1177
+ * Decodes an envelope produced by {@link HpkeProvider.encodeEnvelope}.
1178
+ *
1179
+ * Validates that the buffer is at least 48 bytes (32-byte enc + 16-byte minimum
1180
+ * ciphertext containing the AES-GCM auth tag; zero-length plaintext is the minimum
1181
+ * meaningful case).
1182
+ *
1183
+ * @param envelope - Envelope bytes from `encodeEnvelope`.
1184
+ * @returns `Success` with `{ enc, ciphertext }`, or `Failure` if malformed.
1185
+ */
1186
+ static decodeEnvelope(envelope: Uint8Array): Result<IHpkeSealResult>;
1187
+ }
1188
+
1038
1189
  /**
1039
1190
  * Options for adding an asymmetric keypair to the key store.
1040
1191
  * @public
@@ -1079,6 +1230,25 @@ declare interface IAddKeyPairResult {
1079
1230
  readonly warning?: string;
1080
1231
  }
1081
1232
 
1233
+ /**
1234
+ * Options for adding an Argon2id password-derived secret.
1235
+ * @public
1236
+ */
1237
+ declare interface IAddSecretFromPasswordArgon2idOptions {
1238
+ /**
1239
+ * Argon2id parameters. Defaults to {@link CryptoUtils.ARGON2ID_OWASP_MIN}.
1240
+ */
1241
+ readonly params?: IArgon2idParams;
1242
+ /**
1243
+ * Optional description for the secret.
1244
+ */
1245
+ readonly description?: string;
1246
+ /**
1247
+ * Whether to replace an existing secret with the same name.
1248
+ */
1249
+ readonly replace?: boolean;
1250
+ }
1251
+
1082
1252
  /**
1083
1253
  * Options for adding a secret derived from a password.
1084
1254
  * @public
@@ -1615,6 +1785,81 @@ declare interface IAnthropicThinkingOptions {
1615
1785
  readonly config: IAnthropicThinkingConfig;
1616
1786
  }
1617
1787
 
1788
+ /**
1789
+ * Argon2id key derivation parameters (RFC 9106).
1790
+ * @public
1791
+ */
1792
+ declare interface IArgon2idKeyDerivationParams {
1793
+ /** Key derivation function discriminator. */
1794
+ readonly kdf: 'argon2id';
1795
+ /** Base64-encoded salt used for key derivation. */
1796
+ readonly salt: string;
1797
+ /** Memory cost in kibibytes. */
1798
+ readonly memoryKiB: number;
1799
+ /** Number of passes (time cost). */
1800
+ readonly iterations: number;
1801
+ /** Degree of parallelism. */
1802
+ readonly parallelism: number;
1803
+ }
1804
+
1805
+ /**
1806
+ * Parameters for Argon2id key derivation (RFC 9106).
1807
+ * All fields are required; fgv does not pick defaults silently.
1808
+ * @public
1809
+ */
1810
+ declare interface IArgon2idParams {
1811
+ /**
1812
+ * Memory cost in kibibytes (KiB).
1813
+ * OWASP 2023 minimum: 19456 (19 MiB). Stronger: 65536 (64 MiB).
1814
+ * Constraint: \>= 8.
1815
+ */
1816
+ readonly memoryKiB: number;
1817
+ /**
1818
+ * Number of passes (iterations / time cost).
1819
+ * OWASP 2023 minimum: 2. Range: \>= 1.
1820
+ */
1821
+ readonly iterations: number;
1822
+ /**
1823
+ * Degree of parallelism (threads).
1824
+ * Note: WASM-based implementations compute sequentially regardless of this value,
1825
+ * but the value is wired into the algorithm and AFFECTS the output hash bytes.
1826
+ * Callers must use the same parallelism value consistently for a given secret.
1827
+ * Range: 1–255.
1828
+ */
1829
+ readonly parallelism: number;
1830
+ /**
1831
+ * Number of output bytes (hash length).
1832
+ * Typical values: 16 (128-bit), 32 (256-bit, AES-256 key), 64 (512-bit).
1833
+ * Constraint: \>= 4.
1834
+ */
1835
+ readonly outputBytes: number;
1836
+ }
1837
+
1838
+ /**
1839
+ * Argon2id key derivation provider (RFC 9106).
1840
+ *
1841
+ * Implementations are in separate packages to avoid WASM bundle costs for
1842
+ * consumers who don't need Argon2id:
1843
+ * - Node: `@fgv/ts-extras-argon2` (`NodeArgon2Provider`)
1844
+ * - Browser: `@fgv/ts-web-extras-argon2` (`BrowserArgon2Provider`)
1845
+ *
1846
+ * @public
1847
+ */
1848
+ declare interface IArgon2idProvider {
1849
+ /**
1850
+ * Derives key material from a password using Argon2id (RFC 9106 §3.1).
1851
+ *
1852
+ * Returns the raw derived bytes as a `Uint8Array`. Both Node and browser
1853
+ * implementations produce bit-identical output for identical inputs.
1854
+ *
1855
+ * @param password - Password or passphrase. Accepts string (UTF-8) or raw bytes.
1856
+ * @param salt - Salt bytes. Must be random and unique per credential (\>= 16 bytes recommended).
1857
+ * @param params - Argon2id parameters. Use `ARGON2ID_OWASP_MIN` as a starting point.
1858
+ * @returns Success with derived bytes, Failure with error context.
1859
+ */
1860
+ argon2id(password: Uint8Array | string, salt: Uint8Array, params: IArgon2idParams): Promise<Result<Uint8Array>>;
1861
+ }
1862
+
1618
1863
  /**
1619
1864
  * A single chat message in OpenAI format.
1620
1865
  * @public
@@ -1845,6 +2090,80 @@ declare interface ICryptoProvider {
1845
2090
  * @returns `Success` with the original `plaintext`, or `Failure` with error context.
1846
2091
  */
1847
2092
  unwrapBytes(wrapped: IWrappedBytes, recipientPrivateKey: CryptoKey, options: IWrapBytesOptions): Promise<Result<Uint8Array>>;
2093
+ /**
2094
+ * Signs `data` with `privateKey` using the algorithm inferred from the key.
2095
+ * Delegates to `crypto.subtle.sign`; the algorithm is derived from
2096
+ * `privateKey.algorithm.name` — ECDSA keys are augmented with
2097
+ * `hash: 'SHA-256'` at sign time (the hash is not stored in the key);
2098
+ * all other algorithm names are passed through as-is.
2099
+ * Intended for Ed25519 and ECDSA-P256 asymmetric private keys; for
2100
+ * HMAC-SHA256 authentication codes use {@link ICryptoProvider.hmacSha256} instead.
2101
+ * @param privateKey - A `CryptoKey` with `'sign'` usage (e.g. generated by
2102
+ * {@link CryptoUtils.ICryptoProvider.generateKeyPair | generateKeyPair} with
2103
+ * `'ecdsa-p256'` or `'ed25519'`).
2104
+ * @param data - The bytes to sign.
2105
+ * @returns `Success` with the raw signature bytes, or `Failure` with error context.
2106
+ */
2107
+ sign(privateKey: CryptoKey, data: Uint8Array): Promise<Result<Uint8Array>>;
2108
+ /**
2109
+ * Verifies a signature produced by {@link ICryptoProvider.sign}.
2110
+ * Delegates to `crypto.subtle.verify`; the algorithm is derived from
2111
+ * `publicKey.algorithm.name` — ECDSA keys are augmented with
2112
+ * `hash: 'SHA-256'`; all other algorithm names are passed through as-is.
2113
+ * Intended for Ed25519 and ECDSA-P256 asymmetric public keys; for
2114
+ * HMAC-SHA256 verification use {@link ICryptoProvider.verifyHmacSha256} instead.
2115
+ * @param publicKey - A `CryptoKey` with `'verify'` usage (e.g. the public
2116
+ * half of a keypair generated by
2117
+ * {@link CryptoUtils.ICryptoProvider.generateKeyPair | generateKeyPair} with
2118
+ * `'ecdsa-p256'` or `'ed25519'`).
2119
+ * @param signature - The raw signature bytes produced by `sign`.
2120
+ * @param data - The original data that was signed.
2121
+ * @returns `Success` with `true` if the signature is valid, `false` if it is
2122
+ * not, or `Failure` with error context if the operation itself failed.
2123
+ */
2124
+ verify(publicKey: CryptoKey, signature: Uint8Array, data: Uint8Array): Promise<Result<boolean>>;
2125
+ /**
2126
+ * Compares two byte arrays in constant time.
2127
+ *
2128
+ * The comparison visits all bytes of `a` and `b` regardless of where they
2129
+ * diverge, accumulating XOR differences with bitwise-OR. No early-return is
2130
+ * possible once the length check passes, making timing independent of the
2131
+ * byte values. This prevents timing side-channels when comparing MAC outputs,
2132
+ * signed-token bytes, or any secret-derived byte sequences.
2133
+ *
2134
+ * Returns `false` immediately (before the loop) when `a.length !== b.length`;
2135
+ * the length mismatch itself is not secret in normal use.
2136
+ * @param a - First byte array.
2137
+ * @param b - Second byte array.
2138
+ * @returns `true` if the arrays have the same length and identical contents,
2139
+ * `false` otherwise.
2140
+ */
2141
+ timingSafeEqual(a: Uint8Array, b: Uint8Array): boolean;
2142
+ /**
2143
+ * Computes an HMAC-SHA256 authentication code for `data` using `key`.
2144
+ *
2145
+ * The key must be a `CryptoKey` with `'sign'` usage and algorithm name
2146
+ * `'HMAC'` (e.g. derived via PBKDF2 or imported with
2147
+ * `crypto.subtle.importKey`). Use {@link ICryptoProvider.verifyHmacSha256}
2148
+ * for constant-time verification of the output.
2149
+ * @param key - An HMAC `CryptoKey` with `'sign'` usage.
2150
+ * @param data - The bytes to authenticate.
2151
+ * @returns `Success` with the 32-byte MAC, or `Failure` with error context.
2152
+ */
2153
+ hmacSha256(key: CryptoKey, data: Uint8Array): Promise<Result<Uint8Array>>;
2154
+ /**
2155
+ * Verifies an HMAC-SHA256 authentication code in constant time.
2156
+ *
2157
+ * Computes the expected MAC over `data` with `key`, then compares it to
2158
+ * `signature` using {@link ICryptoProvider.timingSafeEqual} so that
2159
+ * mismatches do not leak information through timing.
2160
+ * @param key - An HMAC `CryptoKey` with `'sign'` usage.
2161
+ * @param signature - The MAC bytes to verify (typically 32 bytes).
2162
+ * @param data - The original data that was authenticated.
2163
+ * @returns `Success` with `true` if the MAC is valid, `false` if it is not,
2164
+ * or `Failure` with error context if the MAC computation itself failed.
2165
+ */
2166
+ verifyHmacSha256(key: CryptoKey, signature: Uint8Array, data: Uint8Array): Promise<Result<boolean>>;
1848
2167
  }
1849
2168
 
1850
2169
  /**
@@ -2181,6 +2500,26 @@ declare interface IGrokImagineModelOptions extends INamedModelFamilyConfig {
2181
2500
  readonly config: IGrokImagineImageGenerationConfig;
2182
2501
  }
2183
2502
 
2503
+ /**
2504
+ * Output of {@link HpkeProvider.sealBase}.
2505
+ *
2506
+ * The `ciphertext` field includes the 16-byte AES-256-GCM authentication tag
2507
+ * appended by Web Crypto's `encrypt()` operation: `length = plaintext.length + 16`.
2508
+ * @public
2509
+ */
2510
+ declare interface IHpkeSealResult {
2511
+ /**
2512
+ * Encapsulated key — 32-byte raw X25519 ephemeral public key (`enc` in RFC 9180).
2513
+ * Must be transmitted to the recipient alongside `ciphertext`.
2514
+ */
2515
+ readonly enc: Uint8Array;
2516
+ /**
2517
+ * AES-256-GCM ciphertext with the 16-byte authentication tag appended.
2518
+ * Length = `plaintext.length + 16`.
2519
+ */
2520
+ readonly ciphertext: Uint8Array;
2521
+ }
2522
+
2184
2523
  /**
2185
2524
  * Provider-specific config for Google Imagen 4 models.
2186
2525
  * @public
@@ -2239,23 +2578,10 @@ declare interface IImportSecretOptions extends IAddSecretOptions {
2239
2578
 
2240
2579
  /**
2241
2580
  * Key derivation parameters stored in encrypted files.
2242
- * Allows decryption with password without needing to know the original salt/iterations.
2581
+ * Discriminated union on `kdf` field: `'pbkdf2'` or `'argon2id'`.
2243
2582
  * @public
2244
2583
  */
2245
- declare interface IKeyDerivationParams {
2246
- /**
2247
- * Key derivation function used.
2248
- */
2249
- readonly kdf: KeyDerivationFunction;
2250
- /**
2251
- * Base64-encoded salt used for key derivation.
2252
- */
2253
- readonly salt: string;
2254
- /**
2255
- * Number of iterations used for key derivation.
2256
- */
2257
- readonly iterations: number;
2258
- }
2584
+ declare type IKeyDerivationParams = IPbkdf2KeyDerivationParams | IArgon2idKeyDerivationParams;
2259
2585
 
2260
2586
  /**
2261
2587
  * WebCrypto parameters for a single {@link CryptoUtils.KeyPairAlgorithm}.
@@ -2436,9 +2762,9 @@ declare interface IKeyStoreFile {
2436
2762
  */
2437
2763
  readonly encryptedData: string;
2438
2764
  /**
2439
- * Key derivation parameters (required for key store - always password-derived).
2765
+ * Key derivation parameters for the vault master key (always PBKDF2).
2440
2766
  */
2441
- readonly keyDerivation: IKeyDerivationParams;
2767
+ readonly keyDerivation: IPbkdf2KeyDerivationParams;
2442
2768
  }
2443
2769
 
2444
2770
  /**
@@ -2743,6 +3069,19 @@ declare interface IOtherThinkingOptions {
2743
3069
  readonly config: JsonObject;
2744
3070
  }
2745
3071
 
3072
+ /**
3073
+ * PBKDF2 key derivation parameters.
3074
+ * @public
3075
+ */
3076
+ declare interface IPbkdf2KeyDerivationParams {
3077
+ /** Key derivation function discriminator. */
3078
+ readonly kdf: 'pbkdf2';
3079
+ /** Base64-encoded salt used for key derivation. */
3080
+ readonly salt: string;
3081
+ /** Number of iterations used for key derivation. */
3082
+ readonly iterations: number;
3083
+ }
3084
+
2746
3085
  /**
2747
3086
  * Pluggable backend that persists raw asymmetric private keys outside of the
2748
3087
  * encrypted keystore vault. Concrete implementations live in platform-specific
@@ -3253,7 +3592,7 @@ declare const jsonWebKeyShape: Validator<JsonWebKey>;
3253
3592
  * Supported key derivation functions.
3254
3593
  * @public
3255
3594
  */
3256
- declare type KeyDerivationFunction = 'pbkdf2';
3595
+ declare type KeyDerivationFunction = 'pbkdf2' | 'argon2id';
3257
3596
 
3258
3597
  /**
3259
3598
  * Converter for {@link CryptoUtils.KeyDerivationFunction | key derivation function} type.
@@ -3263,6 +3602,7 @@ declare const keyDerivationFunction: Converter<KeyDerivationFunction>;
3263
3602
 
3264
3603
  /**
3265
3604
  * Converter for {@link CryptoUtils.IKeyDerivationParams | key derivation parameters}.
3605
+ * Handles both PBKDF2 and Argon2id discriminated union arms.
3266
3606
  * @public
3267
3607
  */
3268
3608
  declare const keyDerivationParams: Converter<IKeyDerivationParams>;
@@ -3341,6 +3681,7 @@ declare namespace KeyStore {
3341
3681
  IAddSecretFromPasswordOptions,
3342
3682
  DEFAULT_SECRET_ITERATIONS,
3343
3683
  IAddSecretFromPasswordResult,
3684
+ IAddSecretFromPasswordArgon2idOptions,
3344
3685
  IAddKeyPairOptions,
3345
3686
  IAddKeyPairResult,
3346
3687
  IRemoveSecretResult,
@@ -3577,6 +3918,36 @@ declare class KeyStore_2 implements IEncryptionProvider {
3577
3918
  * @public
3578
3919
  */
3579
3920
  verifySecretFromPassword(name: string, password: string, keyDerivation: IKeyDerivationParams): Promise<Result<boolean>>;
3921
+ /**
3922
+ * Adds a secret derived from a password using Argon2id (RFC 9106).
3923
+ *
3924
+ * The Argon2id provider must be supplied explicitly; the KeyStore does not
3925
+ * hold one by default (consumers opt in by depending on the argon2 package).
3926
+ *
3927
+ * Returns the key derivation parameters so callers can store them alongside
3928
+ * encrypted artifacts, enabling future re-derivation and verification.
3929
+ *
3930
+ * @param name - Unique name for the secret
3931
+ * @param password - Password or passphrase
3932
+ * @param argon2idProvider - Argon2id provider (Node or Browser implementation)
3933
+ * @param options - Optional: Argon2id params (defaults to ARGON2ID_OWASP_MIN), description, replace flag
3934
+ * @returns Success with entry and keyDerivation params, Failure if locked or invalid
3935
+ * @public
3936
+ */
3937
+ addSecretFromPasswordArgon2id(name: string, password: string, argon2idProvider: IArgon2idProvider, options?: IAddSecretFromPasswordArgon2idOptions): Promise<Result<IAddSecretFromPasswordResult>>;
3938
+ /**
3939
+ * Verifies a candidate password against an Argon2id-derived entry using the
3940
+ * supplied key derivation parameters. Constant-time comparison.
3941
+ *
3942
+ * @param name - Name of the secret to verify against
3943
+ * @param password - Candidate password to test
3944
+ * @param argon2idProvider - Argon2id provider (must produce bit-identical output for identical inputs)
3945
+ * @param keyDerivation - The Argon2id key derivation parameters returned by `addSecretFromPasswordArgon2id`
3946
+ * @returns Success(true) if candidate matches stored key, Success(false) if not,
3947
+ * Failure if locked, secret missing, wrong type, or derivation fails
3948
+ * @public
3949
+ */
3950
+ verifySecretFromPasswordArgon2id(name: string, password: string, argon2idProvider: IArgon2idProvider, keyDerivation: IArgon2idKeyDerivationParams): Promise<Result<boolean>>;
3580
3951
  /**
3581
3952
  * Removes a secret by name. Vault-first: the in-memory vault entry is dropped
3582
3953
  * before any storage cleanup runs. For asymmetric-keypair entries, best-effort
@@ -4129,6 +4500,45 @@ declare class NodeCryptoProvider implements ICryptoProvider {
4129
4500
  * @returns `Success` with the imported public `CryptoKey`, or `Failure` with error context.
4130
4501
  */
4131
4502
  importPublicKeySpki(spkiBytes: Uint8Array, algorithm: KeyPairAlgorithm): Promise<Result<CryptoKey>>;
4503
+ /**
4504
+ * Signs `data` with `privateKey` using the algorithm inferred from the key.
4505
+ * @param privateKey - A signing `CryptoKey` (`'ecdsa-p256'` or `'ed25519'`).
4506
+ * @param data - The bytes to sign.
4507
+ * @returns `Success` with the raw signature bytes, or `Failure` with error context.
4508
+ */
4509
+ sign(privateKey: CryptoKey, data: Uint8Array): Promise<Result<Uint8Array>>;
4510
+ /**
4511
+ * Verifies a signature produced by {@link NodeCryptoProvider.sign}.
4512
+ * @param publicKey - A verify `CryptoKey` (`'ecdsa-p256'` or `'ed25519'`).
4513
+ * @param signature - The raw signature bytes.
4514
+ * @param data - The original data that was signed.
4515
+ * @returns `Success` with `true` if valid, `false` if not, or `Failure` with error context.
4516
+ */
4517
+ verify(publicKey: CryptoKey, signature: Uint8Array, data: Uint8Array): Promise<Result<boolean>>;
4518
+ /**
4519
+ * Compares two byte arrays in constant time using Node's native
4520
+ * `crypto.timingSafeEqual`. Returns `false` for mismatched lengths
4521
+ * rather than throwing (Node's native throws on length mismatch).
4522
+ * @param a - First byte array.
4523
+ * @param b - Second byte array.
4524
+ * @returns `true` if lengths match and all bytes are equal, `false` otherwise.
4525
+ */
4526
+ timingSafeEqual(a: Uint8Array, b: Uint8Array): boolean;
4527
+ /**
4528
+ * Computes an HMAC-SHA256 MAC for `data` using `key`.
4529
+ * @param key - An HMAC `CryptoKey` with `'sign'` usage.
4530
+ * @param data - The bytes to authenticate.
4531
+ * @returns `Success` with the 32-byte MAC, or `Failure` with error context.
4532
+ */
4533
+ hmacSha256(key: CryptoKey, data: Uint8Array): Promise<Result<Uint8Array>>;
4534
+ /**
4535
+ * Verifies an HMAC-SHA256 MAC in constant time.
4536
+ * @param key - An HMAC `CryptoKey` with `'sign'` usage.
4537
+ * @param signature - The MAC bytes to verify.
4538
+ * @param data - The original data that was authenticated.
4539
+ * @returns `Success` with `true` if valid, `false` if not, or `Failure` with error context.
4540
+ */
4541
+ verifyHmacSha256(key: CryptoKey, signature: Uint8Array, data: Uint8Array): Promise<Result<boolean>>;
4132
4542
  /**
4133
4543
  * Wraps `plaintext` for the holder of `recipientPublicKey` using
4134
4544
  * ECIES (ECDH P-256 + HKDF-SHA256 + AES-GCM-256). See
@@ -4181,6 +4591,12 @@ declare function parseCsvString(body: string, options?: CsvOptions): Result<unkn
4181
4591
  */
4182
4592
  declare function parseRecordJarLines(lines: string[], options?: JarRecordParserOptions): Result<JarRecord[]>;
4183
4593
 
4594
+ /**
4595
+ * Converter for {@link CryptoUtils.IPbkdf2KeyDerivationParams | PBKDF2 key derivation parameters}.
4596
+ * @public
4597
+ */
4598
+ declare const pbkdf2KeyDerivationParams: Converter<IPbkdf2KeyDerivationParams>;
4599
+
4184
4600
  /**
4185
4601
  * Simple implementation of a possibly open-ended range of some comparable
4186
4602
  * type `<T>` with test and formatting.
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.57.7"
8
+ "packageVersion": "7.58.7"
9
9
  }
10
10
  ]
11
11
  }
@@ -1,6 +1,6 @@
1
1
  import { JsonValue } from '@fgv/ts-json-base';
2
2
  import { Converter } from '@fgv/ts-utils';
3
- import { EncryptedFileErrorMode, EncryptedFileFormat, EncryptionAlgorithm, IEncryptedFile, IKeyDerivationParams, INamedSecret, KeyDerivationFunction } from './model';
3
+ import { EncryptedFileErrorMode, EncryptedFileFormat, EncryptionAlgorithm, IArgon2idKeyDerivationParams, IEncryptedFile, IKeyDerivationParams, INamedSecret, IPbkdf2KeyDerivationParams, KeyDerivationFunction } from './model';
4
4
  /**
5
5
  * Converter for {@link CryptoUtils.EncryptionAlgorithm | encryption algorithm} values.
6
6
  * @public
@@ -21,8 +21,19 @@ export declare const encryptedFileErrorMode: Converter<EncryptedFileErrorMode>;
21
21
  * @public
22
22
  */
23
23
  export declare const keyDerivationFunction: Converter<KeyDerivationFunction>;
24
+ /**
25
+ * Converter for {@link CryptoUtils.IPbkdf2KeyDerivationParams | PBKDF2 key derivation parameters}.
26
+ * @public
27
+ */
28
+ export declare const pbkdf2KeyDerivationParams: Converter<IPbkdf2KeyDerivationParams>;
29
+ /**
30
+ * Converter for {@link CryptoUtils.IArgon2idKeyDerivationParams | Argon2id key derivation parameters}.
31
+ * @public
32
+ */
33
+ export declare const argon2idKeyDerivationParams: Converter<IArgon2idKeyDerivationParams>;
24
34
  /**
25
35
  * Converter for {@link CryptoUtils.IKeyDerivationParams | key derivation parameters}.
36
+ * Handles both PBKDF2 and Argon2id discriminated union arms.
26
37
  * @public
27
38
  */
28
39
  export declare const keyDerivationParams: Converter<IKeyDerivationParams>;
@@ -1 +1 @@
1
- {"version":3,"file":"converters.d.ts","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/converters.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAgC,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,SAAS,EAA6B,MAAM,eAAe,CAAC;AAErE,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,YAAY,EACZ,qBAAqB,EACtB,MAAM,SAAS,CAAC;AAMjB;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,mBAAmB,CACiB,CAAC;AAEjF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,mBAAmB,CAE7D,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,CAAC,sBAAsB,CACS,CAAC;AAE/E;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,CAAC,qBAAqB,CACJ,CAAC;AAEhE;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,oBAAoB,CAI9D,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,SAAS,CAAC,MAAM,CAOzC,CAAC;AAMH;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,CAAC,UAAU,CAoBrD,CAAC;AAMH;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,YAAY,CAG9C,CAAC;AAsCH;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,SAAS,GAAG,SAAS,EAChE,iBAAiB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,GACvC,SAAS,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAyBtC;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,cAAc,CAAkC,CAAC"}
1
+ {"version":3,"file":"converters.d.ts","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/converters.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAgC,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,SAAS,EAA6B,MAAM,eAAe,CAAC;AAErE,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,4BAA4B,EAC5B,cAAc,EACd,oBAAoB,EACpB,YAAY,EACZ,0BAA0B,EAC1B,qBAAqB,EACtB,MAAM,SAAS,CAAC;AAMjB;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,mBAAmB,CACiB,CAAC;AAEjF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,mBAAmB,CAE7D,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,CAAC,sBAAsB,CACS,CAAC;AAE/E;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,CAAC,qBAAqB,CACQ,CAAC;AAE5E;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,SAAS,CAAC,0BAA0B,CAKxE,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,SAAS,CAAC,4BAA4B,CAO5E,CAAC;AAEL;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,oBAAoB,CAG9D,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,SAAS,CAAC,MAAM,CAOzC,CAAC;AAMH;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,CAAC,UAAU,CAoBrD,CAAC;AAMH;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,YAAY,CAG9C,CAAC;AAsCH;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,SAAS,GAAG,SAAS,EAChE,iBAAiB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,GACvC,SAAS,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAyBtC;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,cAAc,CAAkC,CAAC"}
@@ -52,7 +52,7 @@ var __importStar = (this && this.__importStar) || (function () {
52
52
  };
53
53
  })();
54
54
  Object.defineProperty(exports, "__esModule", { value: true });
55
- exports.encryptedFile = exports.namedSecret = exports.uint8ArrayFromBase64 = exports.base64String = exports.keyDerivationParams = exports.keyDerivationFunction = exports.encryptedFileErrorMode = exports.encryptedFileFormat = exports.encryptionAlgorithm = void 0;
55
+ exports.encryptedFile = exports.namedSecret = exports.uint8ArrayFromBase64 = exports.base64String = exports.keyDerivationParams = exports.argon2idKeyDerivationParams = exports.pbkdf2KeyDerivationParams = exports.keyDerivationFunction = exports.encryptedFileErrorMode = exports.encryptedFileFormat = exports.encryptionAlgorithm = void 0;
56
56
  exports.createEncryptedFileConverter = createEncryptedFileConverter;
57
57
  const ts_json_base_1 = require("@fgv/ts-json-base");
58
58
  const ts_utils_1 = require("@fgv/ts-utils");
@@ -81,16 +81,36 @@ exports.encryptedFileErrorMode = ts_utils_1.Converters.enumeratedValue(['fail',
81
81
  * Converter for {@link CryptoUtils.KeyDerivationFunction | key derivation function} type.
82
82
  * @public
83
83
  */
84
- exports.keyDerivationFunction = ts_utils_1.Converters.enumeratedValue(['pbkdf2']);
84
+ exports.keyDerivationFunction = ts_utils_1.Converters.enumeratedValue(['pbkdf2', 'argon2id']);
85
85
  /**
86
- * Converter for {@link CryptoUtils.IKeyDerivationParams | key derivation parameters}.
86
+ * Converter for {@link CryptoUtils.IPbkdf2KeyDerivationParams | PBKDF2 key derivation parameters}.
87
87
  * @public
88
88
  */
89
- exports.keyDerivationParams = ts_utils_1.Converters.object({
90
- kdf: exports.keyDerivationFunction,
89
+ exports.pbkdf2KeyDerivationParams = ts_utils_1.Converters.object({
90
+ kdf: ts_utils_1.Converters.enumeratedValue(['pbkdf2']),
91
91
  salt: ts_utils_1.Converters.string,
92
92
  iterations: ts_utils_1.Converters.number
93
93
  });
94
+ /**
95
+ * Converter for {@link CryptoUtils.IArgon2idKeyDerivationParams | Argon2id key derivation parameters}.
96
+ * @public
97
+ */
98
+ exports.argon2idKeyDerivationParams = ts_utils_1.Converters.object({
99
+ kdf: ts_utils_1.Converters.enumeratedValue(['argon2id']),
100
+ salt: ts_utils_1.Converters.string,
101
+ memoryKiB: ts_utils_1.Converters.number,
102
+ iterations: ts_utils_1.Converters.number,
103
+ parallelism: ts_utils_1.Converters.number
104
+ });
105
+ /**
106
+ * Converter for {@link CryptoUtils.IKeyDerivationParams | key derivation parameters}.
107
+ * Handles both PBKDF2 and Argon2id discriminated union arms.
108
+ * @public
109
+ */
110
+ exports.keyDerivationParams = ts_utils_1.Converters.oneOf([
111
+ exports.pbkdf2KeyDerivationParams,
112
+ exports.argon2idKeyDerivationParams
113
+ ]);
94
114
  /**
95
115
  * Converter for base64 strings (validates format).
96
116
  * @public