@brashkie/signalis-core 0.1.0 → 0.3.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/CHANGELOG.md +181 -0
- package/MIGRATION.md +256 -0
- package/NOTICE +107 -9
- package/README.es.md +332 -21
- package/README.md +345 -24
- package/SECURITY.md +191 -0
- package/dist/index.cjs +320 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +270 -3
- package/dist/index.d.ts +270 -3
- package/dist/index.mjs +302 -6
- package/dist/index.mjs.map +1 -1
- package/index.d.ts +35 -0
- package/index.js +19 -1
- package/package.json +41 -25
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core.ts","../src/constants.ts","../src/errors.ts","../src/validators.ts","../src/types.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["/**\n * Core cryptographic wrappers for signalis-core.\n *\n * Provides robust, validated, and well-documented APIs over the native Rust\n * crypto primitives.\n *\n * @packageDocumentation\n */\n\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nimport * as native from '../index.js';\n\nimport {\n CURVE25519_PRIVATE_KEY_SIZE,\n CURVE25519_PUBLIC_KEY_SIZE,\n CURVE25519_SHARED_SECRET_SIZE,\n HKDF_PRK_SIZE,\n AES_256_KEY_SIZE,\n AES_256_GCM_NONCE_SIZE,\n AES_256_GCM_TAG_SIZE,\n AES_256_CBC_IV_SIZE,\n HMAC_SHA256_TAG_SIZE,\n SHA256_OUTPUT_SIZE,\n} from './constants';\n\nimport {\n CryptoError,\n AuthenticationError,\n} from './errors';\n\nimport {\n assertBufferOfSize,\n assertBuffer,\n assertHkdfLength,\n} from './validators';\n\nimport type {\n KeyPair,\n HkdfParams,\n} from './types';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Curve25519 / X25519\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Curve25519 / X25519 elliptic curve operations.\n *\n * Provides:\n * - Keypair generation\n * - Public key derivation\n * - ECDH key agreement\n *\n * @example\n * ```ts\n * import { Curve25519 } from '@brashkie/signalis-core';\n *\n * const alice = Curve25519.generateKeyPair();\n * const bob = Curve25519.generateKeyPair();\n *\n * const shared = Curve25519.diffieHellman(alice.privateKey, bob.publicKey);\n * // ⚠️ Always derive via HKDF before use as a key!\n * ```\n */\nexport const Curve25519 = Object.freeze({\n /**\n * Generate a new random Curve25519 keypair.\n *\n * Uses the OS's cryptographically secure RNG (via Rust's `OsRng`).\n *\n * @returns A {@link KeyPair} with private and public keys (32 bytes each)\n */\n generateKeyPair(): KeyPair {\n const kp = native.curve25519GenerateKeypair() as {\n private: Buffer;\n public: Buffer;\n };\n return Object.freeze({\n privateKey: kp.private,\n publicKey: kp.public,\n });\n },\n\n /**\n * Derive the public key corresponding to a given private key.\n *\n * @param privateKey - 32-byte private key\n * @returns The corresponding 32-byte public key\n * @throws {ValidationError} If `privateKey` is not a 32-byte Buffer.\n */\n publicFromPrivate(privateKey: Buffer): Buffer {\n assertBufferOfSize(privateKey, CURVE25519_PRIVATE_KEY_SIZE, 'privateKey');\n // X25519 base scalar mult cannot fail with a 32-byte (clamped) scalar\n return native.curve25519PublicFromPrivate(privateKey) as Buffer;\n },\n\n /**\n * Perform X25519 Diffie-Hellman key agreement.\n *\n * Both parties run this with swapped (private, peer-public) arguments\n * and obtain the same 32-byte shared secret.\n *\n * **⚠️ CRITICAL:** Do NOT use the returned secret directly as an\n * encryption key. Always derive an actual key through HKDF:\n *\n * @example\n * ```ts\n * const shared = Curve25519.diffieHellman(myPriv, theirPub);\n * const key = HKDF.derive(salt, shared, Buffer.from('aes-key'), 32);\n * ```\n *\n * @param privateKey - Your 32-byte private key\n * @param peerPublicKey - Peer's 32-byte public key\n * @returns 32-byte shared secret\n * @throws {ValidationError} If keys are not 32 bytes.\n * @throws {CryptoError} If the operation fails.\n */\n diffieHellman(privateKey: Buffer, peerPublicKey: Buffer): Buffer {\n assertBufferOfSize(privateKey, CURVE25519_PRIVATE_KEY_SIZE, 'privateKey');\n assertBufferOfSize(peerPublicKey, CURVE25519_PUBLIC_KEY_SIZE, 'peerPublicKey');\n // X25519 ECDH cannot fail with valid 32-byte inputs\n return native.curve25519DiffieHellman(privateKey, peerPublicKey) as Buffer;\n },\n\n /**\n * The size of a Curve25519 private key in bytes (32).\n */\n PRIVATE_KEY_SIZE: CURVE25519_PRIVATE_KEY_SIZE,\n\n /**\n * The size of a Curve25519 public key in bytes (32).\n */\n PUBLIC_KEY_SIZE: CURVE25519_PUBLIC_KEY_SIZE,\n\n /**\n * The size of an X25519 shared secret in bytes (32).\n */\n SHARED_SECRET_SIZE: CURVE25519_SHARED_SECRET_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// HKDF-SHA256\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * HKDF-SHA256 (RFC 5869) — HMAC-based Key Derivation Function.\n *\n * Provides cryptographic key derivation from high-entropy inputs (e.g., ECDH\n * shared secrets) into arbitrary-length output keying material (OKM).\n *\n * @example\n * ```ts\n * // One-shot (recommended)\n * const key = HKDF.derive(salt, sharedSecret, Buffer.from('aes-key'), 32);\n *\n * // Two-step (advanced)\n * const prk = HKDF.extract(salt, ikm);\n * const okm = HKDF.expand(prk, info, 64);\n * ```\n */\nexport const HKDF = Object.freeze({\n /**\n * HKDF-Extract: produces a 32-byte pseudorandom key (PRK).\n *\n * @param salt - Optional salt (pass `Buffer.alloc(0)` if not available)\n * @param ikm - Input keying material\n * @returns 32-byte PRK\n * @throws {ValidationError} If inputs are not Buffers.\n */\n extract(salt: Buffer, ikm: Buffer): Buffer {\n assertBuffer(salt, 'salt');\n assertBuffer(ikm, 'ikm');\n return native.hkdfExtract(salt, ikm) as Buffer;\n },\n\n /**\n * HKDF-Expand: produces `length` bytes of output keying material.\n *\n * @param prk - 32-byte pseudorandom key from {@link extract}\n * @param info - Context-specific information (binds output to a usage)\n * @param length - Desired output length (1 to 8160 bytes)\n * @returns OKM of requested length\n * @throws {ValidationError} If PRK is not 32 bytes or length is out of bounds.\n */\n expand(prk: Buffer, info: Buffer, length: number): Buffer {\n assertBufferOfSize(prk, HKDF_PRK_SIZE, 'prk');\n assertBuffer(info, 'info');\n assertHkdfLength(length);\n // Length already validated; native cannot fail with valid PRK + length <= 8160\n return native.hkdfExpand(prk, info, length) as Buffer;\n },\n\n /**\n * HKDF one-shot: extract + expand in a single call.\n *\n * Use this whenever possible — it's the standard HKDF API.\n *\n * @param salt - Optional salt\n * @param ikm - Input keying material\n * @param info - Context info\n * @param length - Desired output length\n * @returns OKM of requested length\n */\n derive(salt: Buffer, ikm: Buffer, info: Buffer, length: number): Buffer {\n assertBuffer(salt, 'salt');\n assertBuffer(ikm, 'ikm');\n assertBuffer(info, 'info');\n assertHkdfLength(length);\n // Length already validated; native cannot fail with valid inputs\n return native.hkdfDerive(salt, ikm, info, length) as Buffer;\n },\n\n /**\n * Derive multiple keys from the same shared secret in a single call.\n *\n * Useful for deriving e.g., a send key AND a receive key simultaneously.\n *\n * @example\n * ```ts\n * const [sendKey, recvKey] = HKDF.deriveMultiple(\n * salt,\n * sharedSecret,\n * Buffer.from('signalis-channel-v1'),\n * [32, 32],\n * );\n * ```\n *\n * @param salt - Optional salt\n * @param ikm - Input keying material\n * @param info - Context info\n * @param lengths - Array of output lengths\n * @returns Array of derived keys, one per requested length\n */\n deriveMultiple(\n salt: Buffer,\n ikm: Buffer,\n info: Buffer,\n lengths: number[],\n ): Buffer[] {\n assertBuffer(salt, 'salt');\n assertBuffer(ikm, 'ikm');\n assertBuffer(info, 'info');\n if (!Array.isArray(lengths) || lengths.length === 0) {\n throw new TypeError('lengths must be a non-empty array of integers');\n }\n\n const total = lengths.reduce((sum, len) => sum + len, 0);\n assertHkdfLength(total);\n\n const okm = this.derive(salt, ikm, info, total);\n const results: Buffer[] = [];\n let offset = 0;\n for (const len of lengths) {\n results.push(okm.subarray(offset, offset + len));\n offset += len;\n }\n return results;\n },\n\n /**\n * Derive a key using an {@link HkdfParams} object (alternative API).\n */\n deriveFromParams(params: HkdfParams): Buffer {\n return this.derive(params.salt, params.ikm, params.info, params.length);\n },\n\n /**\n * The size of an HKDF PRK in bytes (32).\n */\n PRK_SIZE: HKDF_PRK_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// AES-256-GCM (Authenticated Encryption)\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * AES-256-GCM authenticated encryption (AEAD).\n *\n * Combines confidentiality + authenticity in a single primitive.\n *\n * **⚠️ CRITICAL SECURITY RULES:**\n * 1. Never reuse a (key, nonce) pair. Catastrophic failure.\n * 2. Generate nonces with `secureRandom(12)` for each message.\n * 3. After 2^32 messages with random nonces, rotate the key.\n *\n * @example\n * ```ts\n * import { AES_GCM, secureRandom } from '@brashkie/signalis-core';\n *\n * const key = secureRandom(32);\n * const nonce = secureRandom(12);\n * const plaintext = Buffer.from('Hello!');\n *\n * const ciphertext = AES_GCM.encrypt(key, nonce, plaintext);\n * const decrypted = AES_GCM.decrypt(key, nonce, ciphertext);\n * ```\n */\nexport const AES_GCM = Object.freeze({\n /**\n * Encrypt plaintext.\n *\n * Returns: ciphertext || 16-byte authentication tag (concatenated).\n *\n * @param key - 32-byte symmetric key\n * @param nonce - 12-byte unique nonce (NEVER reuse with same key)\n * @param plaintext - Data to encrypt\n * @returns Ciphertext + auth tag (output is `plaintext.length + 16` bytes)\n * @throws {ValidationError} On invalid sizes.\n * @throws {CryptoError} If the operation fails.\n */\n encrypt(key: Buffer, nonce: Buffer, plaintext: Buffer): Buffer {\n assertBufferOfSize(key, AES_256_KEY_SIZE, 'key');\n assertBufferOfSize(nonce, AES_256_GCM_NONCE_SIZE, 'nonce');\n assertBuffer(plaintext, 'plaintext');\n // GCM encryption cannot fail with valid-sized inputs\n return native.aes256GcmEncrypt(key, nonce, plaintext) as Buffer;\n },\n\n /**\n * Decrypt ciphertext and verify authentication tag.\n *\n * @param key - 32-byte symmetric key (same as encryption)\n * @param nonce - 12-byte nonce (same as encryption)\n * @param ciphertext - Ciphertext || auth tag\n * @returns Original plaintext\n * @throws {ValidationError} On invalid sizes.\n * @throws {AuthenticationError} If the tag is invalid (tampered or wrong key).\n */\n decrypt(key: Buffer, nonce: Buffer, ciphertext: Buffer): Buffer {\n assertBufferOfSize(key, AES_256_KEY_SIZE, 'key');\n assertBufferOfSize(nonce, AES_256_GCM_NONCE_SIZE, 'nonce');\n assertBuffer(ciphertext, 'ciphertext');\n\n if (ciphertext.length < AES_256_GCM_TAG_SIZE) {\n throw new CryptoError(\n `Ciphertext too short: must be at least ${AES_256_GCM_TAG_SIZE} bytes (tag size)`,\n 'aes_gcm_decrypt',\n );\n }\n\n try {\n return native.aes256GcmDecrypt(key, nonce, ciphertext) as Buffer;\n } catch (e) {\n throw new AuthenticationError(\n `AES-256-GCM authentication failed: ${(e as Error).message}`,\n );\n }\n },\n\n /** Key size in bytes (32). */\n KEY_SIZE: AES_256_KEY_SIZE,\n /** Nonce size in bytes (12). */\n NONCE_SIZE: AES_256_GCM_NONCE_SIZE,\n /** Tag size in bytes (16). */\n TAG_SIZE: AES_256_GCM_TAG_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// AES-256-CBC (Encryption only — pair with HMAC!)\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * AES-256-CBC block cipher (NOT authenticated by itself).\n *\n * **⚠️ MUST be paired with HMAC** for integrity protection (encrypt-then-MAC).\n *\n * Prefer {@link AES_GCM} unless you need:\n * - Legacy Signal Protocol media compatibility\n * - Hardware that lacks GCM acceleration\n */\nexport const AES_CBC = Object.freeze({\n /**\n * Encrypt with PKCS#7 padding.\n *\n * @param key - 32-byte symmetric key\n * @param iv - 16-byte initialization vector\n * @param plaintext - Data to encrypt\n * @returns Ciphertext (padded to nearest 16-byte block)\n */\n encrypt(key: Buffer, iv: Buffer, plaintext: Buffer): Buffer {\n assertBufferOfSize(key, AES_256_KEY_SIZE, 'key');\n assertBufferOfSize(iv, AES_256_CBC_IV_SIZE, 'iv');\n assertBuffer(plaintext, 'plaintext');\n // CBC encryption with PKCS#7 padding cannot fail given valid-sized inputs\n return native.aes256CbcEncrypt(key, iv, plaintext) as Buffer;\n },\n\n /**\n * Decrypt with PKCS#7 padding (no authentication).\n *\n * @param key - 32-byte symmetric key\n * @param iv - 16-byte IV (same as encryption)\n * @param ciphertext - Ciphertext\n * @returns Original plaintext\n * @throws {CryptoError} On padding errors.\n */\n decrypt(key: Buffer, iv: Buffer, ciphertext: Buffer): Buffer {\n assertBufferOfSize(key, AES_256_KEY_SIZE, 'key');\n assertBufferOfSize(iv, AES_256_CBC_IV_SIZE, 'iv');\n assertBuffer(ciphertext, 'ciphertext');\n try {\n return native.aes256CbcDecrypt(key, iv, ciphertext) as Buffer;\n } catch (e) {\n throw new CryptoError(\n `AES-256-CBC decryption failed: ${(e as Error).message}`,\n 'aes_cbc_decrypt',\n );\n }\n },\n\n /** Key size in bytes (32). */\n KEY_SIZE: AES_256_KEY_SIZE,\n /** IV size in bytes (16). */\n IV_SIZE: AES_256_CBC_IV_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// HMAC-SHA256\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * HMAC-SHA256 message authentication code.\n *\n * Provides cryptographic authentication of arbitrary data with a shared key.\n *\n * @example\n * ```ts\n * const tag = HMAC.sha256(key, message);\n * const valid = HMAC.verifySha256(key, message, tag); // constant-time\n * ```\n */\nexport const HMAC = Object.freeze({\n /**\n * Compute HMAC-SHA256 of `data` using `key`.\n *\n * @param key - Authentication key (any length)\n * @param data - Data to authenticate\n * @returns 32-byte HMAC tag\n */\n sha256(key: Buffer, data: Buffer): Buffer {\n assertBuffer(key, 'key');\n assertBuffer(data, 'data');\n return native.hmacSha256(key, data) as Buffer;\n },\n\n /**\n * Verify an HMAC-SHA256 tag in **constant time**.\n *\n * Always use this instead of `===` to prevent timing attacks.\n *\n * @param key - Authentication key\n * @param data - Original data\n * @param expectedTag - Tag to verify\n * @returns `true` if tag matches, `false` otherwise\n */\n verifySha256(key: Buffer, data: Buffer, expectedTag: Buffer): boolean {\n assertBuffer(key, 'key');\n assertBuffer(data, 'data');\n assertBuffer(expectedTag, 'expectedTag');\n return native.hmacSha256Verify(key, data, expectedTag) as boolean;\n },\n\n /** Tag size in bytes (32). */\n TAG_SIZE: HMAC_SHA256_TAG_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// SHA-256\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * SHA-256 cryptographic hash function.\n *\n * @example\n * ```ts\n * const digest = SHA256.hash(Buffer.from('hello'));\n * ```\n */\nexport const SHA256 = Object.freeze({\n /**\n * Compute SHA-256 hash of `data`.\n *\n * @param data - Data to hash\n * @returns 32-byte digest\n */\n hash(data: Buffer): Buffer {\n assertBuffer(data, 'data');\n return native.sha256(data) as Buffer;\n },\n\n /**\n * Hash multiple Buffers concatenated together.\n *\n * Equivalent to `SHA256.hash(Buffer.concat([...]))` but slightly more\n * efficient (avoids the intermediate concat).\n */\n hashAll(buffers: Buffer[]): Buffer {\n if (!Array.isArray(buffers)) {\n throw new TypeError('buffers must be an array');\n }\n for (let i = 0; i < buffers.length; i++) {\n assertBuffer(buffers[i]!, `buffers[${i}]`);\n }\n return this.hash(Buffer.concat(buffers));\n },\n\n /** Output size in bytes (32). */\n OUTPUT_SIZE: SHA256_OUTPUT_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Library version\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * The version of the underlying Rust crate (from `Cargo.toml`).\n */\nexport const nativeVersion: string = (native.version as () => string)();\n","/**\n * Public constants used throughout signalis-core.\n *\n * @packageDocumentation\n */\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Curve25519 / X25519\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** Size of a Curve25519 private key in bytes. */\nexport const CURVE25519_PRIVATE_KEY_SIZE = 32;\n\n/** Size of a Curve25519 public key in bytes. */\nexport const CURVE25519_PUBLIC_KEY_SIZE = 32;\n\n/** Size of an X25519 ECDH shared secret in bytes. */\nexport const CURVE25519_SHARED_SECRET_SIZE = 32;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// HKDF-SHA256\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** Size of HKDF-SHA256 PRK (pseudorandom key) in bytes. */\nexport const HKDF_PRK_SIZE = 32;\n\n/** Maximum HKDF-SHA256 output length: 255 * HashLen = 255 * 32 = 8160 bytes. */\nexport const HKDF_MAX_OUTPUT_SIZE = 8160;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// AES-256\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** Size of an AES-256 key in bytes. */\nexport const AES_256_KEY_SIZE = 32;\n\n/** Size of an AES-256-GCM nonce in bytes (recommended size per NIST SP 800-38D). */\nexport const AES_256_GCM_NONCE_SIZE = 12;\n\n/** Size of an AES-256-GCM authentication tag in bytes. */\nexport const AES_256_GCM_TAG_SIZE = 16;\n\n/** Size of an AES-256-CBC IV in bytes (one AES block). */\nexport const AES_256_CBC_IV_SIZE = 16;\n\n/** AES block size in bytes. */\nexport const AES_BLOCK_SIZE = 16;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// SHA-256 / HMAC\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** Size of a SHA-256 hash output in bytes. */\nexport const SHA256_OUTPUT_SIZE = 32;\n\n/** Size of an HMAC-SHA256 tag in bytes. */\nexport const HMAC_SHA256_TAG_SIZE = 32;\n\n/** SHA-256 block size (used internally by HMAC). */\nexport const SHA256_BLOCK_SIZE = 64;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Limits & Recommendations\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Maximum recommended plaintext size for AES-GCM (~64 GiB).\n *\n * AES-GCM has a hard limit of 2^39 - 256 bits ≈ 64 GiB per single encryption\n * under the same key+nonce. We recommend much smaller messages and key rotation.\n */\nexport const AES_GCM_MAX_PLAINTEXT_SIZE = 64 * 1024 * 1024 * 1024;\n\n/**\n * Recommended maximum number of messages encrypted under the same AES-GCM key\n * with random 96-bit nonces before key rotation: 2^32.\n */\nexport const AES_GCM_RECOMMENDED_MESSAGES_PER_KEY = 4294967296;\n","/**\n * Typed error classes for signalis-core.\n *\n * All errors extend the base `SignalisError` class for easy `instanceof` checks.\n *\n * @packageDocumentation\n */\n\n/**\n * Base error class for all signalis-core errors.\n *\n * @example\n * ```ts\n * try {\n * Curve25519.diffieHellman(invalidKey, peer);\n * } catch (e) {\n * if (e instanceof SignalisError) {\n * console.error('Crypto error:', e.code, e.message);\n * }\n * }\n * ```\n */\nexport class SignalisError extends Error {\n /** Error code for programmatic handling. */\n public readonly code: string;\n\n constructor(message: string, code: string) {\n super(message);\n this.name = 'SignalisError';\n this.code = code;\n // Maintain proper stack trace\n if (typeof Error.captureStackTrace === 'function') {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Thrown when input validation fails (wrong size, wrong type, etc.).\n */\nexport class ValidationError extends SignalisError {\n /** Name of the parameter that failed validation. */\n public readonly parameter?: string;\n\n /** Expected value description. */\n public readonly expected?: string;\n\n /** Actual value received. */\n public readonly actual?: string | number;\n\n constructor(\n message: string,\n options: {\n parameter?: string;\n expected?: string;\n actual?: string | number;\n } = {},\n ) {\n super(message, 'VALIDATION_ERROR');\n this.name = 'ValidationError';\n this.parameter = options.parameter;\n this.expected = options.expected;\n this.actual = options.actual;\n }\n}\n\n/**\n * Thrown when a crypto operation fails (decryption, MAC verification, etc.).\n */\nexport class CryptoError extends SignalisError {\n /** The crypto operation that failed. */\n public readonly operation: string;\n\n constructor(message: string, operation: string) {\n super(message, 'CRYPTO_ERROR');\n this.name = 'CryptoError';\n this.operation = operation;\n }\n}\n\n/**\n * Thrown when AEAD authentication fails (e.g., AES-GCM tag mismatch).\n *\n * This is a security-critical error: the ciphertext was tampered with\n * or the wrong key was used.\n */\nexport class AuthenticationError extends CryptoError {\n constructor(message = 'Authentication tag verification failed') {\n super(message, 'authenticate');\n this.name = 'AuthenticationError';\n }\n}\n\n/**\n * Thrown when a key derivation or key agreement operation fails.\n */\nexport class KeyDerivationError extends CryptoError {\n constructor(message: string) {\n super(message, 'derive_key');\n this.name = 'KeyDerivationError';\n }\n}\n\n/**\n * Thrown when the requested output length is invalid (e.g., HKDF > 8160 bytes).\n */\nexport class LengthError extends ValidationError {\n constructor(message: string, options: { expected?: string; actual?: number } = {}) {\n super(message, options);\n this.name = 'LengthError';\n }\n}\n","/**\n * Input validators for signalis-core.\n *\n * All validators throw `ValidationError` with detailed information.\n *\n * @packageDocumentation\n */\n\nimport { ValidationError, LengthError } from './errors';\nimport {\n HKDF_MAX_OUTPUT_SIZE,\n} from './constants';\n\n/**\n * Assert that a value is a `Buffer`.\n *\n * @throws {ValidationError} If `value` is not a Buffer.\n */\nexport function assertBuffer(value: unknown, parameter: string): asserts value is Buffer {\n if (!Buffer.isBuffer(value)) {\n throw new ValidationError(`${parameter} must be a Buffer`, {\n parameter,\n expected: 'Buffer',\n actual: typeof value,\n });\n }\n}\n\n/**\n * Assert that a Buffer has exactly the expected length.\n *\n * @throws {ValidationError} If length mismatch.\n */\nexport function assertBufferLength(\n value: Buffer,\n expectedLength: number,\n parameter: string,\n): void {\n if (value.length !== expectedLength) {\n throw new ValidationError(\n `${parameter} must be ${expectedLength} bytes, got ${value.length}`,\n {\n parameter,\n expected: `${expectedLength} bytes`,\n actual: value.length,\n },\n );\n }\n}\n\n/**\n * Combined check: must be a Buffer of exactly N bytes.\n */\nexport function assertBufferOfSize(\n value: unknown,\n expectedLength: number,\n parameter: string,\n): asserts value is Buffer {\n assertBuffer(value, parameter);\n assertBufferLength(value, expectedLength, parameter);\n}\n\n/**\n * Assert that a number is a positive integer.\n */\nexport function assertPositiveInteger(value: unknown, parameter: string): asserts value is number {\n if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {\n throw new ValidationError(`${parameter} must be a non-negative integer`, {\n parameter,\n expected: 'non-negative integer',\n actual: String(value),\n });\n }\n}\n\n/**\n * Assert HKDF output length is within bounds.\n */\nexport function assertHkdfLength(length: unknown): asserts length is number {\n assertPositiveInteger(length, 'length');\n if ((length as number) > HKDF_MAX_OUTPUT_SIZE) {\n throw new LengthError(\n `HKDF output length cannot exceed ${HKDF_MAX_OUTPUT_SIZE} bytes (255 * 32)`,\n {\n expected: `<= ${HKDF_MAX_OUTPUT_SIZE}`,\n actual: length as number,\n },\n );\n }\n if ((length as number) === 0) {\n throw new LengthError('HKDF output length must be greater than 0', {\n expected: '> 0',\n actual: 0,\n });\n }\n}\n\n/**\n * Check if two Buffers have the same length (utility for tests).\n */\nexport function buffersSameLength(a: Buffer, b: Buffer): boolean {\n return a.length === b.length;\n}\n","/**\n * Shared TypeScript types for signalis-core.\n *\n * @packageDocumentation\n */\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Curve25519\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * A Curve25519 keypair (private + public key).\n *\n * Both keys are 32-byte Buffers.\n */\nexport interface KeyPair {\n /**\n * Private key (32 bytes).\n *\n * **⚠️ KEEP THIS SECRET.** Never log, transmit, or store in plaintext.\n */\n readonly privateKey: Buffer;\n\n /**\n * Public key (32 bytes).\n *\n * Safe to share publicly.\n */\n readonly publicKey: Buffer;\n}\n\n/**\n * A Curve25519 public key — type-tag for stronger typing.\n *\n * Use {@link asPublicKey} to brand a Buffer.\n */\nexport type PublicKey = Buffer & { readonly __brand?: 'PublicKey' };\n\n/**\n * A Curve25519 private key — type-tag for stronger typing.\n *\n * Use {@link asPrivateKey} to brand a Buffer.\n */\nexport type PrivateKey = Buffer & { readonly __brand?: 'PrivateKey' };\n\n/**\n * An X25519 ECDH shared secret (32 bytes).\n *\n * **⚠️ DO NOT USE DIRECTLY AS A KEY.** Always derive through HKDF.\n */\nexport type SharedSecret = Buffer & { readonly __brand?: 'SharedSecret' };\n\n// ═══════════════════════════════════════════════════════════════════════════\n// HKDF\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * HKDF pseudorandom key (32 bytes), output of the Extract step.\n */\nexport type PseudoRandomKey = Buffer & { readonly __brand?: 'PRK' };\n\n/**\n * HKDF parameters object — useful for organizing key derivation calls.\n */\nexport interface HkdfParams {\n /** Optional salt (use `Buffer.alloc(0)` if absent). */\n salt: Buffer;\n /** Input keying material (e.g., ECDH shared secret). */\n ikm: Buffer;\n /** Context-specific information (binds the output to a usage). */\n info: Buffer;\n /** Desired output length in bytes (1 to 8160). */\n length: number;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// AES\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * AES-256-GCM parameters.\n */\nexport interface AesGcmParams {\n /** 32-byte symmetric key. */\n key: Buffer;\n /** 12-byte nonce (MUST be unique per message). */\n nonce: Buffer;\n /** Plaintext or ciphertext. */\n data: Buffer;\n}\n\n/**\n * AES-256-CBC parameters.\n */\nexport interface AesCbcParams {\n /** 32-byte symmetric key. */\n key: Buffer;\n /** 16-byte initialization vector. */\n iv: Buffer;\n /** Plaintext or ciphertext. */\n data: Buffer;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Encoding\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Supported encodings for converting Buffers to/from strings.\n */\nexport type Encoding = 'hex' | 'base64' | 'base64url' | 'utf8' | 'binary';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Branding helpers (zero-cost casts with documentation)\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Brand a Buffer as a {@link PublicKey}.\n *\n * Does NOT validate length — use validators separately.\n */\nexport function asPublicKey(buf: Buffer): PublicKey {\n return buf as PublicKey;\n}\n\n/**\n * Brand a Buffer as a {@link PrivateKey}.\n *\n * Does NOT validate length — use validators separately.\n */\nexport function asPrivateKey(buf: Buffer): PrivateKey {\n return buf as PrivateKey;\n}\n\n/**\n * Brand a Buffer as a {@link SharedSecret}.\n */\nexport function asSharedSecret(buf: Buffer): SharedSecret {\n return buf as SharedSecret;\n}\n","/**\n * Utility functions for signalis-core.\n *\n * Encoding helpers, secure random generation, and constant-time comparisons.\n *\n * @packageDocumentation\n */\n\nimport { randomBytes, timingSafeEqual } from 'node:crypto';\nimport type { Encoding } from './types';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Secure Random\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Generate cryptographically secure random bytes.\n *\n * Uses Node's `crypto.randomBytes` which delegates to the OS CSPRNG:\n * - Linux/macOS: `getrandom()` / `/dev/urandom`\n * - Windows: `BCryptGenRandom`\n *\n * @param length - Number of bytes to generate\n * @returns A Buffer of `length` random bytes\n *\n * @example\n * ```ts\n * const nonce = secureRandom(12); // 12-byte nonce for AES-GCM\n * const key = secureRandom(32); // 32-byte AES key\n * ```\n */\nexport function secureRandom(length: number): Buffer {\n if (!Number.isInteger(length) || length < 0) {\n throw new RangeError(`length must be a non-negative integer, got ${length}`);\n }\n return randomBytes(length);\n}\n\n/**\n * Generate a cryptographically secure random 12-byte nonce (for AES-GCM).\n */\nexport function randomNonce(): Buffer {\n return randomBytes(12);\n}\n\n/**\n * Generate a cryptographically secure random 16-byte IV (for AES-CBC).\n */\nexport function randomIv(): Buffer {\n return randomBytes(16);\n}\n\n/**\n * Generate a cryptographically secure random 32-byte key.\n */\nexport function randomKey(): Buffer {\n return randomBytes(32);\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Encoding helpers\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Convert a Buffer to its hexadecimal string representation.\n *\n * @example\n * ```ts\n * toHex(Buffer.from([0xff, 0x00])); // \"ff00\"\n * ```\n */\nexport function toHex(buf: Buffer): string {\n return buf.toString('hex');\n}\n\n/**\n * Parse a hexadecimal string into a Buffer.\n *\n * @throws {Error} If `hex` contains non-hex characters or has odd length.\n */\nexport function fromHex(hex: string): Buffer {\n if (!/^[0-9a-fA-F]*$/.test(hex)) {\n throw new Error('Invalid hex string: contains non-hex characters');\n }\n if (hex.length % 2 !== 0) {\n throw new Error('Invalid hex string: odd number of characters');\n }\n return Buffer.from(hex, 'hex');\n}\n\n/**\n * Convert a Buffer to a standard base64 string.\n */\nexport function toBase64(buf: Buffer): string {\n return buf.toString('base64');\n}\n\n/**\n * Parse a base64 string into a Buffer.\n */\nexport function fromBase64(b64: string): Buffer {\n return Buffer.from(b64, 'base64');\n}\n\n/**\n * Convert a Buffer to a URL-safe base64 string (no padding).\n *\n * Useful for URLs, query strings, JWT headers, etc.\n */\nexport function toBase64Url(buf: Buffer): string {\n return buf.toString('base64url');\n}\n\n/**\n * Parse a base64url string into a Buffer.\n */\nexport function fromBase64Url(b64url: string): Buffer {\n return Buffer.from(b64url, 'base64url');\n}\n\n/**\n * Convert a Buffer to a string using the specified encoding.\n */\nexport function bufferToString(buf: Buffer, encoding: Encoding = 'hex'): string {\n return buf.toString(encoding);\n}\n\n/**\n * Parse a string into a Buffer using the specified encoding.\n */\nexport function stringToBuffer(str: string, encoding: Encoding = 'hex'): Buffer {\n return Buffer.from(str, encoding);\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Constant-time comparison\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Compare two Buffers in constant time (resistant to timing attacks).\n *\n * **Always** use this instead of `===` or `Buffer.equals` when comparing\n * MACs, signatures, or any other security-sensitive bytes.\n *\n * Returns `false` if lengths differ (without revealing the difference).\n *\n * @example\n * ```ts\n * const valid = constantTimeEqual(receivedTag, expectedTag);\n * if (!valid) throw new Error('MAC verification failed');\n * ```\n */\nexport function constantTimeEqual(a: Buffer, b: Buffer): boolean {\n if (a.length !== b.length) {\n // Compare against itself to keep some constant work\n timingSafeEqual(a, a);\n return false;\n }\n return timingSafeEqual(a, b);\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Buffer manipulation\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Concatenate multiple Buffers into one.\n *\n * Thin wrapper over `Buffer.concat` with cleaner naming.\n */\nexport function concat(buffers: Buffer[]): Buffer {\n return Buffer.concat(buffers);\n}\n\n/**\n * Zero out a Buffer in-place.\n *\n * Useful for clearing sensitive data after use.\n *\n * **Note:** JavaScript runtimes may keep copies in GC buffers, so this is\n * NOT a guaranteed wipe. For real security, use Rust-side zeroization.\n */\nexport function zeroize(buf: Buffer): void {\n buf.fill(0);\n}\n\n/**\n * XOR two equal-length Buffers and return the result.\n *\n * @throws {Error} If buffers have different lengths.\n */\nexport function xor(a: Buffer, b: Buffer): Buffer {\n if (a.length !== b.length) {\n throw new Error(`XOR operands must have equal length: ${a.length} vs ${b.length}`);\n }\n const result = Buffer.alloc(a.length);\n for (let i = 0; i < a.length; i++) {\n result[i] = a[i]! ^ b[i]!;\n }\n return result;\n}\n","/**\n * # @brashkie/signalis-core\n *\n * **Cryptographic primitives for the Signal Protocol — Rust-powered.**\n *\n * High-performance, audited crypto for Node.js with full TypeScript support.\n * Works seamlessly in both CommonJS and ESM environments.\n *\n * ## Quick start\n *\n * ```typescript\n * import { Curve25519, HKDF, AES_GCM, secureRandom } from '@brashkie/signalis-core';\n *\n * // 1. Generate keypairs\n * const alice = Curve25519.generateKeyPair();\n * const bob = Curve25519.generateKeyPair();\n *\n * // 2. ECDH key agreement\n * const shared = Curve25519.diffieHellman(alice.privateKey, bob.publicKey);\n *\n * // 3. Derive a session key via HKDF\n * const key = HKDF.derive(\n * Buffer.from('app-salt'),\n * shared,\n * Buffer.from('encryption'),\n * 32,\n * );\n *\n * // 4. Encrypt with AES-256-GCM\n * const nonce = secureRandom(12);\n * const ciphertext = AES_GCM.encrypt(key, nonce, Buffer.from('Secret!'));\n *\n * // 5. Decrypt\n * const plaintext = AES_GCM.decrypt(key, nonce, ciphertext);\n * ```\n *\n * ## Security\n *\n * - All primitives use audited Rust crates from RustCrypto / curve25519-dalek\n * - Constant-time operations where applicable\n * - Automatic zeroization of secrets on the Rust side\n * - Test vectors from RFC 5869, RFC 7748, RFC 4231, NIST\n *\n * @packageDocumentation\n */\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Core crypto primitives\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport {\n Curve25519,\n HKDF,\n AES_GCM,\n AES_CBC,\n HMAC,\n SHA256,\n nativeVersion,\n} from './core';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Types\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport type {\n KeyPair,\n PublicKey,\n PrivateKey,\n SharedSecret,\n PseudoRandomKey,\n HkdfParams,\n AesGcmParams,\n AesCbcParams,\n Encoding,\n} from './types';\n\nexport {\n asPublicKey,\n asPrivateKey,\n asSharedSecret,\n} from './types';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Errors\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport {\n SignalisError,\n ValidationError,\n CryptoError,\n AuthenticationError,\n KeyDerivationError,\n LengthError,\n} from './errors';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Utilities\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport {\n // Secure random\n secureRandom,\n randomNonce,\n randomIv,\n randomKey,\n // Encoding\n toHex,\n fromHex,\n toBase64,\n fromBase64,\n toBase64Url,\n fromBase64Url,\n bufferToString,\n stringToBuffer,\n // Constant-time\n constantTimeEqual,\n // Buffer manipulation\n concat,\n zeroize,\n xor,\n} from './utils';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Validators (for advanced users building higher-level protocols)\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport {\n assertBuffer,\n assertBufferLength,\n assertBufferOfSize,\n assertPositiveInteger,\n assertHkdfLength,\n buffersSameLength,\n} from './validators';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Constants\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport {\n // Curve25519\n CURVE25519_PRIVATE_KEY_SIZE,\n CURVE25519_PUBLIC_KEY_SIZE,\n CURVE25519_SHARED_SECRET_SIZE,\n // HKDF\n HKDF_PRK_SIZE,\n HKDF_MAX_OUTPUT_SIZE,\n // AES\n AES_256_KEY_SIZE,\n AES_256_GCM_NONCE_SIZE,\n AES_256_GCM_TAG_SIZE,\n AES_256_CBC_IV_SIZE,\n AES_BLOCK_SIZE,\n AES_GCM_MAX_PLAINTEXT_SIZE,\n AES_GCM_RECOMMENDED_MESSAGES_PER_KEY,\n // SHA-256 / HMAC\n SHA256_OUTPUT_SIZE,\n HMAC_SHA256_TAG_SIZE,\n SHA256_BLOCK_SIZE,\n} from './constants';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Library version\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * The version of `@brashkie/signalis-core` (matches `package.json`).\n *\n * Bumped on every release.\n */\nexport const VERSION = '0.1.0' as const;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Default export — Convenience namespace\n// ═══════════════════════════════════════════════════════════════════════════\n\nimport { Curve25519, HKDF, AES_GCM, AES_CBC, HMAC, SHA256, nativeVersion } from './core';\nimport {\n secureRandom,\n randomNonce,\n randomIv,\n randomKey,\n toHex,\n fromHex,\n toBase64,\n fromBase64,\n constantTimeEqual,\n} from './utils';\n\n/**\n * Default export — provides all primitives and helpers under one namespace.\n *\n * @example\n * ```ts\n * import sc from '@brashkie/signalis-core';\n *\n * const kp = sc.Curve25519.generateKeyPair();\n * const nonce = sc.secureRandom(12);\n * ```\n */\nconst SignalisCore = Object.freeze({\n // Crypto primitives\n Curve25519,\n HKDF,\n AES_GCM,\n AES_CBC,\n HMAC,\n SHA256,\n // Random\n secureRandom,\n randomNonce,\n randomIv,\n randomKey,\n // Encoding\n toHex,\n fromHex,\n toBase64,\n fromBase64,\n // Security\n constantTimeEqual,\n // Version\n VERSION: '0.1.0' as const,\n nativeVersion,\n});\n\nexport default SignalisCore;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/core.ts","../src/constants.ts","../src/errors.ts","../src/validators.ts","../src/types.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["/**\n * Core cryptographic wrappers for signalis-core.\n *\n * Provides robust, validated, and well-documented APIs over the native Rust\n * crypto primitives.\n *\n * @packageDocumentation\n */\n\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nimport * as native from '../index.js';\n\nimport {\n CURVE25519_PRIVATE_KEY_SIZE,\n CURVE25519_PUBLIC_KEY_SIZE,\n CURVE25519_SHARED_SECRET_SIZE,\n HKDF_PRK_SIZE,\n AES_256_KEY_SIZE,\n AES_256_GCM_NONCE_SIZE,\n AES_256_GCM_TAG_SIZE,\n AES_256_CBC_IV_SIZE,\n HMAC_SHA256_TAG_SIZE,\n SHA256_OUTPUT_SIZE,\n ED25519_PRIVATE_KEY_SIZE,\n ED25519_PUBLIC_KEY_SIZE,\n ED25519_SIGNATURE_SIZE,\n ED25519_SEED_SIZE,\n XED25519_PRIVATE_KEY_SIZE,\n XED25519_PUBLIC_KEY_SIZE,\n XED25519_SIGNATURE_SIZE,\n XED25519_RANDOM_SIZE,\n} from './constants';\n\nimport {\n CryptoError,\n AuthenticationError,\n SignatureError,\n} from './errors';\n\nimport {\n assertBufferOfSize,\n assertBuffer,\n assertHkdfLength,\n} from './validators';\n\nimport type {\n KeyPair,\n HkdfParams,\n Signature,\n} from './types';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Curve25519 / X25519\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Curve25519 / X25519 elliptic curve operations.\n *\n * Provides:\n * - Keypair generation\n * - Public key derivation\n * - ECDH key agreement\n *\n * @example\n * ```ts\n * import { Curve25519 } from '@brashkie/signalis-core';\n *\n * const alice = Curve25519.generateKeyPair();\n * const bob = Curve25519.generateKeyPair();\n *\n * const shared = Curve25519.diffieHellman(alice.privateKey, bob.publicKey);\n * // ⚠️ Always derive via HKDF before use as a key!\n * ```\n */\nexport const Curve25519 = Object.freeze({\n /**\n * Generate a new random Curve25519 keypair.\n *\n * Uses the OS's cryptographically secure RNG (via Rust's `OsRng`).\n *\n * @returns A {@link KeyPair} with private and public keys (32 bytes each)\n */\n generateKeyPair(): KeyPair {\n const kp = native.curve25519GenerateKeypair() as {\n private: Buffer;\n public: Buffer;\n };\n return Object.freeze({\n privateKey: kp.private,\n publicKey: kp.public,\n });\n },\n\n /**\n * Derive the public key corresponding to a given private key.\n *\n * @param privateKey - 32-byte private key\n * @returns The corresponding 32-byte public key\n * @throws {ValidationError} If `privateKey` is not a 32-byte Buffer.\n */\n publicFromPrivate(privateKey: Buffer): Buffer {\n assertBufferOfSize(privateKey, CURVE25519_PRIVATE_KEY_SIZE, 'privateKey');\n // X25519 base scalar mult cannot fail with a 32-byte (clamped) scalar\n return native.curve25519PublicFromPrivate(privateKey) as Buffer;\n },\n\n /**\n * Perform X25519 Diffie-Hellman key agreement.\n *\n * Both parties run this with swapped (private, peer-public) arguments\n * and obtain the same 32-byte shared secret.\n *\n * **⚠️ CRITICAL:** Do NOT use the returned secret directly as an\n * encryption key. Always derive an actual key through HKDF:\n *\n * @example\n * ```ts\n * const shared = Curve25519.diffieHellman(myPriv, theirPub);\n * const key = HKDF.derive(salt, shared, Buffer.from('aes-key'), 32);\n * ```\n *\n * @param privateKey - Your 32-byte private key\n * @param peerPublicKey - Peer's 32-byte public key\n * @returns 32-byte shared secret\n * @throws {ValidationError} If keys are not 32 bytes.\n * @throws {CryptoError} If the operation fails.\n */\n diffieHellman(privateKey: Buffer, peerPublicKey: Buffer): Buffer {\n assertBufferOfSize(privateKey, CURVE25519_PRIVATE_KEY_SIZE, 'privateKey');\n assertBufferOfSize(peerPublicKey, CURVE25519_PUBLIC_KEY_SIZE, 'peerPublicKey');\n // X25519 ECDH cannot fail with valid 32-byte inputs\n return native.curve25519DiffieHellman(privateKey, peerPublicKey) as Buffer;\n },\n\n /**\n * The size of a Curve25519 private key in bytes (32).\n */\n PRIVATE_KEY_SIZE: CURVE25519_PRIVATE_KEY_SIZE,\n\n /**\n * The size of a Curve25519 public key in bytes (32).\n */\n PUBLIC_KEY_SIZE: CURVE25519_PUBLIC_KEY_SIZE,\n\n /**\n * The size of an X25519 shared secret in bytes (32).\n */\n SHARED_SECRET_SIZE: CURVE25519_SHARED_SECRET_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// HKDF-SHA256\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * HKDF-SHA256 (RFC 5869) — HMAC-based Key Derivation Function.\n *\n * Provides cryptographic key derivation from high-entropy inputs (e.g., ECDH\n * shared secrets) into arbitrary-length output keying material (OKM).\n *\n * @example\n * ```ts\n * // One-shot (recommended)\n * const key = HKDF.derive(salt, sharedSecret, Buffer.from('aes-key'), 32);\n *\n * // Two-step (advanced)\n * const prk = HKDF.extract(salt, ikm);\n * const okm = HKDF.expand(prk, info, 64);\n * ```\n */\nexport const HKDF = Object.freeze({\n /**\n * HKDF-Extract: produces a 32-byte pseudorandom key (PRK).\n *\n * @param salt - Optional salt (pass `Buffer.alloc(0)` if not available)\n * @param ikm - Input keying material\n * @returns 32-byte PRK\n * @throws {ValidationError} If inputs are not Buffers.\n */\n extract(salt: Buffer, ikm: Buffer): Buffer {\n assertBuffer(salt, 'salt');\n assertBuffer(ikm, 'ikm');\n return native.hkdfExtract(salt, ikm) as Buffer;\n },\n\n /**\n * HKDF-Expand: produces `length` bytes of output keying material.\n *\n * @param prk - 32-byte pseudorandom key from {@link extract}\n * @param info - Context-specific information (binds output to a usage)\n * @param length - Desired output length (1 to 8160 bytes)\n * @returns OKM of requested length\n * @throws {ValidationError} If PRK is not 32 bytes or length is out of bounds.\n */\n expand(prk: Buffer, info: Buffer, length: number): Buffer {\n assertBufferOfSize(prk, HKDF_PRK_SIZE, 'prk');\n assertBuffer(info, 'info');\n assertHkdfLength(length);\n // Length already validated; native cannot fail with valid PRK + length <= 8160\n return native.hkdfExpand(prk, info, length) as Buffer;\n },\n\n /**\n * HKDF one-shot: extract + expand in a single call.\n *\n * Use this whenever possible — it's the standard HKDF API.\n *\n * @param salt - Optional salt\n * @param ikm - Input keying material\n * @param info - Context info\n * @param length - Desired output length\n * @returns OKM of requested length\n */\n derive(salt: Buffer, ikm: Buffer, info: Buffer, length: number): Buffer {\n assertBuffer(salt, 'salt');\n assertBuffer(ikm, 'ikm');\n assertBuffer(info, 'info');\n assertHkdfLength(length);\n // Length already validated; native cannot fail with valid inputs\n return native.hkdfDerive(salt, ikm, info, length) as Buffer;\n },\n\n /**\n * Derive multiple keys from the same shared secret in a single call.\n *\n * Useful for deriving e.g., a send key AND a receive key simultaneously.\n *\n * @example\n * ```ts\n * const [sendKey, recvKey] = HKDF.deriveMultiple(\n * salt,\n * sharedSecret,\n * Buffer.from('signalis-channel-v1'),\n * [32, 32],\n * );\n * ```\n *\n * @param salt - Optional salt\n * @param ikm - Input keying material\n * @param info - Context info\n * @param lengths - Array of output lengths\n * @returns Array of derived keys, one per requested length\n */\n deriveMultiple(\n salt: Buffer,\n ikm: Buffer,\n info: Buffer,\n lengths: number[],\n ): Buffer[] {\n assertBuffer(salt, 'salt');\n assertBuffer(ikm, 'ikm');\n assertBuffer(info, 'info');\n if (!Array.isArray(lengths) || lengths.length === 0) {\n throw new TypeError('lengths must be a non-empty array of integers');\n }\n\n const total = lengths.reduce((sum, len) => sum + len, 0);\n assertHkdfLength(total);\n\n const okm = this.derive(salt, ikm, info, total);\n const results: Buffer[] = [];\n let offset = 0;\n for (const len of lengths) {\n results.push(okm.subarray(offset, offset + len));\n offset += len;\n }\n return results;\n },\n\n /**\n * Derive a key using an {@link HkdfParams} object (alternative API).\n */\n deriveFromParams(params: HkdfParams): Buffer {\n return this.derive(params.salt, params.ikm, params.info, params.length);\n },\n\n /**\n * The size of an HKDF PRK in bytes (32).\n */\n PRK_SIZE: HKDF_PRK_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// AES-256-GCM (Authenticated Encryption)\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * AES-256-GCM authenticated encryption (AEAD).\n *\n * Combines confidentiality + authenticity in a single primitive.\n *\n * **⚠️ CRITICAL SECURITY RULES:**\n * 1. Never reuse a (key, nonce) pair. Catastrophic failure.\n * 2. Generate nonces with `secureRandom(12)` for each message.\n * 3. After 2^32 messages with random nonces, rotate the key.\n *\n * @example\n * ```ts\n * import { AES_GCM, secureRandom } from '@brashkie/signalis-core';\n *\n * const key = secureRandom(32);\n * const nonce = secureRandom(12);\n * const plaintext = Buffer.from('Hello!');\n *\n * const ciphertext = AES_GCM.encrypt(key, nonce, plaintext);\n * const decrypted = AES_GCM.decrypt(key, nonce, ciphertext);\n * ```\n */\nexport const AES_GCM = Object.freeze({\n /**\n * Encrypt plaintext.\n *\n * Returns: ciphertext || 16-byte authentication tag (concatenated).\n *\n * @param key - 32-byte symmetric key\n * @param nonce - 12-byte unique nonce (NEVER reuse with same key)\n * @param plaintext - Data to encrypt\n * @returns Ciphertext + auth tag (output is `plaintext.length + 16` bytes)\n * @throws {ValidationError} On invalid sizes.\n * @throws {CryptoError} If the operation fails.\n */\n encrypt(key: Buffer, nonce: Buffer, plaintext: Buffer): Buffer {\n assertBufferOfSize(key, AES_256_KEY_SIZE, 'key');\n assertBufferOfSize(nonce, AES_256_GCM_NONCE_SIZE, 'nonce');\n assertBuffer(plaintext, 'plaintext');\n // GCM encryption cannot fail with valid-sized inputs\n return native.aes256GcmEncrypt(key, nonce, plaintext) as Buffer;\n },\n\n /**\n * Decrypt ciphertext and verify authentication tag.\n *\n * @param key - 32-byte symmetric key (same as encryption)\n * @param nonce - 12-byte nonce (same as encryption)\n * @param ciphertext - Ciphertext || auth tag\n * @returns Original plaintext\n * @throws {ValidationError} On invalid sizes.\n * @throws {AuthenticationError} If the tag is invalid (tampered or wrong key).\n */\n decrypt(key: Buffer, nonce: Buffer, ciphertext: Buffer): Buffer {\n assertBufferOfSize(key, AES_256_KEY_SIZE, 'key');\n assertBufferOfSize(nonce, AES_256_GCM_NONCE_SIZE, 'nonce');\n assertBuffer(ciphertext, 'ciphertext');\n\n if (ciphertext.length < AES_256_GCM_TAG_SIZE) {\n throw new CryptoError(\n `Ciphertext too short: must be at least ${AES_256_GCM_TAG_SIZE} bytes (tag size)`,\n 'aes_gcm_decrypt',\n );\n }\n\n try {\n return native.aes256GcmDecrypt(key, nonce, ciphertext) as Buffer;\n } catch (e) {\n throw new AuthenticationError(\n `AES-256-GCM authentication failed: ${(e as Error).message}`,\n );\n }\n },\n\n /** Key size in bytes (32). */\n KEY_SIZE: AES_256_KEY_SIZE,\n /** Nonce size in bytes (12). */\n NONCE_SIZE: AES_256_GCM_NONCE_SIZE,\n /** Tag size in bytes (16). */\n TAG_SIZE: AES_256_GCM_TAG_SIZE,\n\n /**\n * Encrypt with AES-256-GCM and Additional Authenticated Data (NEW in v0.2.0).\n *\n * AAD is authenticated but NOT encrypted. Useful for binding metadata\n * (like message headers) to the ciphertext.\n *\n * @param key - 32-byte symmetric key\n * @param nonce - 12-byte unique nonce\n * @param plaintext - Data to encrypt\n * @param aad - Additional authenticated data (any length, can be empty)\n * @returns Ciphertext + auth tag\n * @throws {ValidationError} On invalid sizes.\n */\n encryptWithAad(key: Buffer, nonce: Buffer, plaintext: Buffer, aad: Buffer): Buffer {\n assertBufferOfSize(key, AES_256_KEY_SIZE, 'key');\n assertBufferOfSize(nonce, AES_256_GCM_NONCE_SIZE, 'nonce');\n assertBuffer(plaintext, 'plaintext');\n assertBuffer(aad, 'aad');\n return native.aes256GcmEncryptWithAad(key, nonce, plaintext, aad) as Buffer;\n },\n\n /**\n * Decrypt with AES-256-GCM and AAD (NEW in v0.2.0).\n *\n * The same AAD used during encryption must be provided. Mismatch = failure.\n *\n * @throws {AuthenticationError} If tag verification fails (incl. AAD mismatch).\n */\n decryptWithAad(key: Buffer, nonce: Buffer, ciphertext: Buffer, aad: Buffer): Buffer {\n assertBufferOfSize(key, AES_256_KEY_SIZE, 'key');\n assertBufferOfSize(nonce, AES_256_GCM_NONCE_SIZE, 'nonce');\n assertBuffer(ciphertext, 'ciphertext');\n assertBuffer(aad, 'aad');\n\n if (ciphertext.length < AES_256_GCM_TAG_SIZE) {\n throw new CryptoError(\n `Ciphertext too short: must be at least ${AES_256_GCM_TAG_SIZE} bytes (tag size)`,\n 'aes_gcm_decrypt_with_aad',\n );\n }\n\n try {\n return native.aes256GcmDecryptWithAad(key, nonce, ciphertext, aad) as Buffer;\n } catch (e) {\n throw new AuthenticationError(\n `AES-256-GCM authentication failed: ${(e as Error).message}`,\n );\n }\n },\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// AES-256-CBC (Encryption only — pair with HMAC!)\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * AES-256-CBC block cipher (NOT authenticated by itself).\n *\n * **⚠️ MUST be paired with HMAC** for integrity protection (encrypt-then-MAC).\n *\n * Prefer {@link AES_GCM} unless you need:\n * - Legacy Signal Protocol media compatibility\n * - Hardware that lacks GCM acceleration\n */\nexport const AES_CBC = Object.freeze({\n /**\n * Encrypt with PKCS#7 padding.\n *\n * @param key - 32-byte symmetric key\n * @param iv - 16-byte initialization vector\n * @param plaintext - Data to encrypt\n * @returns Ciphertext (padded to nearest 16-byte block)\n */\n encrypt(key: Buffer, iv: Buffer, plaintext: Buffer): Buffer {\n assertBufferOfSize(key, AES_256_KEY_SIZE, 'key');\n assertBufferOfSize(iv, AES_256_CBC_IV_SIZE, 'iv');\n assertBuffer(plaintext, 'plaintext');\n // CBC encryption with PKCS#7 padding cannot fail given valid-sized inputs\n return native.aes256CbcEncrypt(key, iv, plaintext) as Buffer;\n },\n\n /**\n * Decrypt with PKCS#7 padding (no authentication).\n *\n * @param key - 32-byte symmetric key\n * @param iv - 16-byte IV (same as encryption)\n * @param ciphertext - Ciphertext\n * @returns Original plaintext\n * @throws {CryptoError} On padding errors.\n */\n decrypt(key: Buffer, iv: Buffer, ciphertext: Buffer): Buffer {\n assertBufferOfSize(key, AES_256_KEY_SIZE, 'key');\n assertBufferOfSize(iv, AES_256_CBC_IV_SIZE, 'iv');\n assertBuffer(ciphertext, 'ciphertext');\n try {\n return native.aes256CbcDecrypt(key, iv, ciphertext) as Buffer;\n } catch (e) {\n throw new CryptoError(\n `AES-256-CBC decryption failed: ${(e as Error).message}`,\n 'aes_cbc_decrypt',\n );\n }\n },\n\n /** Key size in bytes (32). */\n KEY_SIZE: AES_256_KEY_SIZE,\n /** IV size in bytes (16). */\n IV_SIZE: AES_256_CBC_IV_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// HMAC-SHA256\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * HMAC-SHA256 message authentication code.\n *\n * Provides cryptographic authentication of arbitrary data with a shared key.\n *\n * @example\n * ```ts\n * const tag = HMAC.sha256(key, message);\n * const valid = HMAC.verifySha256(key, message, tag); // constant-time\n * ```\n */\nexport const HMAC = Object.freeze({\n /**\n * Compute HMAC-SHA256 of `data` using `key`.\n *\n * @param key - Authentication key (any length)\n * @param data - Data to authenticate\n * @returns 32-byte HMAC tag\n */\n sha256(key: Buffer, data: Buffer): Buffer {\n assertBuffer(key, 'key');\n assertBuffer(data, 'data');\n return native.hmacSha256(key, data) as Buffer;\n },\n\n /**\n * Verify an HMAC-SHA256 tag in **constant time**.\n *\n * Always use this instead of `===` to prevent timing attacks.\n *\n * @param key - Authentication key\n * @param data - Original data\n * @param expectedTag - Tag to verify\n * @returns `true` if tag matches, `false` otherwise\n */\n verifySha256(key: Buffer, data: Buffer, expectedTag: Buffer): boolean {\n assertBuffer(key, 'key');\n assertBuffer(data, 'data');\n assertBuffer(expectedTag, 'expectedTag');\n return native.hmacSha256Verify(key, data, expectedTag) as boolean;\n },\n\n /** Tag size in bytes (32). */\n TAG_SIZE: HMAC_SHA256_TAG_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// SHA-256\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * SHA-256 cryptographic hash function.\n *\n * @example\n * ```ts\n * const digest = SHA256.hash(Buffer.from('hello'));\n * ```\n */\nexport const SHA256 = Object.freeze({\n /**\n * Compute SHA-256 hash of `data`.\n *\n * @param data - Data to hash\n * @returns 32-byte digest\n */\n hash(data: Buffer): Buffer {\n assertBuffer(data, 'data');\n return native.sha256(data) as Buffer;\n },\n\n /**\n * Hash multiple Buffers concatenated together.\n *\n * Equivalent to `SHA256.hash(Buffer.concat([...]))` but slightly more\n * efficient (avoids the intermediate concat).\n */\n hashAll(buffers: Buffer[]): Buffer {\n if (!Array.isArray(buffers)) {\n throw new TypeError('buffers must be an array');\n }\n for (let i = 0; i < buffers.length; i++) {\n assertBuffer(buffers[i]!, `buffers[${i}]`);\n }\n return this.hash(Buffer.concat(buffers));\n },\n\n /** Output size in bytes (32). */\n OUTPUT_SIZE: SHA256_OUTPUT_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Ed25519 (Standard Digital Signatures) — NEW in v0.2.0\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Ed25519 digital signatures (RFC 8032).\n *\n * Standard Ed25519 with deterministic signatures. Use when you want clean\n * separation between signing and ECDH keys.\n *\n * @example\n * ```ts\n * import { Ed25519 } from '@brashkie/signalis-core';\n *\n * const keys = Ed25519.generateKeyPair();\n * const sig = Ed25519.sign(keys.privateKey, Buffer.from('Hello'));\n * Ed25519.verify(keys.publicKey, Buffer.from('Hello'), sig);\n * ```\n */\nexport const Ed25519 = Object.freeze({\n /**\n * Generate a new random Ed25519 keypair.\n */\n generateKeyPair(): KeyPair {\n const kp = native.ed25519GenerateKeypair() as {\n private: Buffer;\n public: Buffer;\n };\n return Object.freeze({\n privateKey: kp.private,\n publicKey: kp.public,\n });\n },\n\n /**\n * Derive a deterministic Ed25519 keypair from a 32-byte seed.\n */\n keyPairFromSeed(seed: Buffer): KeyPair {\n assertBufferOfSize(seed, ED25519_SEED_SIZE, 'seed');\n const kp = native.ed25519KeypairFromSeed(seed) as {\n private: Buffer;\n public: Buffer;\n };\n return Object.freeze({\n privateKey: kp.private,\n publicKey: kp.public,\n });\n },\n\n /**\n * Derive the public key from a private key.\n */\n publicFromPrivate(privateKey: Buffer): Buffer {\n assertBufferOfSize(privateKey, ED25519_PRIVATE_KEY_SIZE, 'privateKey');\n return native.ed25519PublicFromPrivate(privateKey) as Buffer;\n },\n\n /**\n * Sign a message. Ed25519 signatures are deterministic (RFC 8032).\n */\n sign(privateKey: Buffer, message: Buffer): Signature {\n assertBufferOfSize(privateKey, ED25519_PRIVATE_KEY_SIZE, 'privateKey');\n assertBuffer(message, 'message');\n return native.ed25519Sign(privateKey, message) as Signature;\n },\n\n /**\n * Verify a signature. Throws on failure.\n *\n * @throws {SignatureError} If signature is invalid.\n */\n verify(publicKey: Buffer, message: Buffer, signature: Buffer): void {\n assertBufferOfSize(publicKey, ED25519_PUBLIC_KEY_SIZE, 'publicKey');\n assertBuffer(message, 'message');\n assertBufferOfSize(signature, ED25519_SIGNATURE_SIZE, 'signature');\n try {\n native.ed25519Verify(publicKey, message, signature);\n } catch (e) {\n throw new SignatureError((e as Error).message);\n }\n },\n\n /**\n * Verify a signature. Returns boolean (does not throw).\n */\n verifyBool(publicKey: Buffer, message: Buffer, signature: Buffer): boolean {\n if (!Buffer.isBuffer(publicKey) || publicKey.length !== ED25519_PUBLIC_KEY_SIZE) return false;\n if (!Buffer.isBuffer(message)) return false;\n if (!Buffer.isBuffer(signature) || signature.length !== ED25519_SIGNATURE_SIZE) return false;\n return native.ed25519VerifyBool(publicKey, message, signature) as boolean;\n },\n\n /** Private key size in bytes (32). */\n PRIVATE_KEY_SIZE: ED25519_PRIVATE_KEY_SIZE,\n /** Public key size in bytes (32). */\n PUBLIC_KEY_SIZE: ED25519_PUBLIC_KEY_SIZE,\n /** Signature size in bytes (64). */\n SIGNATURE_SIZE: ED25519_SIGNATURE_SIZE,\n /** Seed size for deterministic keypair derivation (32). */\n SEED_SIZE: ED25519_SEED_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// XEd25519 (Signal-style signatures with Curve25519 keys) — NEW in v0.2.0\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * XEd25519 — sign messages using the SAME Curve25519 keypair used for ECDH.\n *\n * This is what Signal Protocol uses to maintain a single identity key.\n * Signatures are non-deterministic (each call gives a different valid sig).\n *\n * @example\n * ```ts\n * import { Curve25519, XEd25519 } from '@brashkie/signalis-core';\n *\n * const identity = Curve25519.generateKeyPair();\n *\n * // Use for ECDH:\n * const shared = Curve25519.diffieHellman(identity.privateKey, peerPublic);\n *\n * // SAME key used to sign:\n * const sig = XEd25519.sign(identity.privateKey, message);\n * XEd25519.verify(identity.publicKey, message, sig);\n * ```\n */\nexport const XEd25519 = Object.freeze({\n /**\n * Sign a message using a Curve25519 private key. Uses OS RNG.\n * Signatures are NOT deterministic (different each call).\n */\n sign(privateKey: Buffer, message: Buffer): Signature {\n assertBufferOfSize(privateKey, XED25519_PRIVATE_KEY_SIZE, 'privateKey');\n assertBuffer(message, 'message');\n return native.xed25519Sign(privateKey, message) as Signature;\n },\n\n /**\n * Sign with explicit 64-byte random nonce (for testing/reproducibility).\n */\n signWithRandom(privateKey: Buffer, message: Buffer, random: Buffer): Signature {\n assertBufferOfSize(privateKey, XED25519_PRIVATE_KEY_SIZE, 'privateKey');\n assertBuffer(message, 'message');\n assertBufferOfSize(random, XED25519_RANDOM_SIZE, 'random');\n return native.xed25519SignWithRandom(privateKey, message, random) as Signature;\n },\n\n /**\n * Verify a XEd25519 signature. Throws on failure.\n *\n * @throws {SignatureError} If signature is invalid.\n */\n verify(publicKey: Buffer, message: Buffer, signature: Buffer): void {\n assertBufferOfSize(publicKey, XED25519_PUBLIC_KEY_SIZE, 'publicKey');\n assertBuffer(message, 'message');\n assertBufferOfSize(signature, XED25519_SIGNATURE_SIZE, 'signature');\n try {\n native.xed25519Verify(publicKey, message, signature);\n } catch (e) {\n throw new SignatureError((e as Error).message);\n }\n },\n\n /**\n * Verify a XEd25519 signature. Returns boolean (does not throw).\n */\n verifyBool(publicKey: Buffer, message: Buffer, signature: Buffer): boolean {\n if (!Buffer.isBuffer(publicKey) || publicKey.length !== XED25519_PUBLIC_KEY_SIZE) return false;\n if (!Buffer.isBuffer(message)) return false;\n if (!Buffer.isBuffer(signature) || signature.length !== XED25519_SIGNATURE_SIZE) return false;\n return native.xed25519VerifyBool(publicKey, message, signature) as boolean;\n },\n\n /** Private key size in bytes (32, same as Curve25519). */\n PRIVATE_KEY_SIZE: XED25519_PRIVATE_KEY_SIZE,\n /** Public key size in bytes (32, same as Curve25519). */\n PUBLIC_KEY_SIZE: XED25519_PUBLIC_KEY_SIZE,\n /** Signature size in bytes (64). */\n SIGNATURE_SIZE: XED25519_SIGNATURE_SIZE,\n /** Random nonce size for signing (64). */\n RANDOM_SIZE: XED25519_RANDOM_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Library version\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * The version of the underlying Rust crate (from `Cargo.toml`).\n */\nexport const nativeVersion: string = (native.version as () => string)();\n\n// ═══════════════════════════════════════════════════════════════════════════\n// ChaCha20-Poly1305 (NEW in v0.3.0)\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** ChaCha20-Poly1305 key size (bytes). */\nexport const CHACHA20_POLY1305_KEY_SIZE = 32;\n/** ChaCha20-Poly1305 nonce size (bytes). */\nexport const CHACHA20_POLY1305_NONCE_SIZE = 12;\n/** Poly1305 authentication tag size (bytes), appended to ciphertext. */\nexport const CHACHA20_POLY1305_TAG_SIZE = 16;\n\n/**\n * ChaCha20-Poly1305 authenticated encryption with associated data (AEAD).\n *\n * RFC 8439-compliant alternative to AES-GCM. Same security guarantees,\n * but typically 2-3x faster on platforms without AES-NI hardware\n * (Android arm64-v8a without crypto extensions, IoT, older embedded).\n *\n * On servers and modern desktops with AES-NI, AES-GCM is usually faster\n * — pick the cipher based on your deployment target.\n *\n * @example\n * ```ts\n * import { ChaCha20Poly1305, secureRandom } from '@brashkie/signalis-core';\n *\n * const key = secureRandom(32);\n * const nonce = secureRandom(12);\n * const ct = ChaCha20Poly1305.encrypt(key, nonce, Buffer.from('secret'));\n * const pt = ChaCha20Poly1305.decrypt(key, nonce, ct);\n * ```\n */\nexport const ChaCha20Poly1305 = Object.freeze({\n /**\n * Encrypt + authenticate `plaintext`.\n *\n * @param key 32-byte key\n * @param nonce 12-byte nonce — MUST be unique per (key, plaintext)\n * @param plaintext data to encrypt\n * @returns ciphertext || tag (16 bytes appended)\n */\n encrypt(key: Buffer, nonce: Buffer, plaintext: Buffer): Buffer {\n if (!Buffer.isBuffer(key) || key.length !== CHACHA20_POLY1305_KEY_SIZE) {\n throw new RangeError(`key must be ${CHACHA20_POLY1305_KEY_SIZE} bytes`);\n }\n if (!Buffer.isBuffer(nonce) || nonce.length !== CHACHA20_POLY1305_NONCE_SIZE) {\n throw new RangeError(`nonce must be ${CHACHA20_POLY1305_NONCE_SIZE} bytes`);\n }\n if (!Buffer.isBuffer(plaintext)) {\n throw new TypeError('plaintext must be a Buffer');\n }\n return native.chacha20Poly1305Encrypt(key, nonce, plaintext) as Buffer;\n },\n\n /**\n * Verify-then-decrypt. Returns plaintext on success, throws on auth failure.\n */\n decrypt(key: Buffer, nonce: Buffer, ciphertext: Buffer): Buffer {\n if (!Buffer.isBuffer(key) || key.length !== CHACHA20_POLY1305_KEY_SIZE) {\n throw new RangeError(`key must be ${CHACHA20_POLY1305_KEY_SIZE} bytes`);\n }\n if (!Buffer.isBuffer(nonce) || nonce.length !== CHACHA20_POLY1305_NONCE_SIZE) {\n throw new RangeError(`nonce must be ${CHACHA20_POLY1305_NONCE_SIZE} bytes`);\n }\n if (!Buffer.isBuffer(ciphertext)) {\n throw new TypeError('ciphertext must be a Buffer');\n }\n return native.chacha20Poly1305Decrypt(key, nonce, ciphertext) as Buffer;\n },\n\n /**\n * Encrypt + authenticate with Additional Authenticated Data.\n *\n * AAD is NOT encrypted but IS authenticated. Use for plaintext metadata\n * (e.g., message headers) that must not be tampered with.\n */\n encryptWithAad(\n key: Buffer,\n nonce: Buffer,\n plaintext: Buffer,\n aad: Buffer,\n ): Buffer {\n if (!Buffer.isBuffer(key) || key.length !== CHACHA20_POLY1305_KEY_SIZE) {\n throw new RangeError(`key must be ${CHACHA20_POLY1305_KEY_SIZE} bytes`);\n }\n if (!Buffer.isBuffer(nonce) || nonce.length !== CHACHA20_POLY1305_NONCE_SIZE) {\n throw new RangeError(`nonce must be ${CHACHA20_POLY1305_NONCE_SIZE} bytes`);\n }\n if (!Buffer.isBuffer(plaintext) || !Buffer.isBuffer(aad)) {\n throw new TypeError('plaintext and aad must be Buffers');\n }\n return native.chacha20Poly1305EncryptWithAad(key, nonce, plaintext, aad) as Buffer;\n },\n\n /**\n * Verify (key + nonce + ciphertext + AAD) and decrypt.\n */\n decryptWithAad(\n key: Buffer,\n nonce: Buffer,\n ciphertext: Buffer,\n aad: Buffer,\n ): Buffer {\n if (!Buffer.isBuffer(key) || key.length !== CHACHA20_POLY1305_KEY_SIZE) {\n throw new RangeError(`key must be ${CHACHA20_POLY1305_KEY_SIZE} bytes`);\n }\n if (!Buffer.isBuffer(nonce) || nonce.length !== CHACHA20_POLY1305_NONCE_SIZE) {\n throw new RangeError(`nonce must be ${CHACHA20_POLY1305_NONCE_SIZE} bytes`);\n }\n if (!Buffer.isBuffer(ciphertext) || !Buffer.isBuffer(aad)) {\n throw new TypeError('ciphertext and aad must be Buffers');\n }\n return native.chacha20Poly1305DecryptWithAad(key, nonce, ciphertext, aad) as Buffer;\n },\n\n /** Key size in bytes (32). */\n KEY_SIZE: CHACHA20_POLY1305_KEY_SIZE,\n /** Nonce size in bytes (12). */\n NONCE_SIZE: CHACHA20_POLY1305_NONCE_SIZE,\n /** Authentication tag size in bytes (16), appended to ciphertext. */\n TAG_SIZE: CHACHA20_POLY1305_TAG_SIZE,\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Constant-time comparison (NEW in v0.3.0)\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Compare two buffers in constant time.\n *\n * Returns `true` only if both buffers have identical length AND contents.\n *\n * Use this for any secret comparison (MAC tags, signatures, tokens) where\n * a fast-fail comparison could leak information via timing side-channels.\n *\n * **Wrong:**\n * ```ts\n * if (expectedMac.equals(receivedMac)) { ... } // ← timing-vulnerable\n * ```\n *\n * **Right:**\n * ```ts\n * if (constantTimeEq(expectedMac, receivedMac)) { ... }\n * ```\n */\nexport function constantTimeEq(a: Buffer, b: Buffer): boolean {\n if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {\n throw new TypeError('constantTimeEq: both arguments must be Buffers');\n }\n return native.constantTimeEq(a, b) as boolean;\n}\n\n/**\n * Generate `size` cryptographically secure random bytes via the OS RNG\n * (Rust side). Equivalent to {@link secureRandom} but routed through the\n * native bindings — useful when you want to ensure entropy comes from the\n * same source that the rest of the library uses internally.\n *\n * For most code, plain {@link secureRandom} (which uses `node:crypto`)\n * is fine and avoids a NAPI hop.\n */\nexport function nativeSecureRandom(size: number): Buffer {\n if (!Number.isInteger(size) || size <= 0) {\n throw new RangeError(`size must be a positive integer, got ${size}`);\n }\n return native.secureRandom(size) as Buffer;\n}\n","/**\n * Public constants used throughout signalis-core.\n *\n * @packageDocumentation\n */\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Curve25519 / X25519\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** Size of a Curve25519 private key in bytes. */\nexport const CURVE25519_PRIVATE_KEY_SIZE = 32;\n\n/** Size of a Curve25519 public key in bytes. */\nexport const CURVE25519_PUBLIC_KEY_SIZE = 32;\n\n/** Size of an X25519 ECDH shared secret in bytes. */\nexport const CURVE25519_SHARED_SECRET_SIZE = 32;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Ed25519 (NEW in v0.2.0) — Standard digital signatures\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** Size of an Ed25519 private key in bytes. */\nexport const ED25519_PRIVATE_KEY_SIZE = 32;\n\n/** Size of an Ed25519 public key in bytes. */\nexport const ED25519_PUBLIC_KEY_SIZE = 32;\n\n/** Size of an Ed25519 signature in bytes. */\nexport const ED25519_SIGNATURE_SIZE = 64;\n\n/** Size of an Ed25519 seed for deterministic key derivation. */\nexport const ED25519_SEED_SIZE = 32;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// XEd25519 (NEW in v0.2.0) — Signatures using Curve25519 keys (Signal style)\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** Size of an XEd25519 private key in bytes (same as Curve25519). */\nexport const XED25519_PRIVATE_KEY_SIZE = 32;\n\n/** Size of an XEd25519 public key in bytes (same as Curve25519). */\nexport const XED25519_PUBLIC_KEY_SIZE = 32;\n\n/** Size of an XEd25519 signature in bytes. */\nexport const XED25519_SIGNATURE_SIZE = 64;\n\n/** Size of XEd25519 random nonce for signing (in bytes). */\nexport const XED25519_RANDOM_SIZE = 64;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// HKDF-SHA256\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** Size of HKDF-SHA256 PRK (pseudorandom key) in bytes. */\nexport const HKDF_PRK_SIZE = 32;\n\n/** Maximum HKDF-SHA256 output length: 255 * HashLen = 255 * 32 = 8160 bytes. */\nexport const HKDF_MAX_OUTPUT_SIZE = 8160;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// AES-256\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** Size of an AES-256 key in bytes. */\nexport const AES_256_KEY_SIZE = 32;\n\n/** Size of an AES-256-GCM nonce in bytes (recommended size per NIST SP 800-38D). */\nexport const AES_256_GCM_NONCE_SIZE = 12;\n\n/** Size of an AES-256-GCM authentication tag in bytes. */\nexport const AES_256_GCM_TAG_SIZE = 16;\n\n/** Size of an AES-256-CBC IV in bytes (one AES block). */\nexport const AES_256_CBC_IV_SIZE = 16;\n\n/** AES block size in bytes. */\nexport const AES_BLOCK_SIZE = 16;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// SHA-256 / HMAC\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** Size of a SHA-256 hash output in bytes. */\nexport const SHA256_OUTPUT_SIZE = 32;\n\n/** Size of an HMAC-SHA256 tag in bytes. */\nexport const HMAC_SHA256_TAG_SIZE = 32;\n\n/** SHA-256 block size (used internally by HMAC). */\nexport const SHA256_BLOCK_SIZE = 64;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Limits & Recommendations\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Maximum recommended plaintext size for AES-GCM (~64 GiB).\n *\n * AES-GCM has a hard limit of 2^39 - 256 bits ≈ 64 GiB per single encryption\n * under the same key+nonce. We recommend much smaller messages and key rotation.\n */\nexport const AES_GCM_MAX_PLAINTEXT_SIZE = 64 * 1024 * 1024 * 1024;\n\n/**\n * Recommended maximum number of messages encrypted under the same AES-GCM key\n * with random 96-bit nonces before key rotation: 2^32.\n */\nexport const AES_GCM_RECOMMENDED_MESSAGES_PER_KEY = 4294967296;\n","/**\n * Typed error classes for signalis-core.\n *\n * All errors extend the base `SignalisError` class for easy `instanceof` checks.\n *\n * @packageDocumentation\n */\n\n/**\n * Base error class for all signalis-core errors.\n *\n * @example\n * ```ts\n * try {\n * Curve25519.diffieHellman(invalidKey, peer);\n * } catch (e) {\n * if (e instanceof SignalisError) {\n * console.error('Crypto error:', e.code, e.message);\n * }\n * }\n * ```\n */\nexport class SignalisError extends Error {\n /** Error code for programmatic handling. */\n public readonly code: string;\n\n constructor(message: string, code: string) {\n super(message);\n this.name = 'SignalisError';\n this.code = code;\n // Maintain proper stack trace\n if (typeof Error.captureStackTrace === 'function') {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Thrown when input validation fails (wrong size, wrong type, etc.).\n */\nexport class ValidationError extends SignalisError {\n /** Name of the parameter that failed validation. */\n public readonly parameter?: string;\n\n /** Expected value description. */\n public readonly expected?: string;\n\n /** Actual value received. */\n public readonly actual?: string | number;\n\n constructor(\n message: string,\n options: {\n parameter?: string;\n expected?: string;\n actual?: string | number;\n } = {},\n ) {\n super(message, 'VALIDATION_ERROR');\n this.name = 'ValidationError';\n this.parameter = options.parameter;\n this.expected = options.expected;\n this.actual = options.actual;\n }\n}\n\n/**\n * Thrown when a crypto operation fails (decryption, MAC verification, etc.).\n */\nexport class CryptoError extends SignalisError {\n /** The crypto operation that failed. */\n public readonly operation: string;\n\n constructor(message: string, operation: string) {\n super(message, 'CRYPTO_ERROR');\n this.name = 'CryptoError';\n this.operation = operation;\n }\n}\n\n/**\n * Thrown when AEAD authentication fails (e.g., AES-GCM tag mismatch).\n *\n * This is a security-critical error: the ciphertext was tampered with\n * or the wrong key was used.\n */\nexport class AuthenticationError extends CryptoError {\n constructor(message = 'Authentication tag verification failed') {\n super(message, 'authenticate');\n this.name = 'AuthenticationError';\n }\n}\n\n/**\n * Thrown when a key derivation or key agreement operation fails.\n */\nexport class KeyDerivationError extends CryptoError {\n constructor(message: string) {\n super(message, 'derive_key');\n this.name = 'KeyDerivationError';\n }\n}\n\n/**\n * Thrown when a digital signature verification fails (NEW in v0.2.0).\n *\n * Used by Ed25519 and XEd25519 verification.\n */\nexport class SignatureError extends CryptoError {\n constructor(message = 'Signature verification failed') {\n super(message, 'verify_signature');\n this.name = 'SignatureError';\n }\n}\n\n/**\n * Thrown when the requested output length is invalid (e.g., HKDF > 8160 bytes).\n */\nexport class LengthError extends ValidationError {\n constructor(message: string, options: { expected?: string; actual?: number } = {}) {\n super(message, options);\n this.name = 'LengthError';\n }\n}\n","/**\n * Input validators for signalis-core.\n *\n * All validators throw `ValidationError` with detailed information.\n *\n * @packageDocumentation\n */\n\nimport { ValidationError, LengthError } from './errors';\nimport {\n HKDF_MAX_OUTPUT_SIZE,\n} from './constants';\n\n/**\n * Assert that a value is a `Buffer`.\n *\n * @throws {ValidationError} If `value` is not a Buffer.\n */\nexport function assertBuffer(value: unknown, parameter: string): asserts value is Buffer {\n if (!Buffer.isBuffer(value)) {\n throw new ValidationError(`${parameter} must be a Buffer`, {\n parameter,\n expected: 'Buffer',\n actual: typeof value,\n });\n }\n}\n\n/**\n * Assert that a Buffer has exactly the expected length.\n *\n * @throws {ValidationError} If length mismatch.\n */\nexport function assertBufferLength(\n value: Buffer,\n expectedLength: number,\n parameter: string,\n): void {\n if (value.length !== expectedLength) {\n throw new ValidationError(\n `${parameter} must be ${expectedLength} bytes, got ${value.length}`,\n {\n parameter,\n expected: `${expectedLength} bytes`,\n actual: value.length,\n },\n );\n }\n}\n\n/**\n * Combined check: must be a Buffer of exactly N bytes.\n */\nexport function assertBufferOfSize(\n value: unknown,\n expectedLength: number,\n parameter: string,\n): asserts value is Buffer {\n assertBuffer(value, parameter);\n assertBufferLength(value, expectedLength, parameter);\n}\n\n/**\n * Assert that a number is a positive integer.\n */\nexport function assertPositiveInteger(value: unknown, parameter: string): asserts value is number {\n if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {\n throw new ValidationError(`${parameter} must be a non-negative integer`, {\n parameter,\n expected: 'non-negative integer',\n actual: String(value),\n });\n }\n}\n\n/**\n * Assert HKDF output length is within bounds.\n */\nexport function assertHkdfLength(length: unknown): asserts length is number {\n assertPositiveInteger(length, 'length');\n if ((length as number) > HKDF_MAX_OUTPUT_SIZE) {\n throw new LengthError(\n `HKDF output length cannot exceed ${HKDF_MAX_OUTPUT_SIZE} bytes (255 * 32)`,\n {\n expected: `<= ${HKDF_MAX_OUTPUT_SIZE}`,\n actual: length as number,\n },\n );\n }\n if ((length as number) === 0) {\n throw new LengthError('HKDF output length must be greater than 0', {\n expected: '> 0',\n actual: 0,\n });\n }\n}\n\n/**\n * Check if two Buffers have the same length (utility for tests).\n */\nexport function buffersSameLength(a: Buffer, b: Buffer): boolean {\n return a.length === b.length;\n}\n","/**\n * Shared TypeScript types for signalis-core.\n *\n * @packageDocumentation\n */\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Curve25519\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * A Curve25519 keypair (private + public key).\n *\n * Both keys are 32-byte Buffers.\n */\nexport interface KeyPair {\n /**\n * Private key (32 bytes).\n *\n * **⚠️ KEEP THIS SECRET.** Never log, transmit, or store in plaintext.\n */\n readonly privateKey: Buffer;\n\n /**\n * Public key (32 bytes).\n *\n * Safe to share publicly.\n */\n readonly publicKey: Buffer;\n}\n\n/**\n * A Curve25519 public key — type-tag for stronger typing.\n *\n * Use {@link asPublicKey} to brand a Buffer.\n */\nexport type PublicKey = Buffer & { readonly __brand?: 'PublicKey' };\n\n/**\n * A Curve25519 private key — type-tag for stronger typing.\n *\n * Use {@link asPrivateKey} to brand a Buffer.\n */\nexport type PrivateKey = Buffer & { readonly __brand?: 'PrivateKey' };\n\n/**\n * An X25519 ECDH shared secret (32 bytes).\n *\n * **⚠️ DO NOT USE DIRECTLY AS A KEY.** Always derive through HKDF.\n */\nexport type SharedSecret = Buffer & { readonly __brand?: 'SharedSecret' };\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Signatures (NEW in v0.2.0)\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * A digital signature (64 bytes) — Ed25519 or XEd25519.\n */\nexport type Signature = Buffer & { readonly __brand?: 'Signature' };\n\n// ═══════════════════════════════════════════════════════════════════════════\n// HKDF\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * HKDF pseudorandom key (32 bytes), output of the Extract step.\n */\nexport type PseudoRandomKey = Buffer & { readonly __brand?: 'PRK' };\n\n/**\n * HKDF parameters object — useful for organizing key derivation calls.\n */\nexport interface HkdfParams {\n /** Optional salt (use `Buffer.alloc(0)` if absent). */\n salt: Buffer;\n /** Input keying material (e.g., ECDH shared secret). */\n ikm: Buffer;\n /** Context-specific information (binds the output to a usage). */\n info: Buffer;\n /** Desired output length in bytes (1 to 8160). */\n length: number;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// AES\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * AES-256-GCM parameters.\n */\nexport interface AesGcmParams {\n /** 32-byte symmetric key. */\n key: Buffer;\n /** 12-byte nonce (MUST be unique per message). */\n nonce: Buffer;\n /** Plaintext or ciphertext. */\n data: Buffer;\n}\n\n/**\n * AES-256-CBC parameters.\n */\nexport interface AesCbcParams {\n /** 32-byte symmetric key. */\n key: Buffer;\n /** 16-byte initialization vector. */\n iv: Buffer;\n /** Plaintext or ciphertext. */\n data: Buffer;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Encoding\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Supported encodings for converting Buffers to/from strings.\n */\nexport type Encoding = 'hex' | 'base64' | 'base64url' | 'utf8' | 'binary';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Branding helpers (zero-cost casts with documentation)\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Brand a Buffer as a {@link PublicKey}.\n *\n * Does NOT validate length — use validators separately.\n */\nexport function asPublicKey(buf: Buffer): PublicKey {\n return buf as PublicKey;\n}\n\n/**\n * Brand a Buffer as a {@link PrivateKey}.\n *\n * Does NOT validate length — use validators separately.\n */\nexport function asPrivateKey(buf: Buffer): PrivateKey {\n return buf as PrivateKey;\n}\n\n/**\n * Brand a Buffer as a {@link SharedSecret}.\n */\nexport function asSharedSecret(buf: Buffer): SharedSecret {\n return buf as SharedSecret;\n}\n\n/**\n * Brand a Buffer as a {@link Signature} (NEW in v0.2.0).\n */\nexport function asSignature(buf: Buffer): Signature {\n return buf as Signature;\n}\n","/**\n * Utility functions for signalis-core.\n *\n * Encoding helpers, secure random generation, and constant-time comparisons.\n *\n * @packageDocumentation\n */\n\nimport { randomBytes, timingSafeEqual } from 'node:crypto';\nimport type { Encoding } from './types';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Secure Random\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Generate cryptographically secure random bytes.\n *\n * Uses Node's `crypto.randomBytes` which delegates to the OS CSPRNG:\n * - Linux/macOS: `getrandom()` / `/dev/urandom`\n * - Windows: `BCryptGenRandom`\n *\n * @param length - Number of bytes to generate\n * @returns A Buffer of `length` random bytes\n *\n * @example\n * ```ts\n * const nonce = secureRandom(12); // 12-byte nonce for AES-GCM\n * const key = secureRandom(32); // 32-byte AES key\n * ```\n */\nexport function secureRandom(length: number): Buffer {\n if (!Number.isInteger(length) || length < 0) {\n throw new RangeError(`length must be a non-negative integer, got ${length}`);\n }\n return randomBytes(length);\n}\n\n/**\n * Generate a cryptographically secure random 12-byte nonce (for AES-GCM).\n */\nexport function randomNonce(): Buffer {\n return randomBytes(12);\n}\n\n/**\n * Generate a cryptographically secure random 16-byte IV (for AES-CBC).\n */\nexport function randomIv(): Buffer {\n return randomBytes(16);\n}\n\n/**\n * Generate a cryptographically secure random 32-byte key.\n */\nexport function randomKey(): Buffer {\n return randomBytes(32);\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Encoding helpers\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Convert a Buffer to its hexadecimal string representation.\n *\n * @example\n * ```ts\n * toHex(Buffer.from([0xff, 0x00])); // \"ff00\"\n * ```\n */\nexport function toHex(buf: Buffer): string {\n return buf.toString('hex');\n}\n\n/**\n * Parse a hexadecimal string into a Buffer.\n *\n * @throws {Error} If `hex` contains non-hex characters or has odd length.\n */\nexport function fromHex(hex: string): Buffer {\n if (!/^[0-9a-fA-F]*$/.test(hex)) {\n throw new Error('Invalid hex string: contains non-hex characters');\n }\n if (hex.length % 2 !== 0) {\n throw new Error('Invalid hex string: odd number of characters');\n }\n return Buffer.from(hex, 'hex');\n}\n\n/**\n * Convert a Buffer to a standard base64 string.\n */\nexport function toBase64(buf: Buffer): string {\n return buf.toString('base64');\n}\n\n/**\n * Parse a base64 string into a Buffer.\n */\nexport function fromBase64(b64: string): Buffer {\n return Buffer.from(b64, 'base64');\n}\n\n/**\n * Convert a Buffer to a URL-safe base64 string (no padding).\n *\n * Useful for URLs, query strings, JWT headers, etc.\n */\nexport function toBase64Url(buf: Buffer): string {\n return buf.toString('base64url');\n}\n\n/**\n * Parse a base64url string into a Buffer.\n */\nexport function fromBase64Url(b64url: string): Buffer {\n return Buffer.from(b64url, 'base64url');\n}\n\n/**\n * Convert a Buffer to a string using the specified encoding.\n */\nexport function bufferToString(buf: Buffer, encoding: Encoding = 'hex'): string {\n return buf.toString(encoding);\n}\n\n/**\n * Parse a string into a Buffer using the specified encoding.\n */\nexport function stringToBuffer(str: string, encoding: Encoding = 'hex'): Buffer {\n return Buffer.from(str, encoding);\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Constant-time comparison\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Compare two Buffers in constant time (resistant to timing attacks).\n *\n * **Always** use this instead of `===` or `Buffer.equals` when comparing\n * MACs, signatures, or any other security-sensitive bytes.\n *\n * Returns `false` if lengths differ (without revealing the difference).\n *\n * @example\n * ```ts\n * const valid = constantTimeEqual(receivedTag, expectedTag);\n * if (!valid) throw new Error('MAC verification failed');\n * ```\n */\nexport function constantTimeEqual(a: Buffer, b: Buffer): boolean {\n if (a.length !== b.length) {\n // Compare against itself to keep some constant work\n timingSafeEqual(a, a);\n return false;\n }\n return timingSafeEqual(a, b);\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Buffer manipulation\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Concatenate multiple Buffers into one.\n *\n * Thin wrapper over `Buffer.concat` with cleaner naming.\n */\nexport function concat(buffers: Buffer[]): Buffer {\n return Buffer.concat(buffers);\n}\n\n/**\n * Zero out a Buffer in-place.\n *\n * Useful for clearing sensitive data after use.\n *\n * **Note:** JavaScript runtimes may keep copies in GC buffers, so this is\n * NOT a guaranteed wipe. For real security, use Rust-side zeroization.\n */\nexport function zeroize(buf: Buffer): void {\n buf.fill(0);\n}\n\n/**\n * XOR two equal-length Buffers and return the result.\n *\n * @throws {Error} If buffers have different lengths.\n */\nexport function xor(a: Buffer, b: Buffer): Buffer {\n if (a.length !== b.length) {\n throw new Error(`XOR operands must have equal length: ${a.length} vs ${b.length}`);\n }\n const result = Buffer.alloc(a.length);\n for (let i = 0; i < a.length; i++) {\n result[i] = a[i]! ^ b[i]!;\n }\n return result;\n}\n","/**\n * # @brashkie/signalis-core\n *\n * **Cryptographic primitives for the Signal Protocol — Rust-powered.**\n *\n * High-performance, audited crypto for Node.js with full TypeScript support.\n * Works seamlessly in both CommonJS and ESM environments.\n *\n * ## Quick start\n *\n * ```typescript\n * import { Curve25519, HKDF, AES_GCM, secureRandom } from '@brashkie/signalis-core';\n *\n * // 1. Generate keypairs\n * const alice = Curve25519.generateKeyPair();\n * const bob = Curve25519.generateKeyPair();\n *\n * // 2. ECDH key agreement\n * const shared = Curve25519.diffieHellman(alice.privateKey, bob.publicKey);\n *\n * // 3. Derive a session key via HKDF\n * const key = HKDF.derive(\n * Buffer.from('app-salt'),\n * shared,\n * Buffer.from('encryption'),\n * 32,\n * );\n *\n * // 4. Encrypt with AES-256-GCM\n * const nonce = secureRandom(12);\n * const ciphertext = AES_GCM.encrypt(key, nonce, Buffer.from('Secret!'));\n *\n * // 5. Decrypt\n * const plaintext = AES_GCM.decrypt(key, nonce, ciphertext);\n * ```\n *\n * ## Security\n *\n * - All primitives use audited Rust crates from RustCrypto / curve25519-dalek\n * - Constant-time operations where applicable\n * - Automatic zeroization of secrets on the Rust side\n * - Test vectors from RFC 5869, RFC 7748, RFC 4231, NIST\n *\n * @packageDocumentation\n */\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Core crypto primitives\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport {\n Curve25519,\n Ed25519,\n XEd25519,\n HKDF,\n AES_GCM,\n AES_CBC,\n HMAC,\n SHA256,\n // NEW in v0.3.0\n ChaCha20Poly1305,\n constantTimeEq,\n nativeSecureRandom,\n CHACHA20_POLY1305_KEY_SIZE,\n CHACHA20_POLY1305_NONCE_SIZE,\n CHACHA20_POLY1305_TAG_SIZE,\n // ────────────────\n nativeVersion,\n} from './core';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Types\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport type {\n KeyPair,\n PublicKey,\n PrivateKey,\n SharedSecret,\n Signature,\n PseudoRandomKey,\n HkdfParams,\n AesGcmParams,\n AesCbcParams,\n Encoding,\n} from './types';\n\nexport {\n asPublicKey,\n asPrivateKey,\n asSharedSecret,\n asSignature,\n} from './types';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Errors\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport {\n SignalisError,\n ValidationError,\n CryptoError,\n AuthenticationError,\n KeyDerivationError,\n SignatureError,\n LengthError,\n} from './errors';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Utilities\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport {\n // Secure random\n secureRandom,\n randomNonce,\n randomIv,\n randomKey,\n // Encoding\n toHex,\n fromHex,\n toBase64,\n fromBase64,\n toBase64Url,\n fromBase64Url,\n bufferToString,\n stringToBuffer,\n // Constant-time\n constantTimeEqual,\n // Buffer manipulation\n concat,\n zeroize,\n xor,\n} from './utils';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Validators (for advanced users building higher-level protocols)\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport {\n assertBuffer,\n assertBufferLength,\n assertBufferOfSize,\n assertPositiveInteger,\n assertHkdfLength,\n buffersSameLength,\n} from './validators';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Constants\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport {\n // Curve25519\n CURVE25519_PRIVATE_KEY_SIZE,\n CURVE25519_PUBLIC_KEY_SIZE,\n CURVE25519_SHARED_SECRET_SIZE,\n // Ed25519 (NEW v0.2.0)\n ED25519_PRIVATE_KEY_SIZE,\n ED25519_PUBLIC_KEY_SIZE,\n ED25519_SIGNATURE_SIZE,\n ED25519_SEED_SIZE,\n // XEd25519 (NEW v0.2.0)\n XED25519_PRIVATE_KEY_SIZE,\n XED25519_PUBLIC_KEY_SIZE,\n XED25519_SIGNATURE_SIZE,\n XED25519_RANDOM_SIZE,\n // HKDF\n HKDF_PRK_SIZE,\n HKDF_MAX_OUTPUT_SIZE,\n // AES\n AES_256_KEY_SIZE,\n AES_256_GCM_NONCE_SIZE,\n AES_256_GCM_TAG_SIZE,\n AES_256_CBC_IV_SIZE,\n AES_BLOCK_SIZE,\n AES_GCM_MAX_PLAINTEXT_SIZE,\n AES_GCM_RECOMMENDED_MESSAGES_PER_KEY,\n // SHA-256 / HMAC\n SHA256_OUTPUT_SIZE,\n HMAC_SHA256_TAG_SIZE,\n SHA256_BLOCK_SIZE,\n} from './constants';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Library version\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * The version of `@brashkie/signalis-core` (matches `package.json`).\n *\n * Bumped on every release.\n */\nexport const VERSION = '0.2.0' as const;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Default export — Convenience namespace\n// ═══════════════════════════════════════════════════════════════════════════\n\nimport { Curve25519, Ed25519, XEd25519, HKDF, AES_GCM, AES_CBC, HMAC, SHA256, nativeVersion } from './core';\nimport {\n secureRandom,\n randomNonce,\n randomIv,\n randomKey,\n toHex,\n fromHex,\n toBase64,\n fromBase64,\n constantTimeEqual,\n} from './utils';\n\n/**\n * Default export — provides all primitives and helpers under one namespace.\n *\n * @example\n * ```ts\n * import sc from '@brashkie/signalis-core';\n *\n * const kp = sc.Curve25519.generateKeyPair();\n * const nonce = sc.secureRandom(12);\n * ```\n */\nconst SignalisCore = Object.freeze({\n // Crypto primitives\n Curve25519,\n Ed25519,\n XEd25519,\n HKDF,\n AES_GCM,\n AES_CBC,\n HMAC,\n SHA256,\n // Random\n secureRandom,\n randomNonce,\n randomIv,\n randomKey,\n // Encoding\n toHex,\n fromHex,\n toBase64,\n fromBase64,\n // Security\n constantTimeEqual,\n // Version\n VERSION: '0.2.0' as const,\n nativeVersion,\n});\n\nexport default SignalisCore;\n"],"mappings":"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","names":["constantTimeEq","secureRandom","secureRandom"]}
|
package/index.d.ts
CHANGED
|
@@ -10,14 +10,49 @@ export interface Curve25519KeyPair {
|
|
|
10
10
|
export declare function curve25519GenerateKeypair(): Curve25519KeyPair
|
|
11
11
|
export declare function curve25519PublicFromPrivate(privateKey: Buffer): Buffer
|
|
12
12
|
export declare function curve25519DiffieHellman(privateKey: Buffer, peerPublicKey: Buffer): Buffer
|
|
13
|
+
export interface Ed25519KeyPair {
|
|
14
|
+
private: Buffer
|
|
15
|
+
public: Buffer
|
|
16
|
+
}
|
|
17
|
+
export declare function ed25519GenerateKeypair(): Ed25519KeyPair
|
|
18
|
+
export declare function ed25519KeypairFromSeed(seed: Buffer): Ed25519KeyPair
|
|
19
|
+
export declare function ed25519PublicFromPrivate(privateKey: Buffer): Buffer
|
|
20
|
+
export declare function ed25519Sign(privateKey: Buffer, message: Buffer): Buffer
|
|
21
|
+
export declare function ed25519Verify(publicKey: Buffer, message: Buffer, signature: Buffer): void
|
|
22
|
+
export declare function ed25519VerifyBool(publicKey: Buffer, message: Buffer, signature: Buffer): boolean
|
|
23
|
+
export declare function xed25519Sign(privateKey: Buffer, message: Buffer): Buffer
|
|
24
|
+
export declare function xed25519SignWithRandom(privateKey: Buffer, message: Buffer, random: Buffer): Buffer
|
|
25
|
+
export declare function xed25519Verify(publicKey: Buffer, message: Buffer, signature: Buffer): void
|
|
26
|
+
export declare function xed25519VerifyBool(publicKey: Buffer, message: Buffer, signature: Buffer): boolean
|
|
13
27
|
export declare function hkdfExtract(salt: Buffer, ikm: Buffer): Buffer
|
|
14
28
|
export declare function hkdfExpand(prk: Buffer, info: Buffer, length: number): Buffer
|
|
15
29
|
export declare function hkdfDerive(salt: Buffer, ikm: Buffer, info: Buffer, length: number): Buffer
|
|
16
30
|
export declare function aes256GcmEncrypt(key: Buffer, nonce: Buffer, plaintext: Buffer): Buffer
|
|
17
31
|
export declare function aes256GcmDecrypt(key: Buffer, nonce: Buffer, ciphertext: Buffer): Buffer
|
|
32
|
+
export declare function aes256GcmEncryptWithAad(key: Buffer, nonce: Buffer, plaintext: Buffer, aad: Buffer): Buffer
|
|
33
|
+
export declare function aes256GcmDecryptWithAad(key: Buffer, nonce: Buffer, ciphertext: Buffer, aad: Buffer): Buffer
|
|
18
34
|
export declare function aes256CbcEncrypt(key: Buffer, iv: Buffer, plaintext: Buffer): Buffer
|
|
19
35
|
export declare function aes256CbcDecrypt(key: Buffer, iv: Buffer, ciphertext: Buffer): Buffer
|
|
20
36
|
export declare function hmacSha256(key: Buffer, data: Buffer): Buffer
|
|
21
37
|
export declare function hmacSha256Verify(key: Buffer, data: Buffer, expectedTag: Buffer): boolean
|
|
22
38
|
export declare function sha256(data: Buffer): Buffer
|
|
39
|
+
export declare function chacha20Poly1305Encrypt(key: Buffer, nonce: Buffer, plaintext: Buffer): Buffer
|
|
40
|
+
export declare function chacha20Poly1305Decrypt(key: Buffer, nonce: Buffer, ciphertext: Buffer): Buffer
|
|
41
|
+
export declare function chacha20Poly1305EncryptWithAad(key: Buffer, nonce: Buffer, plaintext: Buffer, aad: Buffer): Buffer
|
|
42
|
+
export declare function chacha20Poly1305DecryptWithAad(key: Buffer, nonce: Buffer, ciphertext: Buffer, aad: Buffer): Buffer
|
|
43
|
+
/**
|
|
44
|
+
* Generate `size` cryptographically secure random bytes.
|
|
45
|
+
*
|
|
46
|
+
* Backed by the OS random number generator (getrandom/BCryptGenRandom/
|
|
47
|
+
* SecRandomCopyBytes depending on platform).
|
|
48
|
+
*/
|
|
49
|
+
export declare function secureRandom(size: number): Buffer
|
|
50
|
+
/**
|
|
51
|
+
* Compare two buffers in constant time.
|
|
52
|
+
*
|
|
53
|
+
* Returns `true` only if both buffers have identical length AND contents.
|
|
54
|
+
* Use this for comparing MACs, signatures, or any secret value where
|
|
55
|
+
* timing-based comparison could leak information.
|
|
56
|
+
*/
|
|
57
|
+
export declare function constantTimeEq(a: Buffer, b: Buffer): boolean
|
|
23
58
|
export declare function version(): string
|
package/index.js
CHANGED
|
@@ -310,19 +310,37 @@ if (!nativeBinding) {
|
|
|
310
310
|
throw new Error(`Failed to load native binding`)
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
-
const { curve25519GenerateKeypair, curve25519PublicFromPrivate, curve25519DiffieHellman, hkdfExtract, hkdfExpand, hkdfDerive, aes256GcmEncrypt, aes256GcmDecrypt, aes256CbcEncrypt, aes256CbcDecrypt, hmacSha256, hmacSha256Verify, sha256, version } = nativeBinding
|
|
313
|
+
const { curve25519GenerateKeypair, curve25519PublicFromPrivate, curve25519DiffieHellman, ed25519GenerateKeypair, ed25519KeypairFromSeed, ed25519PublicFromPrivate, ed25519Sign, ed25519Verify, ed25519VerifyBool, xed25519Sign, xed25519SignWithRandom, xed25519Verify, xed25519VerifyBool, hkdfExtract, hkdfExpand, hkdfDerive, aes256GcmEncrypt, aes256GcmDecrypt, aes256GcmEncryptWithAad, aes256GcmDecryptWithAad, aes256CbcEncrypt, aes256CbcDecrypt, hmacSha256, hmacSha256Verify, sha256, chacha20Poly1305Encrypt, chacha20Poly1305Decrypt, chacha20Poly1305EncryptWithAad, chacha20Poly1305DecryptWithAad, secureRandom, constantTimeEq, version } = nativeBinding
|
|
314
314
|
|
|
315
315
|
module.exports.curve25519GenerateKeypair = curve25519GenerateKeypair
|
|
316
316
|
module.exports.curve25519PublicFromPrivate = curve25519PublicFromPrivate
|
|
317
317
|
module.exports.curve25519DiffieHellman = curve25519DiffieHellman
|
|
318
|
+
module.exports.ed25519GenerateKeypair = ed25519GenerateKeypair
|
|
319
|
+
module.exports.ed25519KeypairFromSeed = ed25519KeypairFromSeed
|
|
320
|
+
module.exports.ed25519PublicFromPrivate = ed25519PublicFromPrivate
|
|
321
|
+
module.exports.ed25519Sign = ed25519Sign
|
|
322
|
+
module.exports.ed25519Verify = ed25519Verify
|
|
323
|
+
module.exports.ed25519VerifyBool = ed25519VerifyBool
|
|
324
|
+
module.exports.xed25519Sign = xed25519Sign
|
|
325
|
+
module.exports.xed25519SignWithRandom = xed25519SignWithRandom
|
|
326
|
+
module.exports.xed25519Verify = xed25519Verify
|
|
327
|
+
module.exports.xed25519VerifyBool = xed25519VerifyBool
|
|
318
328
|
module.exports.hkdfExtract = hkdfExtract
|
|
319
329
|
module.exports.hkdfExpand = hkdfExpand
|
|
320
330
|
module.exports.hkdfDerive = hkdfDerive
|
|
321
331
|
module.exports.aes256GcmEncrypt = aes256GcmEncrypt
|
|
322
332
|
module.exports.aes256GcmDecrypt = aes256GcmDecrypt
|
|
333
|
+
module.exports.aes256GcmEncryptWithAad = aes256GcmEncryptWithAad
|
|
334
|
+
module.exports.aes256GcmDecryptWithAad = aes256GcmDecryptWithAad
|
|
323
335
|
module.exports.aes256CbcEncrypt = aes256CbcEncrypt
|
|
324
336
|
module.exports.aes256CbcDecrypt = aes256CbcDecrypt
|
|
325
337
|
module.exports.hmacSha256 = hmacSha256
|
|
326
338
|
module.exports.hmacSha256Verify = hmacSha256Verify
|
|
327
339
|
module.exports.sha256 = sha256
|
|
340
|
+
module.exports.chacha20Poly1305Encrypt = chacha20Poly1305Encrypt
|
|
341
|
+
module.exports.chacha20Poly1305Decrypt = chacha20Poly1305Decrypt
|
|
342
|
+
module.exports.chacha20Poly1305EncryptWithAad = chacha20Poly1305EncryptWithAad
|
|
343
|
+
module.exports.chacha20Poly1305DecryptWithAad = chacha20Poly1305DecryptWithAad
|
|
344
|
+
module.exports.secureRandom = secureRandom
|
|
345
|
+
module.exports.constantTimeEq = constantTimeEq
|
|
328
346
|
module.exports.version = version
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brashkie/signalis-core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Cryptographic primitives for Signal Protocol — Rust-powered Node.js library (ESM + CJS + TypeScript)",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Cryptographic primitives for Signal Protocol — Rust-powered Node.js library with Ed25519, XEd25519, Curve25519, HKDF, AES-GCM (with AAD), AES-CBC, ChaCha20-Poly1305, HMAC, SHA-256 (ESM + CJS + TypeScript). Android arm64/armv7 support.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.mjs",
|
|
@@ -37,7 +37,10 @@
|
|
|
37
37
|
"example:cjs": "node examples/cjs-example.cjs",
|
|
38
38
|
"example:esm": "node examples/esm-example.mjs",
|
|
39
39
|
"example:ts": "tsx examples/ts-example.ts",
|
|
40
|
-
"
|
|
40
|
+
"example:signing": "node examples/signing.mjs",
|
|
41
|
+
"example:aad": "node examples/aad.mjs",
|
|
42
|
+
"example:e2e": "node examples/e2e-channel.mjs",
|
|
43
|
+
"examples": "npm run example:cjs && npm run example:esm && npm run example:ts && npm run example:signing && npm run example:aad && npm run example:e2e",
|
|
41
44
|
"lint": "eslint \"src/**/*.ts\" \"__tests__/**/*.ts\"",
|
|
42
45
|
"format": "prettier --write \"src/**/*.{ts,js}\" \"__tests__/**/*.ts\"",
|
|
43
46
|
"format:rust": "cargo fmt --all",
|
|
@@ -53,25 +56,34 @@
|
|
|
53
56
|
"README.es.md",
|
|
54
57
|
"LICENSE",
|
|
55
58
|
"NOTICE",
|
|
56
|
-
"CHANGELOG.md"
|
|
59
|
+
"CHANGELOG.md",
|
|
60
|
+
"MIGRATION.md",
|
|
61
|
+
"SECURITY.md"
|
|
57
62
|
],
|
|
58
63
|
"keywords": [
|
|
59
64
|
"signal-protocol",
|
|
60
65
|
"e2e-encryption",
|
|
61
66
|
"cryptography",
|
|
62
67
|
"curve25519",
|
|
68
|
+
"ed25519",
|
|
69
|
+
"xed25519",
|
|
63
70
|
"x25519",
|
|
71
|
+
"ecdh",
|
|
72
|
+
"diffie-hellman",
|
|
64
73
|
"hkdf",
|
|
65
74
|
"aes-gcm",
|
|
66
75
|
"aes-cbc",
|
|
76
|
+
"aead",
|
|
67
77
|
"hmac",
|
|
68
78
|
"sha256",
|
|
79
|
+
"digital-signature",
|
|
69
80
|
"rust",
|
|
70
81
|
"napi",
|
|
71
82
|
"native",
|
|
72
83
|
"esm",
|
|
73
84
|
"commonjs",
|
|
74
|
-
"dual-package"
|
|
85
|
+
"dual-package",
|
|
86
|
+
"hepein"
|
|
75
87
|
],
|
|
76
88
|
"author": "Brashkie (Hepein)",
|
|
77
89
|
"license": "Apache-2.0",
|
|
@@ -94,32 +106,36 @@
|
|
|
94
106
|
"x86_64-unknown-linux-musl",
|
|
95
107
|
"aarch64-unknown-linux-gnu",
|
|
96
108
|
"aarch64-apple-darwin",
|
|
97
|
-
"aarch64-pc-windows-msvc"
|
|
109
|
+
"aarch64-pc-windows-msvc",
|
|
110
|
+
"aarch64-linux-android",
|
|
111
|
+
"armv7-linux-androideabi"
|
|
98
112
|
]
|
|
99
113
|
}
|
|
100
114
|
},
|
|
101
115
|
"optionalDependencies": {
|
|
102
|
-
"@brashkie/signalis-core-win32-x64-msvc": "0.
|
|
103
|
-
"@brashkie/signalis-core-win32-arm64-msvc": "0.
|
|
104
|
-
"@brashkie/signalis-core-darwin-x64": "0.
|
|
105
|
-
"@brashkie/signalis-core-darwin-arm64": "0.
|
|
106
|
-
"@brashkie/signalis-core-linux-x64-gnu": "0.
|
|
107
|
-
"@brashkie/signalis-core-linux-x64-musl": "0.
|
|
108
|
-
"@brashkie/signalis-core-linux-arm64-gnu": "0.
|
|
116
|
+
"@brashkie/signalis-core-win32-x64-msvc": "0.3.0",
|
|
117
|
+
"@brashkie/signalis-core-win32-arm64-msvc": "0.3.0",
|
|
118
|
+
"@brashkie/signalis-core-darwin-x64": "0.3.0",
|
|
119
|
+
"@brashkie/signalis-core-darwin-arm64": "0.3.0",
|
|
120
|
+
"@brashkie/signalis-core-linux-x64-gnu": "0.3.0",
|
|
121
|
+
"@brashkie/signalis-core-linux-x64-musl": "0.3.0",
|
|
122
|
+
"@brashkie/signalis-core-linux-arm64-gnu": "0.3.0",
|
|
123
|
+
"@brashkie/signalis-core-android-arm64": "0.3.0",
|
|
124
|
+
"@brashkie/signalis-core-android-arm-eabi": "0.3.0"
|
|
109
125
|
},
|
|
110
126
|
"devDependencies": {
|
|
111
127
|
"@napi-rs/cli": "^2.18.4",
|
|
112
|
-
"@types/node": "^
|
|
113
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
114
|
-
"@typescript-eslint/parser": "^
|
|
115
|
-
"@vitest/coverage-v8": "^
|
|
116
|
-
"@vitest/ui": "^
|
|
128
|
+
"@types/node": "^22.0.0",
|
|
129
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
130
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
131
|
+
"@vitest/coverage-v8": "^3.0.0",
|
|
132
|
+
"@vitest/ui": "^3.0.0",
|
|
117
133
|
"cross-env": "^7.0.3",
|
|
118
|
-
"eslint": "^
|
|
119
|
-
"prettier": "^3.
|
|
120
|
-
"tsup": "^8.0
|
|
121
|
-
"tsx": "^4.
|
|
122
|
-
"typescript": "^
|
|
123
|
-
"vitest": "^
|
|
134
|
+
"eslint": "^9.0.0",
|
|
135
|
+
"prettier": "^3.3.0",
|
|
136
|
+
"tsup": "^8.5.0",
|
|
137
|
+
"tsx": "^4.19.0",
|
|
138
|
+
"typescript": "^6.0.3",
|
|
139
|
+
"vitest": "^3.0.0"
|
|
124
140
|
}
|
|
125
|
-
}
|
|
141
|
+
}
|