@zudojs/crypto 1.3.2 → 1.4.0
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.
- package/README.md +5 -5
- package/dist/compare/compare.helper.d.ts +0 -1
- package/dist/compare/compare.helper.js +0 -1
- package/dist/compare/index.d.ts +0 -1
- package/dist/compare/index.js +0 -1
- package/dist/cryptoCipher/cryptoCipher.core.d.ts +12 -1
- package/dist/cryptoCipher/cryptoCipher.core.js +9 -1
- package/dist/cryptoCipher/cryptoCipher.envelope.d.ts +0 -1
- package/dist/cryptoCipher/cryptoCipher.envelope.js +0 -1
- package/dist/cryptoCipher/cryptoCipher.nonceGuard.d.ts +24 -0
- package/dist/cryptoCipher/cryptoCipher.nonceGuard.js +50 -0
- package/dist/cryptoCipher/cryptoCipher.string.d.ts +0 -1
- package/dist/cryptoCipher/cryptoCipher.string.js +0 -1
- package/dist/cryptoCipher/index.d.ts +1 -1
- package/dist/cryptoCipher/index.js +1 -1
- package/dist/cryptoConstants/cryptoConstants.config.d.ts +0 -1
- package/dist/cryptoConstants/cryptoConstants.config.js +0 -1
- package/dist/cryptoConstants/cryptoConstants.guard.d.ts +0 -1
- package/dist/cryptoConstants/cryptoConstants.guard.js +0 -1
- package/dist/cryptoConstants/cryptoConstants.security.d.ts +0 -1
- package/dist/cryptoConstants/cryptoConstants.security.js +0 -1
- package/dist/cryptoConstants/cryptoConstants.token.d.ts +0 -1
- package/dist/cryptoConstants/cryptoConstants.token.js +0 -1
- package/dist/cryptoConstants/cryptoConstants.type.d.ts +0 -1
- package/dist/cryptoConstants/cryptoConstants.type.js +0 -1
- package/dist/cryptoConstants/index.d.ts +0 -1
- package/dist/cryptoConstants/index.js +0 -1
- package/dist/cryptoEncoding/cryptoEncoding.arrayBuffer.d.ts +0 -1
- package/dist/cryptoEncoding/cryptoEncoding.arrayBuffer.js +0 -1
- package/dist/cryptoEncoding/cryptoEncoding.compare.d.ts +0 -1
- package/dist/cryptoEncoding/cryptoEncoding.compare.js +0 -1
- package/dist/cryptoEncoding/cryptoEncoding.core.d.ts +0 -1
- package/dist/cryptoEncoding/cryptoEncoding.core.js +0 -1
- package/dist/cryptoEncoding/encoding/cryptoEncoding.base64.d.ts +0 -1
- package/dist/cryptoEncoding/encoding/cryptoEncoding.base64.js +0 -1
- package/dist/cryptoEncoding/encoding/cryptoEncoding.base64url.d.ts +0 -1
- package/dist/cryptoEncoding/encoding/cryptoEncoding.base64url.js +0 -1
- package/dist/cryptoEncoding/encoding/cryptoEncoding.hex.d.ts +0 -1
- package/dist/cryptoEncoding/encoding/cryptoEncoding.hex.js +0 -1
- package/dist/cryptoEncoding/encoding/index.d.ts +0 -1
- package/dist/cryptoEncoding/encoding/index.js +0 -1
- package/dist/cryptoEncoding/index.d.ts +0 -1
- package/dist/cryptoEncoding/index.js +0 -1
- package/dist/cryptoErrors/cryptoErrors.helper.d.ts +13 -1
- package/dist/cryptoErrors/cryptoErrors.helper.js +18 -1
- package/dist/cryptoErrors/index.d.ts +0 -1
- package/dist/cryptoErrors/index.js +0 -1
- package/dist/cryptoFactory/cryptoFactory.core.d.ts +0 -1
- package/dist/cryptoFactory/cryptoFactory.core.js +0 -1
- package/dist/cryptoFactory/cryptoFactory.encoding.d.ts +0 -1
- package/dist/cryptoFactory/cryptoFactory.encoding.js +0 -1
- package/dist/cryptoFactory/cryptoFactory.password.d.ts +0 -1
- package/dist/cryptoFactory/cryptoFactory.password.js +0 -1
- package/dist/cryptoFactory/cryptoFactory.token.d.ts +0 -1
- package/dist/cryptoFactory/cryptoFactory.token.js +0 -1
- package/dist/cryptoFactory/index.d.ts +0 -1
- package/dist/cryptoFactory/index.js +0 -1
- package/dist/cryptoHash/cryptoHash.codec.d.ts +0 -1
- package/dist/cryptoHash/cryptoHash.codec.js +0 -1
- package/dist/cryptoHash/cryptoHash.compare.d.ts +0 -1
- package/dist/cryptoHash/cryptoHash.compare.js +0 -1
- package/dist/cryptoHash/cryptoHash.convenience.d.ts +0 -1
- package/dist/cryptoHash/cryptoHash.convenience.js +0 -1
- package/dist/cryptoHash/cryptoHash.core.d.ts +0 -1
- package/dist/cryptoHash/cryptoHash.core.js +0 -1
- package/dist/cryptoHash/cryptoHmac.core.d.ts +9 -3
- package/dist/cryptoHash/cryptoHmac.core.js +15 -5
- package/dist/cryptoHash/index.d.ts +0 -1
- package/dist/cryptoHash/index.js +0 -1
- package/dist/cryptoKey/cryptoKey.factory.d.ts +6 -1
- package/dist/cryptoKey/cryptoKey.factory.js +8 -2
- package/dist/cryptoKey/cryptoKey.type.d.ts +12 -1
- package/dist/cryptoKey/cryptoKey.type.js +0 -1
- package/dist/cryptoKey/cryptoKey.utils.d.ts +0 -1
- package/dist/cryptoKey/cryptoKey.utils.js +0 -1
- package/dist/cryptoKey/index.d.ts +0 -1
- package/dist/cryptoKey/index.js +0 -1
- package/dist/cryptoKeyDerivation/cryptoKeyDerivation.core.d.ts +0 -1
- package/dist/cryptoKeyDerivation/cryptoKeyDerivation.core.js +0 -1
- package/dist/cryptoKeyDerivation/cryptoKeyDerivation.salt.d.ts +4 -2
- package/dist/cryptoKeyDerivation/cryptoKeyDerivation.salt.js +6 -3
- package/dist/cryptoKeyDerivation/cryptoKeyDerivation.type.d.ts +0 -1
- package/dist/cryptoKeyDerivation/cryptoKeyDerivation.type.js +0 -1
- package/dist/cryptoKeyDerivation/cryptoKeyDerivation.validate.d.ts +6 -1
- package/dist/cryptoKeyDerivation/cryptoKeyDerivation.validate.js +17 -11
- package/dist/cryptoKeyDerivation/index.d.ts +0 -1
- package/dist/cryptoKeyDerivation/index.js +0 -1
- package/dist/cryptoPassword/cryptoPassword.codec.d.ts +0 -1
- package/dist/cryptoPassword/cryptoPassword.codec.js +0 -1
- package/dist/cryptoPassword/cryptoPassword.core.d.ts +10 -1
- package/dist/cryptoPassword/cryptoPassword.core.js +13 -4
- package/dist/cryptoPassword/cryptoPassword.helper.d.ts +10 -2
- package/dist/cryptoPassword/cryptoPassword.helper.js +26 -4
- package/dist/cryptoPassword/cryptoPassword.type.d.ts +0 -1
- package/dist/cryptoPassword/cryptoPassword.type.js +0 -1
- package/dist/cryptoPassword/cryptoPassword.validate.d.ts +4 -6
- package/dist/cryptoPassword/cryptoPassword.validate.js +13 -24
- package/dist/cryptoPassword/index.d.ts +0 -1
- package/dist/cryptoPassword/index.js +0 -1
- package/dist/cryptoProvider/cryptoProvider.capability.d.ts +0 -1
- package/dist/cryptoProvider/cryptoProvider.capability.js +0 -1
- package/dist/cryptoProvider/cryptoProvider.core.d.ts +0 -1
- package/dist/cryptoProvider/cryptoProvider.core.js +0 -1
- package/dist/cryptoProvider/cryptoProvider.default.d.ts +0 -1
- package/dist/cryptoProvider/cryptoProvider.default.js +0 -1
- package/dist/cryptoProvider/cryptoProvider.interface.d.ts +0 -1
- package/dist/cryptoProvider/cryptoProvider.interface.js +0 -1
- package/dist/cryptoProvider/cryptoProvider.type.d.ts +0 -1
- package/dist/cryptoProvider/cryptoProvider.type.js +0 -1
- package/dist/cryptoProvider/index.d.ts +0 -1
- package/dist/cryptoProvider/index.js +0 -1
- package/dist/cryptoProvider/types/cryptoCipher.type.d.ts +0 -1
- package/dist/cryptoProvider/types/cryptoCipher.type.js +0 -1
- package/dist/cryptoProvider/types/cryptoHash.type.d.ts +0 -1
- package/dist/cryptoProvider/types/cryptoHash.type.js +0 -1
- package/dist/cryptoProvider/types/cryptoKeyDerivation.type.d.ts +0 -1
- package/dist/cryptoProvider/types/cryptoKeyDerivation.type.js +0 -1
- package/dist/cryptoProvider/types/cryptoRandom.type.d.ts +0 -1
- package/dist/cryptoProvider/types/cryptoRandom.type.js +0 -1
- package/dist/cryptoProvider/types/cryptoSignature.type.d.ts +9 -3
- package/dist/cryptoProvider/types/cryptoSignature.type.js +0 -1
- package/dist/cryptoProvider/types/index.d.ts +1 -2
- package/dist/cryptoProvider/types/index.js +0 -1
- package/dist/cryptoRandom/cryptoRandom.choice.d.ts +0 -1
- package/dist/cryptoRandom/cryptoRandom.choice.js +0 -1
- package/dist/cryptoRandom/cryptoRandom.core.d.ts +0 -1
- package/dist/cryptoRandom/cryptoRandom.core.js +0 -1
- package/dist/cryptoRandom/cryptoRandom.string.d.ts +7 -1
- package/dist/cryptoRandom/cryptoRandom.string.js +7 -1
- package/dist/cryptoRandom/index.d.ts +0 -1
- package/dist/cryptoRandom/index.js +0 -1
- package/dist/cryptoService/cryptoService.core.d.ts +0 -1
- package/dist/cryptoService/cryptoService.core.js +0 -1
- package/dist/cryptoService/cryptoService.derivation.d.ts +0 -1
- package/dist/cryptoService/cryptoService.derivation.js +0 -1
- package/dist/cryptoService/cryptoService.encoding.d.ts +0 -1
- package/dist/cryptoService/cryptoService.encoding.js +0 -1
- package/dist/cryptoService/index.d.ts +0 -1
- package/dist/cryptoService/index.js +0 -1
- package/dist/cryptoService/operations/cryptoService.cipher.d.ts +0 -1
- package/dist/cryptoService/operations/cryptoService.cipher.js +0 -1
- package/dist/cryptoService/operations/cryptoService.hash.d.ts +0 -1
- package/dist/cryptoService/operations/cryptoService.hash.js +0 -1
- package/dist/cryptoService/operations/cryptoService.password.d.ts +0 -1
- package/dist/cryptoService/operations/cryptoService.password.js +0 -1
- package/dist/cryptoService/operations/cryptoService.token.d.ts +0 -1
- package/dist/cryptoService/operations/cryptoService.token.js +0 -1
- package/dist/cryptoService/operations/index.d.ts +0 -1
- package/dist/cryptoService/operations/index.js +0 -1
- package/dist/cryptoSignature/cryptoSignature.core.d.ts +5 -6
- package/dist/cryptoSignature/cryptoSignature.core.js +0 -1
- package/dist/cryptoSignature/index.d.ts +0 -1
- package/dist/cryptoSignature/index.js +0 -1
- package/dist/cryptoToken/cryptoToken.core.d.ts +0 -1
- package/dist/cryptoToken/cryptoToken.core.js +0 -1
- package/dist/cryptoToken/cryptoToken.hash.d.ts +0 -1
- package/dist/cryptoToken/cryptoToken.hash.js +0 -1
- package/dist/cryptoToken/cryptoToken.utils.d.ts +0 -1
- package/dist/cryptoToken/cryptoToken.utils.js +0 -1
- package/dist/cryptoToken/index.d.ts +0 -1
- package/dist/cryptoToken/index.js +0 -1
- package/dist/cryptoUtils/cryptoUtils.compare.d.ts +0 -1
- package/dist/cryptoUtils/cryptoUtils.compare.js +0 -1
- package/dist/cryptoUtils/cryptoUtils.conversion.d.ts +0 -1
- package/dist/cryptoUtils/cryptoUtils.conversion.js +0 -1
- package/dist/cryptoUtils/cryptoUtils.number.d.ts +0 -1
- package/dist/cryptoUtils/cryptoUtils.number.js +0 -1
- package/dist/cryptoUtils/cryptoUtils.text.d.ts +0 -1
- package/dist/cryptoUtils/cryptoUtils.text.js +0 -1
- package/dist/cryptoUtils/cryptoUtils.validation.d.ts +0 -1
- package/dist/cryptoUtils/cryptoUtils.validation.js +0 -1
- package/dist/cryptoUtils/encoding/cryptoUtils.base64.d.ts +0 -1
- package/dist/cryptoUtils/encoding/cryptoUtils.base64.js +0 -1
- package/dist/cryptoUtils/encoding/cryptoUtils.base64url.d.ts +0 -1
- package/dist/cryptoUtils/encoding/cryptoUtils.base64url.js +0 -1
- package/dist/cryptoUtils/encoding/cryptoUtils.hex.d.ts +0 -1
- package/dist/cryptoUtils/encoding/cryptoUtils.hex.js +0 -1
- package/dist/cryptoUtils/encoding/index.d.ts +0 -1
- package/dist/cryptoUtils/encoding/index.js +0 -1
- package/dist/cryptoUtils/index.d.ts +0 -1
- package/dist/cryptoUtils/index.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/node/index.d.ts +0 -1
- package/dist/node/index.js +0 -1
- package/dist/node/nodeCryptoProvider/index.d.ts +0 -1
- package/dist/node/nodeCryptoProvider/index.js +0 -1
- package/dist/node/nodeCryptoProvider/nodeCryptoProvider.core.d.ts +0 -1
- package/dist/node/nodeCryptoProvider/nodeCryptoProvider.core.js +0 -1
- package/dist/node/nodeCryptoProvider/nodeCryptoProvider.factory.d.ts +0 -1
- package/dist/node/nodeCryptoProvider/nodeCryptoProvider.factory.js +0 -1
- package/dist/node/nodeCryptoProvider/nodeCryptoProvider.helper.d.ts +0 -1
- package/dist/node/nodeCryptoProvider/nodeCryptoProvider.helper.js +0 -1
- package/dist/node/nodeCryptoProvider/operations/index.d.ts +0 -1
- package/dist/node/nodeCryptoProvider/operations/index.js +0 -1
- package/dist/node/nodeCryptoProvider/operations/nodeCryptoProvider.derivation.d.ts +0 -1
- package/dist/node/nodeCryptoProvider/operations/nodeCryptoProvider.derivation.js +0 -1
- package/dist/node/nodeCryptoProvider/operations/nodeCryptoProvider.password.d.ts +0 -1
- package/dist/node/nodeCryptoProvider/operations/nodeCryptoProvider.password.js +0 -1
- package/dist/node/nodeCryptoProvider/primitives/index.d.ts +0 -1
- package/dist/node/nodeCryptoProvider/primitives/index.js +0 -1
- package/dist/node/nodeCryptoProvider/primitives/nodeCryptoProvider.encryption.d.ts +0 -1
- package/dist/node/nodeCryptoProvider/primitives/nodeCryptoProvider.encryption.js +0 -1
- package/dist/node/nodeCryptoProvider/primitives/nodeCryptoProvider.hash.d.ts +0 -1
- package/dist/node/nodeCryptoProvider/primitives/nodeCryptoProvider.hash.js +0 -1
- package/dist/node/nodeCryptoProvider/primitives/nodeCryptoProvider.random.d.ts +0 -1
- package/dist/node/nodeCryptoProvider/primitives/nodeCryptoProvider.random.js +0 -1
- package/dist/node/nodeCryptoProvider/primitives/nodeCryptoProvider.signing.d.ts +0 -1
- package/dist/node/nodeCryptoProvider/primitives/nodeCryptoProvider.signing.js +0 -1
- package/dist/node/signing/index.d.ts +0 -1
- package/dist/node/signing/index.js +0 -1
- package/dist/node/signing/signing.conversion.d.ts +0 -1
- package/dist/node/signing/signing.conversion.js +0 -1
- package/dist/node/signing/signing.core.d.ts +0 -1
- package/dist/node/signing/signing.core.js +0 -1
- package/dist/node/signing/signing.utils.d.ts +0 -1
- package/dist/node/signing/signing.utils.js +0 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -46,12 +46,12 @@ const sessionToken = await generateToken({ bytes: 32, prefix: "sess_" });
|
|
|
46
46
|
|
|
47
47
|
## Features
|
|
48
48
|
|
|
49
|
-
- Hashing: SHA-256/384/512 and SHA3-256/384/512, HMAC (
|
|
50
|
-
- Authenticated encryption: AES-256-GCM with strict IV (12 bytes) and tag (16 bytes) validation, plus a versioned string envelope
|
|
51
|
-
- Password hashing: scrypt (default N=2^14, r=8, p=5 — the OWASP row for that N) and PBKDF2-HMAC (provider level), versioned self-describing encoding, bounded parameters on verification. New hashes must use a cost of at least `PASSWORD_HASH.SCRYPT.MIN_COST` (16 384); older stored hashes with a smaller cost still verify. Key derivation (`deriveScrypt`) keeps p=1 by default, so derived keys do not change
|
|
49
|
+
- Hashing: SHA-256/384/512 and SHA3-256/384/512, HMAC (the key is a `Uint8Array` of at least 16 bytes — encode a string secret with `new TextEncoder().encode(secret)` first)
|
|
50
|
+
- Authenticated encryption: AES-256-GCM with strict IV (12 bytes) and tag (16 bytes) validation, plus a versioned string envelope. Omit `iv` to get a fresh random one per call; a caller-supplied `iv` is refused if this process already encrypted with it under the same key (`unsafeAllowIvReuse` opts out, for test vectors only)
|
|
51
|
+
- Password hashing: scrypt (default N=2^14, r=8, p=5 — the OWASP row for that N) and PBKDF2-HMAC (provider level), versioned self-describing encoding, bounded parameters on verification. New hashes must use a cost of at least `PASSWORD_HASH.SCRYPT.MIN_COST` (16 384); older stored hashes with a smaller cost still verify. Key derivation (`deriveScrypt`) keeps p=1 by default, so derived keys do not change. `hashPassword(password, { minLength: PASSWORD_POLICY.MIN_LENGTH })` opts into the 8-character minimum; the default stays permissive so existing credentials can be re-hashed
|
|
52
52
|
- Key derivation: PBKDF2 (sha256/384/512, 600 000 iterations by default) and scrypt (cost, block size, parallelization, memory bound); every work factor and the output length are capped by `PASSWORD_HASH.LIMITS`, so a value read from configuration cannot request unbounded CPU or memory
|
|
53
53
|
- Digital signatures: Ed25519, RSA-SHA256/384/512, ECDSA-SHA256/384/512; the algorithm label is bound to the key type
|
|
54
|
-
- Secure random: unbiased integers up to 2^48, UUID v4, bytes, alphabets, numeric codes
|
|
54
|
+
- Secure random: unbiased integers up to 2^48, UUID v4, bytes, alphabets, numeric codes. Units: `randomHex(n)` is `n` characters, `randomBase64Url(n)` is `n` bytes, `generateCryptoKey(n)` is `n` bytes and the resulting `CryptoKey` reports `length` in bits and `byteLength` in bytes
|
|
55
55
|
- Opaque tokens (API keys, sessions, refresh, CSRF, OTP) with SHA-256 storage hashes
|
|
56
56
|
- Encoding helpers (hex, base64, base64url, strict UTF-8) with canonical-form validation and constant-time comparison
|
|
57
57
|
- Provider injection: `setDefaultCryptoProvider`, `createCryptoService({ provider })`, `createCryptoFactory({ provider })`, or a `provider` option on any helper
|
|
@@ -60,7 +60,7 @@ Not implemented (and not advertised by the types): bcrypt, Argon2, ChaCha20-Poly
|
|
|
60
60
|
|
|
61
61
|
## Errors
|
|
62
62
|
|
|
63
|
-
Failures throw `CryptoError` from `@zudojs/errors` with a stable `code` (`ERR_CRYPTO_CIPHER`, `ERR_CRYPTO_HASH`, ...) and the underlying Node error as `cause`. `verifyPassword` and `verifyTokenHash` return `false` (never throw) for wrong or malformed inputs.
|
|
63
|
+
Failures throw `CryptoError` from `@zudojs/errors` with a stable `code` (`ERR_CRYPTO_CIPHER`, `ERR_CRYPTO_HASH`, ...) and the underlying Node error as `cause`. Cryptographic parameter violations are `CryptoError`s too: a short HMAC key (`ERR_CRYPTO_HASH`), an out-of-range scrypt/PBKDF2 work factor (`ERR_CRYPTO_DERIVATION` for `derive*`, `ERR_CRYPTO_HASH` for `hashPassword`), a bad key length (`ERR_CRYPTO_KEY`), and a password outside the length bounds (`ERR_CRYPTO_HASH` with `statusCode: 400` and `expose: true`, since the end user can act on it). Plain argument-shape mistakes — a non-`Uint8Array` key, an unknown algorithm name, a non-integer random length — stay `TypeError`/`RangeError`. `verifyPassword` and `verifyTokenHash` return `false` (never throw) for wrong or malformed inputs.
|
|
64
64
|
|
|
65
65
|
## Use Cases
|
|
66
66
|
|
|
@@ -13,4 +13,3 @@ export declare function timingSafeEqual(left: Uint8Array, right: Uint8Array): bo
|
|
|
13
13
|
* Performs a constant-time comparison of two strings by their UTF-8 bytes.
|
|
14
14
|
*/
|
|
15
15
|
export declare function timingSafeEqualString(left: string, right: string): boolean;
|
|
16
|
-
//# sourceMappingURL=compare.helper.d.ts.map
|
package/dist/compare/index.d.ts
CHANGED
package/dist/compare/index.js
CHANGED
|
@@ -6,11 +6,20 @@ import type { CryptoProvider } from "../cryptoProvider/index.js";
|
|
|
6
6
|
* key. Reusing an IV under the same key with AES-GCM leaks the XOR of the
|
|
7
7
|
* plaintexts and allows authentication-key recovery; omit it to have a
|
|
8
8
|
* fresh random IV drawn for every call.
|
|
9
|
+
*
|
|
10
|
+
* A supplied `iv` is checked against every (key, iv) pair this process has
|
|
11
|
+
* already encrypted with, and a repeat is refused with a `CryptoError`
|
|
12
|
+
* (see {@link assertIvNotReused}). The check is per process and cannot
|
|
13
|
+
* see other processes or earlier runs, so it is a safety net, not a
|
|
14
|
+
* uniqueness guarantee. `unsafeAllowIvReuse` disables it for the rare case
|
|
15
|
+
* that genuinely needs a repeated nonce, such as replaying a published
|
|
16
|
+
* test vector; never set it in application code.
|
|
9
17
|
*/
|
|
10
18
|
export interface CipherOptions {
|
|
11
19
|
readonly iv?: Uint8Array;
|
|
12
20
|
readonly aad?: Uint8Array;
|
|
13
21
|
readonly provider?: CryptoProvider;
|
|
22
|
+
readonly unsafeAllowIvReuse?: boolean;
|
|
14
23
|
}
|
|
15
24
|
/**
|
|
16
25
|
* Authenticated encryption result.
|
|
@@ -23,6 +32,9 @@ export interface CipherResult {
|
|
|
23
32
|
}
|
|
24
33
|
/**
|
|
25
34
|
* Encrypts data using AES-256-GCM.
|
|
35
|
+
*
|
|
36
|
+
* @throws {CryptoError} `CRYPTO_CIPHER` when a supplied `iv` is not 12
|
|
37
|
+
* bytes, or was already used with this key in this process.
|
|
26
38
|
*/
|
|
27
39
|
export declare function encrypt(plaintext: Uint8Array, key: Uint8Array, options?: CipherOptions): Promise<CipherResult>;
|
|
28
40
|
/**
|
|
@@ -32,4 +44,3 @@ export declare function encrypt(plaintext: Uint8Array, key: Uint8Array, options?
|
|
|
32
44
|
* tags are rejected before the cipher is touched.
|
|
33
45
|
*/
|
|
34
46
|
export declare function decrypt(ciphertext: Uint8Array, key: Uint8Array, iv: Uint8Array, authTag: Uint8Array, aad?: Uint8Array, provider?: CryptoProvider): Promise<Uint8Array>;
|
|
35
|
-
//# sourceMappingURL=cryptoCipher.core.d.ts.map
|
|
@@ -3,8 +3,12 @@ import { assertProviderCapability } from "../cryptoProvider/cryptoProvider.capab
|
|
|
3
3
|
import { AES_GCM } from "../cryptoConstants/cryptoConstants.type.js";
|
|
4
4
|
import { CryptoOperation } from "@zudojs/errors";
|
|
5
5
|
import { cipherError } from "../cryptoErrors/cryptoErrors.helper.js";
|
|
6
|
+
import { assertIvNotReused } from "./cryptoCipher.nonceGuard.js";
|
|
6
7
|
/**
|
|
7
8
|
* Encrypts data using AES-256-GCM.
|
|
9
|
+
*
|
|
10
|
+
* @throws {CryptoError} `CRYPTO_CIPHER` when a supplied `iv` is not 12
|
|
11
|
+
* bytes, or was already used with this key in this process.
|
|
8
12
|
*/
|
|
9
13
|
export async function encrypt(plaintext, key, options = {}) {
|
|
10
14
|
if (options.iv !== undefined && options.iv.byteLength !== AES_GCM.IV_BYTES) {
|
|
@@ -12,6 +16,11 @@ export async function encrypt(plaintext, key, options = {}) {
|
|
|
12
16
|
}
|
|
13
17
|
const provider = options.provider ?? getDefaultCryptoProvider();
|
|
14
18
|
assertProviderCapability(provider, "encryption", CryptoOperation.ENCRYPT);
|
|
19
|
+
if (options.iv !== undefined &&
|
|
20
|
+
key instanceof Uint8Array &&
|
|
21
|
+
options.unsafeAllowIvReuse !== true) {
|
|
22
|
+
assertIvNotReused(key, options.iv);
|
|
23
|
+
}
|
|
15
24
|
const encrypted = await provider.encrypt({
|
|
16
25
|
key,
|
|
17
26
|
plaintext,
|
|
@@ -51,4 +60,3 @@ export async function decrypt(ciphertext, key, iv, authTag, aad, provider = getD
|
|
|
51
60
|
associatedData: aad,
|
|
52
61
|
});
|
|
53
62
|
}
|
|
54
|
-
//# sourceMappingURL=cryptoCipher.core.js.map
|
|
@@ -18,4 +18,3 @@ export declare function encryptEnvelope(plaintext: Uint8Array, key: Uint8Array,
|
|
|
18
18
|
* authentication both surface as `CryptoError` with code `ERR_CRYPTO_CIPHER`.
|
|
19
19
|
*/
|
|
20
20
|
export declare function decryptEnvelope(envelope: string, key: Uint8Array, aad?: Uint8Array, provider?: CryptoProvider): Promise<Uint8Array>;
|
|
21
|
-
//# sourceMappingURL=cryptoCipher.envelope.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upper bound on remembered (key, iv) pairs. Past it the oldest entries
|
|
3
|
+
* are forgotten first, so the guard is best-effort for very long-lived
|
|
4
|
+
* processes but exact for the reuse patterns that occur in practice
|
|
5
|
+
* (a fixed iv hard-coded next to a fixed key).
|
|
6
|
+
*/
|
|
7
|
+
export declare const IV_REUSE_GUARD_CAPACITY = 65536;
|
|
8
|
+
/**
|
|
9
|
+
* Rejects a caller-supplied AES-GCM iv that this process has already used
|
|
10
|
+
* under the same key.
|
|
11
|
+
*
|
|
12
|
+
* AES-GCM is catastrophically broken by nonce reuse: two messages encrypted
|
|
13
|
+
* under one (key, iv) pair leak the XOR of their plaintexts and allow the
|
|
14
|
+
* authentication key to be recovered. A random iv drawn per call (the
|
|
15
|
+
* default when `iv` is omitted) never trips this guard; it exists to catch
|
|
16
|
+
* the hard-coded or counter-reset iv before it reaches the cipher.
|
|
17
|
+
*
|
|
18
|
+
* The guard is per process: it cannot see ivs used by other processes or
|
|
19
|
+
* before a restart, so it is a safety net, not a substitute for a scheme
|
|
20
|
+
* that guarantees uniqueness (random ivs, or a durable counter).
|
|
21
|
+
*
|
|
22
|
+
* @throws {CryptoError} `CRYPTO_CIPHER` when the pair was already used.
|
|
23
|
+
*/
|
|
24
|
+
export declare function assertIvNotReused(key: Uint8Array, iv: Uint8Array): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { CryptoOperation } from "@zudojs/errors";
|
|
3
|
+
import { cipherError } from "../cryptoErrors/cryptoErrors.helper.js";
|
|
4
|
+
/**
|
|
5
|
+
* Upper bound on remembered (key, iv) pairs. Past it the oldest entries
|
|
6
|
+
* are forgotten first, so the guard is best-effort for very long-lived
|
|
7
|
+
* processes but exact for the reuse patterns that occur in practice
|
|
8
|
+
* (a fixed iv hard-coded next to a fixed key).
|
|
9
|
+
*/
|
|
10
|
+
export const IV_REUSE_GUARD_CAPACITY = 65_536;
|
|
11
|
+
const seen = new Set();
|
|
12
|
+
function fingerprint(key, iv) {
|
|
13
|
+
return createHash("sha256")
|
|
14
|
+
.update("zudojs-crypto-iv-reuse-guard-v1")
|
|
15
|
+
.update(Uint8Array.from([key.byteLength]))
|
|
16
|
+
.update(key)
|
|
17
|
+
.update(iv)
|
|
18
|
+
.digest("base64url");
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Rejects a caller-supplied AES-GCM iv that this process has already used
|
|
22
|
+
* under the same key.
|
|
23
|
+
*
|
|
24
|
+
* AES-GCM is catastrophically broken by nonce reuse: two messages encrypted
|
|
25
|
+
* under one (key, iv) pair leak the XOR of their plaintexts and allow the
|
|
26
|
+
* authentication key to be recovered. A random iv drawn per call (the
|
|
27
|
+
* default when `iv` is omitted) never trips this guard; it exists to catch
|
|
28
|
+
* the hard-coded or counter-reset iv before it reaches the cipher.
|
|
29
|
+
*
|
|
30
|
+
* The guard is per process: it cannot see ivs used by other processes or
|
|
31
|
+
* before a restart, so it is a safety net, not a substitute for a scheme
|
|
32
|
+
* that guarantees uniqueness (random ivs, or a durable counter).
|
|
33
|
+
*
|
|
34
|
+
* @throws {CryptoError} `CRYPTO_CIPHER` when the pair was already used.
|
|
35
|
+
*/
|
|
36
|
+
export function assertIvNotReused(key, iv) {
|
|
37
|
+
const entry = fingerprint(key, iv);
|
|
38
|
+
if (seen.has(entry)) {
|
|
39
|
+
throw cipherError("AES-256-GCM iv has already been used with this key in this process; " +
|
|
40
|
+
"reusing a GCM nonce under one key breaks confidentiality and " +
|
|
41
|
+
"authenticity. Omit `iv` to draw a fresh random one per call.", CryptoOperation.ENCRYPT, "aes-256-gcm");
|
|
42
|
+
}
|
|
43
|
+
if (seen.size >= IV_REUSE_GUARD_CAPACITY) {
|
|
44
|
+
const oldest = seen.values().next();
|
|
45
|
+
if (!oldest.done) {
|
|
46
|
+
seen.delete(oldest.value);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
seen.add(entry);
|
|
50
|
+
}
|
|
@@ -8,4 +8,3 @@ export declare function encryptString(plaintext: string, key: Uint8Array, option
|
|
|
8
8
|
* Decrypts AES-256-GCM ciphertext into a UTF-8 string.
|
|
9
9
|
*/
|
|
10
10
|
export declare function decryptString(ciphertext: Uint8Array, key: Uint8Array, iv: Uint8Array, authTag: Uint8Array, aad?: Uint8Array, provider?: CryptoProvider): Promise<string>;
|
|
11
|
-
//# sourceMappingURL=cryptoCipher.string.d.ts.map
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* Symmetric and asymmetric encryption operations.
|
|
5
5
|
*/
|
|
6
6
|
export * from "./cryptoCipher.core.js";
|
|
7
|
+
export * from "./cryptoCipher.nonceGuard.js";
|
|
7
8
|
export * from "./cryptoCipher.string.js";
|
|
8
9
|
export * from "./cryptoCipher.envelope.js";
|
|
9
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* Symmetric and asymmetric encryption operations.
|
|
5
5
|
*/
|
|
6
6
|
export * from "./cryptoCipher.core.js";
|
|
7
|
+
export * from "./cryptoCipher.nonceGuard.js";
|
|
7
8
|
export * from "./cryptoCipher.string.js";
|
|
8
9
|
export * from "./cryptoCipher.envelope.js";
|
|
9
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -34,4 +34,3 @@ export declare function isCryptoAlgorithm(value: unknown): value is CryptoAlgori
|
|
|
34
34
|
* Throws when the value is not a supported algorithm.
|
|
35
35
|
*/
|
|
36
36
|
export declare function parseCryptoAlgorithm(value: string): CryptoAlgorithm;
|
|
37
|
-
//# sourceMappingURL=cryptoConstants.guard.d.ts.map
|
|
@@ -19,6 +19,19 @@ export declare function keyDerivationError(message: string, algorithm: string |
|
|
|
19
19
|
* Builds a key error that preserves the underlying failure as `cause`.
|
|
20
20
|
*/
|
|
21
21
|
export declare function keyError(message: string, operation: CryptoOperation.KEY_GENERATION | CryptoOperation.KEY_IMPORT | CryptoOperation.KEY_EXPORT, algorithm: string | undefined, cause?: unknown): CryptoError;
|
|
22
|
+
/**
|
|
23
|
+
* Builds a password hashing error (`CRYPTO_HASH`, operation `HASH`).
|
|
24
|
+
*
|
|
25
|
+
* Pass `userFacing: true` for a rejection the end user caused and can act
|
|
26
|
+
* on, such as a password outside the length policy: the error then carries
|
|
27
|
+
* `statusCode: 400` and `expose: true` so an HTTP layer answers with the
|
|
28
|
+
* message instead of a generic 500. Parameter violations by the caller
|
|
29
|
+
* (a weak scrypt cost) keep the 500 default.
|
|
30
|
+
*/
|
|
31
|
+
export declare function passwordHashError(message: string, options?: {
|
|
32
|
+
readonly userFacing?: boolean;
|
|
33
|
+
readonly cause?: unknown;
|
|
34
|
+
}): CryptoError;
|
|
22
35
|
/**
|
|
23
36
|
* Builds a generic crypto error for an operation, preserving `cause`.
|
|
24
37
|
*/
|
|
@@ -27,4 +40,3 @@ export declare function operationError(message: string, operation: CryptoOperati
|
|
|
27
40
|
* Re-throws CryptoErrors unchanged and wraps anything else.
|
|
28
41
|
*/
|
|
29
42
|
export declare function rethrowAsCryptoError(error: unknown, wrap: (cause: unknown) => CryptoError): never;
|
|
30
|
-
//# sourceMappingURL=cryptoErrors.helper.d.ts.map
|
|
@@ -54,6 +54,24 @@ export function keyError(message, operation, algorithm, cause) {
|
|
|
54
54
|
cause,
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Builds a password hashing error (`CRYPTO_HASH`, operation `HASH`).
|
|
59
|
+
*
|
|
60
|
+
* Pass `userFacing: true` for a rejection the end user caused and can act
|
|
61
|
+
* on, such as a password outside the length policy: the error then carries
|
|
62
|
+
* `statusCode: 400` and `expose: true` so an HTTP layer answers with the
|
|
63
|
+
* message instead of a generic 500. Parameter violations by the caller
|
|
64
|
+
* (a weak scrypt cost) keep the 500 default.
|
|
65
|
+
*/
|
|
66
|
+
export function passwordHashError(message, options = {}) {
|
|
67
|
+
return new CryptoError(message, {
|
|
68
|
+
code: ErrorCode.CRYPTO_HASH,
|
|
69
|
+
operation: CryptoOperation.HASH,
|
|
70
|
+
algorithm: "scrypt",
|
|
71
|
+
cause: options.cause,
|
|
72
|
+
...(options.userFacing ? { statusCode: 400, expose: true } : {}),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
57
75
|
/**
|
|
58
76
|
* Builds a generic crypto error for an operation, preserving `cause`.
|
|
59
77
|
*/
|
|
@@ -69,4 +87,3 @@ export function rethrowAsCryptoError(error, wrap) {
|
|
|
69
87
|
}
|
|
70
88
|
throw wrap(error);
|
|
71
89
|
}
|
|
72
|
-
//# sourceMappingURL=cryptoErrors.helper.js.map
|
|
@@ -8,4 +8,3 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export { CryptoError, CryptoOperation, createCryptoError, isCryptoError, cryptoHashError, cryptoCipherError, cryptoSignatureError, cryptoKeyDerivationError, cryptoKeyError, } from "@zudojs/errors";
|
|
10
10
|
export type { CryptoErrorOptions } from "@zudojs/errors";
|
|
11
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -7,4 +7,3 @@
|
|
|
7
7
|
* error hierarchy across the framework.
|
|
8
8
|
*/
|
|
9
9
|
export { CryptoError, CryptoOperation, createCryptoError, isCryptoError, cryptoHashError, cryptoCipherError, cryptoSignatureError, cryptoKeyDerivationError, cryptoKeyError, } from "@zudojs/errors";
|
|
10
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -2,4 +2,3 @@ import type { CryptoEncoding } from "../cryptoEncoding/cryptoEncoding.core.js";
|
|
|
2
2
|
export type { CryptoEncoding };
|
|
3
3
|
export declare function factoryEncode(value: Uint8Array, encoding?: CryptoEncoding): string;
|
|
4
4
|
export declare function factoryDecode(value: string, encoding?: CryptoEncoding): Uint8Array;
|
|
5
|
-
//# sourceMappingURL=cryptoFactory.encoding.d.ts.map
|
|
@@ -3,4 +3,3 @@ import type { PasswordHashOptions, PasswordHashResult } from "../cryptoPassword/
|
|
|
3
3
|
export type { PasswordHashOptions };
|
|
4
4
|
export declare function factoryCreatePasswordHash(password: string, options?: PasswordHashOptions, provider?: CryptoProvider): Promise<PasswordHashResult>;
|
|
5
5
|
export declare function factoryVerifyPassword(password: string, encodedHash: string, provider?: CryptoProvider): Promise<boolean>;
|
|
6
|
-
//# sourceMappingURL=cryptoFactory.password.d.ts.map
|
|
@@ -8,4 +8,3 @@ export declare function factoryCreateVerificationToken(provider?: CryptoProvider
|
|
|
8
8
|
export declare function factoryCreatePasswordResetToken(provider?: CryptoProvider): Promise<string>;
|
|
9
9
|
export declare function factoryCreateCsrfToken(provider?: CryptoProvider): Promise<string>;
|
|
10
10
|
export declare function factoryCreateOtp(digits?: number, provider?: CryptoProvider): Promise<string>;
|
|
11
|
-
//# sourceMappingURL=cryptoFactory.token.d.ts.map
|
|
@@ -9,4 +9,3 @@ export declare function encodeDigest(digest: Uint8Array, encoding: HashEncoding)
|
|
|
9
9
|
* Input must be a non-empty, canonical encoding.
|
|
10
10
|
*/
|
|
11
11
|
export declare function decodeDigest(digest: string, encoding?: HashEncoding): Uint8Array;
|
|
12
|
-
//# sourceMappingURL=cryptoHash.codec.d.ts.map
|
|
@@ -23,4 +23,3 @@ export declare function sha3_384(input: HashInput, encoding?: HashEncoding): Pro
|
|
|
23
23
|
* Calculates a SHA3-512 digest.
|
|
24
24
|
*/
|
|
25
25
|
export declare function sha3_512(input: HashInput, encoding?: HashEncoding): Promise<string>;
|
|
26
|
-
//# sourceMappingURL=cryptoHash.convenience.d.ts.map
|