@happyvertical/encryption 0.80.0 → 0.80.2
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/dist/chunks/base-qiu-WiZ0.js +239 -0
- package/dist/chunks/base-qiu-WiZ0.js.map +1 -0
- package/dist/chunks/nacl-BElkPprm.js +334 -0
- package/dist/chunks/nacl-BElkPprm.js.map +1 -0
- package/dist/chunks/node-Bg7R5Icq.js +421 -0
- package/dist/chunks/node-Bg7R5Icq.js.map +1 -0
- package/dist/chunks/pgp-rwlJTWLC.js +648 -0
- package/dist/chunks/pgp-rwlJTWLC.js.map +1 -0
- package/dist/cli/claude-context.js +17 -17
- package/dist/cli/claude-context.js.map +1 -1
- package/dist/index.js +125 -344
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/dist/chunks/nacl-CoiIhzki.js +0 -454
- package/dist/chunks/nacl-CoiIhzki.js.map +0 -1
- package/dist/chunks/node-nfBpcQQH.js +0 -551
- package/dist/chunks/node-nfBpcQQH.js.map +0 -1
- package/dist/chunks/pgp-BIhtvrNo.js +0 -916
- package/dist/chunks/pgp-BIhtvrNo.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/shared/errors.ts","../src/shared/base.ts","../src/shared/factory.ts"],"sourcesContent":["/**\n * Base error class for all encryption errors\n */\nexport class EncryptionError extends Error {\n public readonly code: string;\n public readonly adapter?: string;\n public readonly cause?: unknown;\n public readonly timestamp: Date;\n\n constructor(\n message: string,\n code: string,\n adapter?: string,\n cause?: unknown,\n ) {\n super(message);\n this.name = 'EncryptionError';\n this.code = code;\n this.adapter = adapter;\n this.cause = cause;\n this.timestamp = new Date();\n\n // Maintains proper stack trace for where error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n /**\n * Convert error to JSON for logging/serialization\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n adapter: this.adapter,\n timestamp: this.timestamp.toISOString(),\n stack: this.stack,\n cause: this.cause,\n };\n }\n}\n\n/**\n * Key-related errors\n */\nexport class KeyError extends EncryptionError {\n constructor(message: string, adapter?: string, cause?: unknown) {\n super(message, 'KEY_ERROR', adapter, cause);\n this.name = 'KeyError';\n }\n}\n\n/**\n * Invalid key format or content\n */\nexport class InvalidKeyError extends EncryptionError {\n constructor(message: string, adapter?: string, cause?: unknown) {\n super(message, 'INVALID_KEY', adapter, cause);\n this.name = 'InvalidKeyError';\n }\n}\n\n/**\n * Key not found error\n */\nexport class KeyNotFoundError extends EncryptionError {\n public readonly keyId?: string;\n\n constructor(message: string, keyId?: string, adapter?: string) {\n super(message, 'KEY_NOT_FOUND', adapter);\n this.name = 'KeyNotFoundError';\n this.keyId = keyId;\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n keyId: this.keyId,\n };\n }\n}\n\n/**\n * Passphrase-related errors\n */\nexport class PassphraseError extends EncryptionError {\n constructor(message: string, adapter?: string, cause?: unknown) {\n super(message, 'PASSPHRASE_ERROR', adapter, cause);\n this.name = 'PassphraseError';\n }\n}\n\n/**\n * Encryption operation errors\n */\nexport class EncryptError extends EncryptionError {\n constructor(message: string, adapter?: string, cause?: unknown) {\n super(message, 'ENCRYPT_ERROR', adapter, cause);\n this.name = 'EncryptError';\n }\n}\n\n/**\n * Decryption operation errors\n */\nexport class DecryptError extends EncryptionError {\n constructor(message: string, adapter?: string, cause?: unknown) {\n super(message, 'DECRYPT_ERROR', adapter, cause);\n this.name = 'DecryptError';\n }\n}\n\n/**\n * Signature operation errors\n */\nexport class SignatureError extends EncryptionError {\n constructor(message: string, adapter?: string, cause?: unknown) {\n super(message, 'SIGNATURE_ERROR', adapter, cause);\n this.name = 'SignatureError';\n }\n}\n\n/**\n * Verification operation errors\n */\nexport class VerificationError extends EncryptionError {\n constructor(message: string, adapter?: string, cause?: unknown) {\n super(message, 'VERIFICATION_ERROR', adapter, cause);\n this.name = 'VerificationError';\n }\n}\n\n/**\n * Format-related errors\n */\nexport class FormatError extends EncryptionError {\n constructor(message: string, adapter?: string, cause?: unknown) {\n super(message, 'FORMAT_ERROR', adapter, cause);\n this.name = 'FormatError';\n }\n}\n\n/**\n * Algorithm-related errors\n */\nexport class AlgorithmError extends EncryptionError {\n public readonly algorithm?: string;\n\n constructor(message: string, algorithm?: string, adapter?: string) {\n super(message, 'ALGORITHM_ERROR', adapter);\n this.name = 'AlgorithmError';\n this.algorithm = algorithm;\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n algorithm: this.algorithm,\n };\n }\n}\n","import { readFile, writeFile } from 'node:fs/promises';\nimport type { Transform } from 'node:stream';\nimport {\n DecryptError,\n EncryptError,\n InvalidKeyError,\n KeyError,\n} from './errors.js';\nimport type {\n AdapterType,\n DecryptEmailOptions,\n DecryptedEmail,\n DecryptOptions,\n EmailMessage,\n EncryptEmailOptions,\n Encryption,\n EncryptionCapabilities,\n EncryptOptions,\n ExportKeyOptions,\n ImportKeyOptions,\n Key,\n KeyPair,\n KeyPairOptions,\n SignEmailOptions,\n SignOptions,\n VerificationResult,\n VerifyEmailOptions,\n VerifyOptions,\n} from './types.js';\n\n/**\n * Base adapter class that provides common functionality for all encryption adapters\n */\nexport abstract class BaseEncryption implements Encryption {\n protected readonly adapterType: AdapterType;\n protected readonly debug: boolean;\n\n constructor(adapterType: AdapterType, debug = false) {\n this.adapterType = adapterType;\n this.debug = debug;\n }\n\n /**\n * Get the adapter type\n */\n getAdapter(): AdapterType {\n return this.adapterType;\n }\n\n /**\n * Log debug messages if debug mode is enabled\n */\n protected log(message: string, ...args: unknown[]): void {\n if (this.debug) {\n console.log(`[${this.adapterType}] ${message}`, ...args);\n }\n }\n\n /**\n * Validate that a key is provided\n */\n protected validateKey(\n key: string | Buffer | Uint8Array | undefined,\n keyType: 'public' | 'private',\n ): void {\n if (!key) {\n throw new KeyError(\n `${keyType} key is required but was not provided`,\n this.adapterType,\n );\n }\n\n if (typeof key === 'string' && key.trim().length === 0) {\n throw new InvalidKeyError(\n `${keyType} key cannot be empty`,\n this.adapterType,\n );\n }\n\n if (Buffer.isBuffer(key) && key.length === 0) {\n throw new InvalidKeyError(\n `${keyType} key cannot be empty`,\n this.adapterType,\n );\n }\n\n if (key instanceof Uint8Array && key.length === 0) {\n throw new InvalidKeyError(\n `${keyType} key cannot be empty`,\n this.adapterType,\n );\n }\n }\n\n /**\n * Validate encryption options\n */\n protected validateEncryptOptions(options?: EncryptOptions): void {\n // Base validation - adapters can override\n if (!options) return;\n\n // Validate encoding if provided\n if (\n options.encoding &&\n !['base64', 'hex', 'utf8'].includes(options.encoding)\n ) {\n throw new Error(\n `Invalid encoding: ${options.encoding}. Must be 'base64', 'hex', or 'utf8'`,\n );\n }\n }\n\n /**\n * Validate decryption options\n */\n protected validateDecryptOptions(options?: DecryptOptions): void {\n // Base validation - adapters can override\n if (!options) return;\n\n // Validate encoding if provided\n if (\n options.encoding &&\n !['base64', 'hex', 'utf8'].includes(options.encoding)\n ) {\n throw new Error(\n `Invalid encoding: ${options.encoding}. Must be 'base64', 'hex', or 'utf8'`,\n );\n }\n }\n\n /**\n * Convert Buffer to string based on encoding\n */\n protected bufferToString(\n buffer: Buffer,\n encoding: 'base64' | 'hex' | 'utf8' = 'base64',\n ): string {\n return buffer.toString(encoding);\n }\n\n /**\n * Convert string to Buffer based on encoding\n */\n protected stringToBuffer(\n str: string,\n encoding: 'base64' | 'hex' | 'utf8' = 'base64',\n ): Buffer {\n return Buffer.from(str, encoding);\n }\n\n /**\n * Wrap errors with adapter context\n */\n protected wrapError(error: unknown, operation: string): Error {\n if (error instanceof Error) {\n return error;\n }\n return new Error(\n `${operation} failed in ${this.adapterType} adapter: ${String(error)}`,\n );\n }\n\n // =============================================================================\n // Text operations (must be implemented by adapters)\n // =============================================================================\n\n abstract encryptText(text: string, options?: EncryptOptions): Promise<string>;\n\n abstract decryptText(\n encrypted: string,\n options?: DecryptOptions,\n ): Promise<string>;\n\n // =============================================================================\n // File operations (default implementation using text/buffer methods)\n // =============================================================================\n\n async encryptFile(\n inputPath: string,\n outputPath: string,\n options?: EncryptOptions,\n ): Promise<void> {\n try {\n this.log(`Encrypting file: ${inputPath} -> ${outputPath}`);\n\n // Read input file\n const input = await readFile(inputPath);\n\n // Encrypt buffer\n const encrypted = await this.encryptBuffer(input, options);\n\n // Write output file\n await writeFile(outputPath, encrypted);\n\n this.log(`File encrypted successfully: ${outputPath}`);\n } catch (error) {\n throw new EncryptError(\n `Failed to encrypt file: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n async decryptFile(\n inputPath: string,\n outputPath: string,\n options?: DecryptOptions,\n ): Promise<void> {\n try {\n this.log(`Decrypting file: ${inputPath} -> ${outputPath}`);\n\n // Read input file\n const input = await readFile(inputPath);\n\n // Decrypt buffer\n const decrypted = await this.decryptBuffer(input, options);\n\n // Write output file\n await writeFile(outputPath, decrypted);\n\n this.log(`File decrypted successfully: ${outputPath}`);\n } catch (error) {\n throw new DecryptError(\n `Failed to decrypt file: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n // =============================================================================\n // Buffer operations (must be implemented by adapters)\n // =============================================================================\n\n abstract encryptBuffer(\n buffer: Buffer,\n options?: EncryptOptions,\n ): Promise<Buffer>;\n\n abstract decryptBuffer(\n buffer: Buffer,\n options?: DecryptOptions,\n ): Promise<Buffer>;\n\n // =============================================================================\n // Stream operations (optional - not implemented by default)\n // =============================================================================\n\n encryptStream?(options?: EncryptOptions): Transform;\n\n decryptStream?(options?: DecryptOptions): Transform;\n\n // =============================================================================\n // Email operations (optional - mainly PGP)\n // =============================================================================\n\n encryptEmail?(\n message: EmailMessage,\n options?: EncryptEmailOptions,\n ): Promise<EmailMessage>;\n\n decryptEmail?(\n message: EmailMessage,\n options?: DecryptEmailOptions,\n ): Promise<DecryptedEmail>;\n\n signEmail?(\n message: EmailMessage,\n options?: SignEmailOptions,\n ): Promise<EmailMessage>;\n\n verifyEmail?(\n message: EmailMessage,\n options?: VerifyEmailOptions,\n ): Promise<VerificationResult>;\n\n // =============================================================================\n // Signing operations (optional - mainly PGP)\n // =============================================================================\n\n sign?(data: string | Buffer, options?: SignOptions): Promise<string | Buffer>;\n\n verify?(\n data: string | Buffer,\n signature: string | Buffer,\n options?: VerifyOptions,\n ): Promise<boolean>;\n\n // =============================================================================\n // Key management (must be implemented by adapters)\n // =============================================================================\n\n abstract generateKeyPair(options?: KeyPairOptions): Promise<KeyPair>;\n\n abstract importKey(\n key: string | Buffer,\n options?: ImportKeyOptions,\n ): Promise<Key>;\n\n abstract exportKey(\n key: Key,\n options?: ExportKeyOptions,\n ): Promise<string | Buffer>;\n\n // =============================================================================\n // Adapter capabilities (must be implemented by adapters)\n // =============================================================================\n\n abstract getCapabilities(): Promise<EncryptionCapabilities>;\n}\n","import type {\n Encryption,\n GetEncryptionOptions,\n NaClOptions,\n NodeCryptoOptions,\n PGPOptions,\n} from './types.js';\n\n/**\n * Type guard to check if options are PGP options\n */\nexport function isPGPOptions(opts: GetEncryptionOptions): opts is PGPOptions {\n return opts.type === 'pgp';\n}\n\n/**\n * Type guard to check if options are NaCl options\n */\nexport function isNaClOptions(opts: GetEncryptionOptions): opts is NaClOptions {\n return opts.type === 'nacl';\n}\n\n/**\n * Type guard to check if options are Node crypto options\n */\nexport function isNodeCryptoOptions(\n opts: GetEncryptionOptions,\n): opts is NodeCryptoOptions {\n return opts.type === 'node';\n}\n\n/**\n * Validate common options\n */\nfunction validateCommonOptions(options: GetEncryptionOptions): void {\n if (!options.type) {\n throw new Error('Encryption adapter type is required');\n }\n\n const validTypes = ['pgp', 'nacl', 'node'];\n if (!validTypes.includes(options.type)) {\n throw new Error(\n `Invalid encryption adapter type: ${options.type}. Must be one of: ${validTypes.join(', ')}`,\n );\n }\n}\n\n/**\n * Validate PGP-specific options\n */\nfunction validatePGPOptions(options: PGPOptions): void {\n // Validate armor option if provided\n if (options.armor !== undefined && typeof options.armor !== 'boolean') {\n throw new Error('PGP armor option must be a boolean');\n }\n\n // Validate compression option if provided\n if (\n options.compression !== undefined &&\n typeof options.compression !== 'boolean'\n ) {\n throw new Error('PGP compression option must be a boolean');\n }\n\n // PGP requires at least one public key or private key for initialization\n // (keys can also be provided per-operation)\n // Keys are optional - adapter can be created without them (e.g., for key generation)\n}\n\n/**\n * Validate NaCl-specific options\n */\nfunction validateNaClOptions(options: NaClOptions): void {\n // Validate encoding option if provided\n if (options.encoding) {\n const validEncodings = ['base64', 'hex', 'utf8'];\n if (!validEncodings.includes(options.encoding)) {\n throw new Error(\n `Invalid NaCl encoding: ${options.encoding}. Must be one of: ${validEncodings.join(', ')}`,\n );\n }\n }\n\n // Validate key formats if provided as strings\n if (typeof options.secretKey === 'string' && options.secretKey.length === 0) {\n throw new Error('NaCl secret key cannot be empty string');\n }\n\n if (typeof options.publicKey === 'string' && options.publicKey.length === 0) {\n throw new Error('NaCl public key cannot be empty string');\n }\n\n // NaCl requires at least a secret key or public key\n // Keys are optional - adapter can be created without them (e.g., for key generation)\n}\n\n/**\n * Validate Node crypto-specific options\n */\nfunction validateNodeCryptoOptions(options: NodeCryptoOptions): void {\n // Algorithm is required\n if (!options.algorithm) {\n throw new Error('Node crypto algorithm is required');\n }\n\n // Validate encoding option if provided\n if (options.encoding) {\n const validEncodings = ['hex', 'base64', 'utf8'];\n if (!validEncodings.includes(options.encoding)) {\n throw new Error(\n `Invalid Node crypto encoding: ${options.encoding}. Must be one of: ${validEncodings.join(', ')}`,\n );\n }\n }\n\n // Validate key derivation options if provided\n if (options.keyDerivation) {\n if (\n !options.keyDerivation.password ||\n options.keyDerivation.password.trim().length === 0\n ) {\n throw new Error('Key derivation password is required');\n }\n\n if (\n options.keyDerivation.iterations !== undefined &&\n options.keyDerivation.iterations < 1000\n ) {\n throw new Error(\n 'Key derivation iterations must be at least 1000 for security',\n );\n }\n\n if (\n options.keyDerivation.keyLength !== undefined &&\n options.keyDerivation.keyLength < 16\n ) {\n throw new Error('Key derivation key length must be at least 16 bytes');\n }\n }\n\n // Validate symmetric vs asymmetric algorithm requirements\n const symmetricAlgorithms = [\n 'aes-256-gcm',\n 'aes-256-cbc',\n 'aes-128-gcm',\n 'aes-128-cbc',\n ];\n const asymmetricAlgorithms = ['rsa', 'rsa-oaep', 'rsa-pss', 'ecdh', 'ecdsa'];\n\n if (symmetricAlgorithms.includes(options.algorithm)) {\n // Symmetric algorithms need a key or key derivation for encryption/decryption\n // Keys are optional - adapter can be created without them (e.g., for key generation)\n } else if (asymmetricAlgorithms.includes(options.algorithm)) {\n // Asymmetric algorithms need public/private keys for encryption/decryption\n // Keys are optional - adapter can be created without them (e.g., for key generation)\n }\n}\n\n/**\n * Factory function to create encryption adapter instances\n *\n * @example\n * ```typescript\n * // PGP\n * const pgp = await getEncryption({\n * type: 'pgp',\n * publicKey: recipientPublicKey,\n * privateKey: myPrivateKey,\n * passphrase: 'my-passphrase'\n * });\n *\n * // NaCl\n * const nacl = await getEncryption({\n * type: 'nacl',\n * secretKey: mySecretKey\n * });\n *\n * // Node crypto\n * const crypto = await getEncryption({\n * type: 'node',\n * algorithm: 'aes-256-gcm',\n * key: encryptionKey\n * });\n * ```\n */\nexport async function getEncryption(\n options: GetEncryptionOptions,\n): Promise<Encryption> {\n // Validate common options\n validateCommonOptions(options);\n\n // Validate and create adapter based on type\n if (isPGPOptions(options)) {\n validatePGPOptions(options);\n\n // Lazy load PGP adapter (reduces initial bundle size)\n const { PGPEncryption } = await import('../adapters/pgp.js');\n return new PGPEncryption(options);\n }\n\n if (isNaClOptions(options)) {\n validateNaClOptions(options);\n\n // Lazy load NaCl adapter\n const { NaClEncryption } = await import('../adapters/nacl.js');\n return new NaClEncryption(options);\n }\n\n if (isNodeCryptoOptions(options)) {\n validateNodeCryptoOptions(options);\n\n // Lazy load Node crypto adapter\n const { NodeCryptoEncryption } = await import('../adapters/node.js');\n return new NodeCryptoEncryption(options);\n }\n\n // This should never happen due to validateCommonOptions, but TypeScript needs it\n throw new Error(\n `Unsupported encryption adapter type: ${(options as GetEncryptionOptions).type}`,\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/shared/factory.ts"],"sourcesContent":["import type {\n Encryption,\n GetEncryptionOptions,\n NaClOptions,\n NodeCryptoOptions,\n PGPOptions,\n} from './types.js';\n\n/**\n * Type guard to check if options are PGP options\n */\nexport function isPGPOptions(opts: GetEncryptionOptions): opts is PGPOptions {\n return opts.type === 'pgp';\n}\n\n/**\n * Type guard to check if options are NaCl options\n */\nexport function isNaClOptions(opts: GetEncryptionOptions): opts is NaClOptions {\n return opts.type === 'nacl';\n}\n\n/**\n * Type guard to check if options are Node crypto options\n */\nexport function isNodeCryptoOptions(\n opts: GetEncryptionOptions,\n): opts is NodeCryptoOptions {\n return opts.type === 'node';\n}\n\n/**\n * Validate common options\n */\nfunction validateCommonOptions(options: GetEncryptionOptions): void {\n if (!options.type) {\n throw new Error('Encryption adapter type is required');\n }\n\n const validTypes = ['pgp', 'nacl', 'node'];\n if (!validTypes.includes(options.type)) {\n throw new Error(\n `Invalid encryption adapter type: ${options.type}. Must be one of: ${validTypes.join(', ')}`,\n );\n }\n}\n\n/**\n * Validate PGP-specific options\n */\nfunction validatePGPOptions(options: PGPOptions): void {\n // Validate armor option if provided\n if (options.armor !== undefined && typeof options.armor !== 'boolean') {\n throw new Error('PGP armor option must be a boolean');\n }\n\n // Validate compression option if provided\n if (\n options.compression !== undefined &&\n typeof options.compression !== 'boolean'\n ) {\n throw new Error('PGP compression option must be a boolean');\n }\n\n // PGP requires at least one public key or private key for initialization\n // (keys can also be provided per-operation)\n // Keys are optional - adapter can be created without them (e.g., for key generation)\n}\n\n/**\n * Validate NaCl-specific options\n */\nfunction validateNaClOptions(options: NaClOptions): void {\n // Validate encoding option if provided\n if (options.encoding) {\n const validEncodings = ['base64', 'hex', 'utf8'];\n if (!validEncodings.includes(options.encoding)) {\n throw new Error(\n `Invalid NaCl encoding: ${options.encoding}. Must be one of: ${validEncodings.join(', ')}`,\n );\n }\n }\n\n // Validate key formats if provided as strings\n if (typeof options.secretKey === 'string' && options.secretKey.length === 0) {\n throw new Error('NaCl secret key cannot be empty string');\n }\n\n if (typeof options.publicKey === 'string' && options.publicKey.length === 0) {\n throw new Error('NaCl public key cannot be empty string');\n }\n\n // NaCl requires at least a secret key or public key\n // Keys are optional - adapter can be created without them (e.g., for key generation)\n}\n\n/**\n * Validate Node crypto-specific options\n */\nfunction validateNodeCryptoOptions(options: NodeCryptoOptions): void {\n // Algorithm is required\n if (!options.algorithm) {\n throw new Error('Node crypto algorithm is required');\n }\n\n // Validate encoding option if provided\n if (options.encoding) {\n const validEncodings = ['hex', 'base64', 'utf8'];\n if (!validEncodings.includes(options.encoding)) {\n throw new Error(\n `Invalid Node crypto encoding: ${options.encoding}. Must be one of: ${validEncodings.join(', ')}`,\n );\n }\n }\n\n // Validate key derivation options if provided\n if (options.keyDerivation) {\n if (\n !options.keyDerivation.password ||\n options.keyDerivation.password.trim().length === 0\n ) {\n throw new Error('Key derivation password is required');\n }\n\n if (\n options.keyDerivation.iterations !== undefined &&\n options.keyDerivation.iterations < 1000\n ) {\n throw new Error(\n 'Key derivation iterations must be at least 1000 for security',\n );\n }\n\n if (\n options.keyDerivation.keyLength !== undefined &&\n options.keyDerivation.keyLength < 16\n ) {\n throw new Error('Key derivation key length must be at least 16 bytes');\n }\n }\n\n // Validate symmetric vs asymmetric algorithm requirements\n const symmetricAlgorithms = [\n 'aes-256-gcm',\n 'aes-256-cbc',\n 'aes-128-gcm',\n 'aes-128-cbc',\n ];\n const asymmetricAlgorithms = ['rsa', 'rsa-oaep', 'rsa-pss', 'ecdh', 'ecdsa'];\n\n if (symmetricAlgorithms.includes(options.algorithm)) {\n // Symmetric algorithms need a key or key derivation for encryption/decryption\n // Keys are optional - adapter can be created without them (e.g., for key generation)\n } else if (asymmetricAlgorithms.includes(options.algorithm)) {\n // Asymmetric algorithms need public/private keys for encryption/decryption\n // Keys are optional - adapter can be created without them (e.g., for key generation)\n }\n}\n\n/**\n * Factory function to create encryption adapter instances\n *\n * @example\n * ```typescript\n * // PGP\n * const pgp = await getEncryption({\n * type: 'pgp',\n * publicKey: recipientPublicKey,\n * privateKey: myPrivateKey,\n * passphrase: 'my-passphrase'\n * });\n *\n * // NaCl\n * const nacl = await getEncryption({\n * type: 'nacl',\n * secretKey: mySecretKey\n * });\n *\n * // Node crypto\n * const crypto = await getEncryption({\n * type: 'node',\n * algorithm: 'aes-256-gcm',\n * key: encryptionKey\n * });\n * ```\n */\nexport async function getEncryption(\n options: GetEncryptionOptions,\n): Promise<Encryption> {\n // Validate common options\n validateCommonOptions(options);\n\n // Validate and create adapter based on type\n if (isPGPOptions(options)) {\n validatePGPOptions(options);\n\n // Lazy load PGP adapter (reduces initial bundle size)\n const { PGPEncryption } = await import('../adapters/pgp.js');\n return new PGPEncryption(options);\n }\n\n if (isNaClOptions(options)) {\n validateNaClOptions(options);\n\n // Lazy load NaCl adapter\n const { NaClEncryption } = await import('../adapters/nacl.js');\n return new NaClEncryption(options);\n }\n\n if (isNodeCryptoOptions(options)) {\n validateNodeCryptoOptions(options);\n\n // Lazy load Node crypto adapter\n const { NodeCryptoEncryption } = await import('../adapters/node.js');\n return new NodeCryptoEncryption(options);\n }\n\n // This should never happen due to validateCommonOptions, but TypeScript needs it\n throw new Error(\n `Unsupported encryption adapter type: ${(options as GetEncryptionOptions).type}`,\n );\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/encryption",
|
|
3
|
-
"version": "0.80.
|
|
3
|
+
"version": "0.80.2",
|
|
4
4
|
"description": "Unified encryption and cryptography operations with adapter-based architecture",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -31,15 +31,15 @@
|
|
|
31
31
|
"openpgp": "^6.3.0",
|
|
32
32
|
"tweetnacl": "^1.0.3",
|
|
33
33
|
"tweetnacl-util": "^0.15.1",
|
|
34
|
-
"@happyvertical/logger": "0.80.
|
|
35
|
-
"@happyvertical/utils": "0.80.
|
|
34
|
+
"@happyvertical/logger": "0.80.2",
|
|
35
|
+
"@happyvertical/utils": "0.80.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "25.0.10",
|
|
39
|
-
"typescript": "
|
|
40
|
-
"vite": "
|
|
39
|
+
"typescript": "5.9.3",
|
|
40
|
+
"vite": "8.1.4",
|
|
41
41
|
"vite-plugin-dts": "4.5.4",
|
|
42
|
-
"vitest": "
|
|
42
|
+
"vitest": "4.1.10"
|
|
43
43
|
},
|
|
44
44
|
"keywords": [
|
|
45
45
|
"encryption",
|
|
@@ -1,454 +0,0 @@
|
|
|
1
|
-
import nacl from "tweetnacl";
|
|
2
|
-
import { decodeBase64, decodeUTF8, encodeBase64, encodeUTF8 } from "tweetnacl-util";
|
|
3
|
-
import { BaseEncryption, InvalidKeyError, EncryptError, DecryptError, KeyError, SignatureError } from "../index.js";
|
|
4
|
-
class NaClEncryption extends BaseEncryption {
|
|
5
|
-
options;
|
|
6
|
-
secretKey;
|
|
7
|
-
publicKey;
|
|
8
|
-
constructor(options) {
|
|
9
|
-
super("nacl", options.debug);
|
|
10
|
-
this.options = options;
|
|
11
|
-
this.initializeKeys();
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Initialize keys from options
|
|
15
|
-
*/
|
|
16
|
-
initializeKeys() {
|
|
17
|
-
const encoding = this.options.encoding || "base64";
|
|
18
|
-
if (this.options.secretKey) {
|
|
19
|
-
this.secretKey = this.parseKey(this.options.secretKey, encoding);
|
|
20
|
-
if (this.secretKey.length !== nacl.secretbox.keyLength) {
|
|
21
|
-
throw new InvalidKeyError(
|
|
22
|
-
`NaCl secret key must be ${nacl.secretbox.keyLength} bytes`,
|
|
23
|
-
this.adapterType
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
if (this.options.publicKey) {
|
|
28
|
-
this.publicKey = this.parseKey(this.options.publicKey, encoding);
|
|
29
|
-
if (this.publicKey.length !== nacl.box.publicKeyLength) {
|
|
30
|
-
throw new InvalidKeyError(
|
|
31
|
-
`NaCl public key must be ${nacl.box.publicKeyLength} bytes`,
|
|
32
|
-
this.adapterType
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Parse key from various formats
|
|
39
|
-
*/
|
|
40
|
-
parseKey(key, encoding) {
|
|
41
|
-
if (key instanceof Uint8Array) {
|
|
42
|
-
return key;
|
|
43
|
-
}
|
|
44
|
-
if (Buffer.isBuffer(key)) {
|
|
45
|
-
return new Uint8Array(key);
|
|
46
|
-
}
|
|
47
|
-
if (typeof key === "string") {
|
|
48
|
-
if (encoding === "base64") {
|
|
49
|
-
return decodeBase64(key);
|
|
50
|
-
}
|
|
51
|
-
if (encoding === "hex") {
|
|
52
|
-
return new Uint8Array(Buffer.from(key, "hex"));
|
|
53
|
-
}
|
|
54
|
-
if (encoding === "utf8") {
|
|
55
|
-
return decodeUTF8(key);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
throw new InvalidKeyError("Invalid key format for NaCl", this.adapterType);
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Format key for output
|
|
62
|
-
*/
|
|
63
|
-
formatKey(key, encoding = "base64") {
|
|
64
|
-
if (encoding === "base64") {
|
|
65
|
-
return encodeBase64(key);
|
|
66
|
-
}
|
|
67
|
-
if (encoding === "hex") {
|
|
68
|
-
return Buffer.from(key).toString("hex");
|
|
69
|
-
}
|
|
70
|
-
if (encoding === "utf8") {
|
|
71
|
-
return encodeUTF8(key);
|
|
72
|
-
}
|
|
73
|
-
return encodeBase64(key);
|
|
74
|
-
}
|
|
75
|
-
async encryptText(text, options) {
|
|
76
|
-
try {
|
|
77
|
-
this.log("Encrypting text", { length: text.length });
|
|
78
|
-
const message = decodeUTF8(text);
|
|
79
|
-
if (options?.recipientPublicKey) {
|
|
80
|
-
return this.encryptAsymmetric(message, options);
|
|
81
|
-
}
|
|
82
|
-
return this.encryptSymmetric(message);
|
|
83
|
-
} catch (error) {
|
|
84
|
-
throw new EncryptError(
|
|
85
|
-
`Failed to encrypt text: ${error.message}`,
|
|
86
|
-
this.adapterType,
|
|
87
|
-
error
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
async decryptText(encrypted, options) {
|
|
92
|
-
try {
|
|
93
|
-
this.log("Decrypting text", { length: encrypted.length });
|
|
94
|
-
const encryptedData = decodeBase64(encrypted);
|
|
95
|
-
const nonceLength = nacl.secretbox.nonceLength;
|
|
96
|
-
const nonce = encryptedData.slice(0, nonceLength);
|
|
97
|
-
const ciphertext = encryptedData.slice(nonceLength);
|
|
98
|
-
let decrypted;
|
|
99
|
-
if (this.publicKey && this.secretKey) {
|
|
100
|
-
if (ciphertext.length > nacl.box.publicKeyLength) {
|
|
101
|
-
const senderPublicKey = ciphertext.slice(0, nacl.box.publicKeyLength);
|
|
102
|
-
const actualCiphertext = ciphertext.slice(nacl.box.publicKeyLength);
|
|
103
|
-
decrypted = nacl.box.open(
|
|
104
|
-
actualCiphertext,
|
|
105
|
-
nonce,
|
|
106
|
-
senderPublicKey,
|
|
107
|
-
this.secretKey
|
|
108
|
-
);
|
|
109
|
-
if (decrypted) {
|
|
110
|
-
this.log("Text decrypted successfully (asymmetric)");
|
|
111
|
-
return encodeUTF8(decrypted);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
if (this.secretKey) {
|
|
116
|
-
decrypted = nacl.secretbox.open(ciphertext, nonce, this.secretKey);
|
|
117
|
-
if (decrypted) {
|
|
118
|
-
this.log("Text decrypted successfully (symmetric)");
|
|
119
|
-
return encodeUTF8(decrypted);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
throw new DecryptError(
|
|
123
|
-
"Decryption failed: invalid key or corrupted ciphertext",
|
|
124
|
-
this.adapterType
|
|
125
|
-
);
|
|
126
|
-
} catch (error) {
|
|
127
|
-
if (error instanceof DecryptError) {
|
|
128
|
-
throw error;
|
|
129
|
-
}
|
|
130
|
-
throw new DecryptError(
|
|
131
|
-
`Failed to decrypt text: ${error.message}`,
|
|
132
|
-
this.adapterType,
|
|
133
|
-
error
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
async encryptBuffer(buffer, options) {
|
|
138
|
-
try {
|
|
139
|
-
this.log("Encrypting buffer", { size: buffer.length });
|
|
140
|
-
const message = new Uint8Array(buffer);
|
|
141
|
-
if (options?.recipientPublicKey) {
|
|
142
|
-
const encrypted2 = this.encryptAsymmetric(message, options);
|
|
143
|
-
return Buffer.from(decodeBase64(encrypted2));
|
|
144
|
-
}
|
|
145
|
-
const encrypted = this.encryptSymmetric(message);
|
|
146
|
-
return Buffer.from(decodeBase64(encrypted));
|
|
147
|
-
} catch (error) {
|
|
148
|
-
throw new EncryptError(
|
|
149
|
-
`Failed to encrypt buffer: ${error.message}`,
|
|
150
|
-
this.adapterType,
|
|
151
|
-
error
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
async decryptBuffer(buffer, options) {
|
|
156
|
-
try {
|
|
157
|
-
this.log("Decrypting buffer", { size: buffer.length });
|
|
158
|
-
const decoded = decodeBase64(buffer.toString("base64"));
|
|
159
|
-
const nonce = decoded.slice(0, nacl.secretbox.nonceLength);
|
|
160
|
-
const ciphertext = decoded.slice(nacl.secretbox.nonceLength);
|
|
161
|
-
let decrypted = null;
|
|
162
|
-
if (this.publicKey && this.secretKey) {
|
|
163
|
-
if (ciphertext.length > nacl.box.publicKeyLength) {
|
|
164
|
-
const senderPublicKey = ciphertext.slice(0, nacl.box.publicKeyLength);
|
|
165
|
-
const actualCiphertext = ciphertext.slice(nacl.box.publicKeyLength);
|
|
166
|
-
decrypted = nacl.box.open(
|
|
167
|
-
actualCiphertext,
|
|
168
|
-
nonce,
|
|
169
|
-
senderPublicKey,
|
|
170
|
-
this.secretKey
|
|
171
|
-
);
|
|
172
|
-
if (decrypted) {
|
|
173
|
-
this.log("Buffer decrypted successfully (asymmetric)");
|
|
174
|
-
return Buffer.from(decrypted);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (this.secretKey) {
|
|
179
|
-
decrypted = nacl.secretbox.open(ciphertext, nonce, this.secretKey);
|
|
180
|
-
if (decrypted) {
|
|
181
|
-
this.log("Buffer decrypted successfully (symmetric)");
|
|
182
|
-
return Buffer.from(decrypted);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
throw new DecryptError(
|
|
186
|
-
"Decryption failed: invalid key or corrupted ciphertext",
|
|
187
|
-
this.adapterType
|
|
188
|
-
);
|
|
189
|
-
} catch (error) {
|
|
190
|
-
if (error instanceof DecryptError) {
|
|
191
|
-
throw error;
|
|
192
|
-
}
|
|
193
|
-
throw new DecryptError(
|
|
194
|
-
`Failed to decrypt buffer: ${error.message}`,
|
|
195
|
-
this.adapterType,
|
|
196
|
-
error
|
|
197
|
-
);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Symmetric encryption using secretbox
|
|
202
|
-
*/
|
|
203
|
-
encryptSymmetric(message) {
|
|
204
|
-
if (!this.secretKey) {
|
|
205
|
-
throw new KeyError(
|
|
206
|
-
"Secret key required for symmetric encryption",
|
|
207
|
-
this.adapterType
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);
|
|
211
|
-
const ciphertext = nacl.secretbox(message, nonce, this.secretKey);
|
|
212
|
-
const encrypted = new Uint8Array(nonce.length + ciphertext.length);
|
|
213
|
-
encrypted.set(nonce);
|
|
214
|
-
encrypted.set(ciphertext, nonce.length);
|
|
215
|
-
return encodeBase64(encrypted);
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Asymmetric encryption using box
|
|
219
|
-
*/
|
|
220
|
-
encryptAsymmetric(message, options) {
|
|
221
|
-
if (!this.secretKey) {
|
|
222
|
-
throw new KeyError(
|
|
223
|
-
"Secret key required for asymmetric encryption",
|
|
224
|
-
this.adapterType
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
const recipientPublicKey = this.parseKey(
|
|
228
|
-
options.recipientPublicKey,
|
|
229
|
-
this.options.encoding || "base64"
|
|
230
|
-
);
|
|
231
|
-
if (recipientPublicKey.length !== nacl.box.publicKeyLength) {
|
|
232
|
-
throw new InvalidKeyError(
|
|
233
|
-
`Recipient public key must be ${nacl.box.publicKeyLength} bytes`,
|
|
234
|
-
this.adapterType
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
const nonce = nacl.randomBytes(nacl.box.nonceLength);
|
|
238
|
-
const ciphertext = nacl.box(
|
|
239
|
-
message,
|
|
240
|
-
nonce,
|
|
241
|
-
recipientPublicKey,
|
|
242
|
-
this.secretKey
|
|
243
|
-
);
|
|
244
|
-
const senderPublicKey = this.publicKey || nacl.box.keyPair.fromSecretKey(this.secretKey).publicKey;
|
|
245
|
-
const encrypted = new Uint8Array(
|
|
246
|
-
nonce.length + senderPublicKey.length + ciphertext.length
|
|
247
|
-
);
|
|
248
|
-
encrypted.set(nonce);
|
|
249
|
-
encrypted.set(senderPublicKey, nonce.length);
|
|
250
|
-
encrypted.set(ciphertext, nonce.length + senderPublicKey.length);
|
|
251
|
-
return encodeBase64(encrypted);
|
|
252
|
-
}
|
|
253
|
-
async generateKeyPair(options) {
|
|
254
|
-
try {
|
|
255
|
-
this.log("Generating NaCl key pair", options);
|
|
256
|
-
const keyType = options?.type || "box";
|
|
257
|
-
if (keyType === "box" || keyType === "ecdh") {
|
|
258
|
-
const keypair = nacl.box.keyPair();
|
|
259
|
-
this.log("Encryption key pair generated");
|
|
260
|
-
return {
|
|
261
|
-
publicKey: keypair.publicKey,
|
|
262
|
-
privateKey: keypair.secretKey
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
if (keyType === "ecdsa") {
|
|
266
|
-
const keypair = nacl.sign.keyPair();
|
|
267
|
-
this.log("Signing key pair generated");
|
|
268
|
-
return {
|
|
269
|
-
publicKey: keypair.publicKey,
|
|
270
|
-
privateKey: keypair.secretKey
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
throw new KeyError(
|
|
274
|
-
`Unsupported key type for NaCl: ${keyType}. Use 'box' for encryption or 'sign' for signatures.`,
|
|
275
|
-
this.adapterType
|
|
276
|
-
);
|
|
277
|
-
} catch (error) {
|
|
278
|
-
throw new KeyError(
|
|
279
|
-
`Failed to generate NaCl key pair: ${error.message}`,
|
|
280
|
-
this.adapterType,
|
|
281
|
-
error
|
|
282
|
-
);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
async importKey(key, options) {
|
|
286
|
-
try {
|
|
287
|
-
this.log("Importing NaCl key");
|
|
288
|
-
const encoding = this.options.encoding || "base64";
|
|
289
|
-
const keyData = typeof key === "string" ? key : key.toString(encoding);
|
|
290
|
-
const keyBytes = this.parseKey(keyData, encoding);
|
|
291
|
-
const keyType = options?.type || "public";
|
|
292
|
-
const format = options?.format || "armored";
|
|
293
|
-
const expectedLength = keyType === "public" ? nacl.box.publicKeyLength : nacl.box.secretKeyLength;
|
|
294
|
-
if (keyBytes.length !== expectedLength) {
|
|
295
|
-
throw new InvalidKeyError(
|
|
296
|
-
`NaCl ${keyType} key must be ${expectedLength} bytes`,
|
|
297
|
-
this.adapterType
|
|
298
|
-
);
|
|
299
|
-
}
|
|
300
|
-
this.log("Key imported successfully");
|
|
301
|
-
return {
|
|
302
|
-
type: keyType,
|
|
303
|
-
format,
|
|
304
|
-
data: keyData,
|
|
305
|
-
algorithm: "nacl"
|
|
306
|
-
};
|
|
307
|
-
} catch (error) {
|
|
308
|
-
throw new InvalidKeyError(
|
|
309
|
-
`Failed to import NaCl key: ${error.message}`,
|
|
310
|
-
this.adapterType,
|
|
311
|
-
error
|
|
312
|
-
);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
async exportKey(key, options) {
|
|
316
|
-
try {
|
|
317
|
-
this.log("Exporting NaCl key");
|
|
318
|
-
const format = options?.format || key.format || "armored";
|
|
319
|
-
const encoding = this.options.encoding || "base64";
|
|
320
|
-
if (typeof key.data === "string") {
|
|
321
|
-
if (format === "binary") {
|
|
322
|
-
return Buffer.from(key.data, encoding);
|
|
323
|
-
}
|
|
324
|
-
return key.data;
|
|
325
|
-
}
|
|
326
|
-
if (Buffer.isBuffer(key.data)) {
|
|
327
|
-
if (format === "armored") {
|
|
328
|
-
return key.data.toString(encoding);
|
|
329
|
-
}
|
|
330
|
-
return key.data;
|
|
331
|
-
}
|
|
332
|
-
if (key.data instanceof Uint8Array) {
|
|
333
|
-
if (format === "binary") {
|
|
334
|
-
return Buffer.from(key.data);
|
|
335
|
-
}
|
|
336
|
-
return this.formatKey(key.data, encoding);
|
|
337
|
-
}
|
|
338
|
-
throw new InvalidKeyError(
|
|
339
|
-
"Invalid key data format for export",
|
|
340
|
-
this.adapterType
|
|
341
|
-
);
|
|
342
|
-
} catch (error) {
|
|
343
|
-
throw new KeyError(
|
|
344
|
-
`Failed to export NaCl key: ${error.message}`,
|
|
345
|
-
this.adapterType,
|
|
346
|
-
error
|
|
347
|
-
);
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Sign data with signing key
|
|
352
|
-
*/
|
|
353
|
-
async sign(data, options) {
|
|
354
|
-
try {
|
|
355
|
-
this.log("Signing data");
|
|
356
|
-
let signingKey;
|
|
357
|
-
if (options?.privateKey) {
|
|
358
|
-
signingKey = this.parseKey(
|
|
359
|
-
options.privateKey,
|
|
360
|
-
this.options.encoding || "base64"
|
|
361
|
-
);
|
|
362
|
-
} else if (this.secretKey) {
|
|
363
|
-
signingKey = this.secretKey;
|
|
364
|
-
} else {
|
|
365
|
-
throw new KeyError("No signing key available", this.adapterType);
|
|
366
|
-
}
|
|
367
|
-
if (signingKey.length !== nacl.sign.secretKeyLength) {
|
|
368
|
-
throw new InvalidKeyError(
|
|
369
|
-
`NaCl signing key must be ${nacl.sign.secretKeyLength} bytes`,
|
|
370
|
-
this.adapterType
|
|
371
|
-
);
|
|
372
|
-
}
|
|
373
|
-
const message = typeof data === "string" ? decodeUTF8(data) : new Uint8Array(data);
|
|
374
|
-
const signed = nacl.sign(message, signingKey);
|
|
375
|
-
this.log("Data signed successfully");
|
|
376
|
-
if (typeof data === "string") {
|
|
377
|
-
return encodeBase64(signed);
|
|
378
|
-
}
|
|
379
|
-
return Buffer.from(signed);
|
|
380
|
-
} catch (error) {
|
|
381
|
-
throw new SignatureError(
|
|
382
|
-
`Failed to sign data: ${error.message}`,
|
|
383
|
-
this.adapterType,
|
|
384
|
-
error
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Verify signature
|
|
390
|
-
*/
|
|
391
|
-
async verify(data, signature, options) {
|
|
392
|
-
try {
|
|
393
|
-
this.log("Verifying signature");
|
|
394
|
-
if (!options?.publicKey) {
|
|
395
|
-
throw new KeyError(
|
|
396
|
-
"Public key required for signature verification",
|
|
397
|
-
this.adapterType
|
|
398
|
-
);
|
|
399
|
-
}
|
|
400
|
-
const verificationKey = this.parseKey(
|
|
401
|
-
options.publicKey,
|
|
402
|
-
this.options.encoding || "base64"
|
|
403
|
-
);
|
|
404
|
-
if (verificationKey.length !== nacl.sign.publicKeyLength) {
|
|
405
|
-
throw new InvalidKeyError(
|
|
406
|
-
`NaCl verification key must be ${nacl.sign.publicKeyLength} bytes`,
|
|
407
|
-
this.adapterType
|
|
408
|
-
);
|
|
409
|
-
}
|
|
410
|
-
const signedMessage = typeof signature === "string" ? decodeBase64(signature) : new Uint8Array(signature);
|
|
411
|
-
const verified = nacl.sign.open(signedMessage, verificationKey);
|
|
412
|
-
if (!verified) {
|
|
413
|
-
this.log("Signature verification failed");
|
|
414
|
-
return false;
|
|
415
|
-
}
|
|
416
|
-
const originalMessage = typeof data === "string" ? decodeUTF8(data) : new Uint8Array(data);
|
|
417
|
-
if (verified.length !== originalMessage.length) {
|
|
418
|
-
this.log("Signature verification failed: message mismatch");
|
|
419
|
-
return false;
|
|
420
|
-
}
|
|
421
|
-
for (let i = 0; i < verified.length; i++) {
|
|
422
|
-
if (verified[i] !== originalMessage[i]) {
|
|
423
|
-
this.log("Signature verification failed: message mismatch");
|
|
424
|
-
return false;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
this.log("Signature verified successfully");
|
|
428
|
-
return true;
|
|
429
|
-
} catch (error) {
|
|
430
|
-
this.log("Signature verification failed", error);
|
|
431
|
-
return false;
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
async getCapabilities() {
|
|
435
|
-
return {
|
|
436
|
-
textEncryption: true,
|
|
437
|
-
fileEncryption: true,
|
|
438
|
-
bufferEncryption: true,
|
|
439
|
-
streamEncryption: false,
|
|
440
|
-
emailEncryption: false,
|
|
441
|
-
signing: true,
|
|
442
|
-
verification: true,
|
|
443
|
-
keyGeneration: true,
|
|
444
|
-
keyManagement: true,
|
|
445
|
-
multipleRecipients: false,
|
|
446
|
-
symmetricEncryption: true,
|
|
447
|
-
asymmetricEncryption: true
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
export {
|
|
452
|
-
NaClEncryption
|
|
453
|
-
};
|
|
454
|
-
//# sourceMappingURL=nacl-CoiIhzki.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nacl-CoiIhzki.js","sources":["../../src/adapters/nacl.ts"],"sourcesContent":["import nacl from 'tweetnacl';\nimport {\n decodeBase64,\n decodeUTF8,\n encodeBase64,\n encodeUTF8,\n} from 'tweetnacl-util';\nimport { BaseEncryption } from '../shared/base.js';\nimport {\n DecryptError,\n EncryptError,\n InvalidKeyError,\n KeyError,\n SignatureError,\n} from '../shared/errors.js';\nimport type {\n DecryptOptions,\n EncryptionCapabilities,\n EncryptOptions,\n ExportKeyOptions,\n ImportKeyOptions,\n Key,\n KeyPair,\n KeyPairOptions,\n NaClOptions,\n SignOptions,\n VerifyOptions,\n} from '../shared/types.js';\n\n/**\n * NaCl/TweetNaCl encryption adapter\n *\n * Provides fast, modern cryptography using the NaCl library.\n * Supports both symmetric (secretbox) and asymmetric (box) encryption.\n *\n * @example\n * ```typescript\n * // Symmetric encryption\n * const nacl = new NaClEncryption({\n * type: 'nacl',\n * secretKey: secretKey\n * });\n *\n * const encrypted = await nacl.encryptText('Secret message');\n * const decrypted = await nacl.decryptText(encrypted);\n *\n * // Asymmetric encryption\n * const nacl = new NaClEncryption({\n * type: 'nacl',\n * publicKey: theirPublicKey,\n * secretKey: mySecretKey\n * });\n *\n * const encrypted = await nacl.encryptText('Secret message', {\n * recipientPublicKey: theirPublicKey\n * });\n * const decrypted = await nacl.decryptText(encrypted);\n * ```\n */\nexport class NaClEncryption extends BaseEncryption {\n private options: NaClOptions;\n private secretKey?: Uint8Array;\n private publicKey?: Uint8Array;\n\n constructor(options: NaClOptions) {\n super('nacl', options.debug);\n this.options = options;\n this.initializeKeys();\n }\n\n /**\n * Initialize keys from options\n */\n private initializeKeys(): void {\n const encoding = this.options.encoding || 'base64';\n\n // Initialize secret key for symmetric encryption\n if (this.options.secretKey) {\n this.secretKey = this.parseKey(this.options.secretKey, encoding);\n if (this.secretKey.length !== nacl.secretbox.keyLength) {\n throw new InvalidKeyError(\n `NaCl secret key must be ${nacl.secretbox.keyLength} bytes`,\n this.adapterType,\n );\n }\n }\n\n // Initialize public key for asymmetric encryption\n if (this.options.publicKey) {\n this.publicKey = this.parseKey(this.options.publicKey, encoding);\n if (this.publicKey.length !== nacl.box.publicKeyLength) {\n throw new InvalidKeyError(\n `NaCl public key must be ${nacl.box.publicKeyLength} bytes`,\n this.adapterType,\n );\n }\n }\n }\n\n /**\n * Parse key from various formats\n */\n private parseKey(\n key: Uint8Array | Buffer | string,\n encoding: 'base64' | 'hex' | 'utf8',\n ): Uint8Array {\n if (key instanceof Uint8Array) {\n return key;\n }\n\n if (Buffer.isBuffer(key)) {\n return new Uint8Array(key);\n }\n\n if (typeof key === 'string') {\n if (encoding === 'base64') {\n return decodeBase64(key);\n }\n if (encoding === 'hex') {\n return new Uint8Array(Buffer.from(key, 'hex'));\n }\n if (encoding === 'utf8') {\n return decodeUTF8(key);\n }\n }\n\n throw new InvalidKeyError('Invalid key format for NaCl', this.adapterType);\n }\n\n /**\n * Format key for output\n */\n private formatKey(\n key: Uint8Array,\n encoding: 'base64' | 'hex' | 'utf8' = 'base64',\n ): string {\n if (encoding === 'base64') {\n return encodeBase64(key);\n }\n if (encoding === 'hex') {\n return Buffer.from(key).toString('hex');\n }\n if (encoding === 'utf8') {\n return encodeUTF8(key);\n }\n return encodeBase64(key);\n }\n\n async encryptText(text: string, options?: EncryptOptions): Promise<string> {\n try {\n this.log('Encrypting text', { length: text.length });\n\n const message = decodeUTF8(text);\n\n // Check if asymmetric or symmetric encryption\n if (options?.recipientPublicKey) {\n // Asymmetric encryption (box)\n return this.encryptAsymmetric(message, options);\n }\n\n // Symmetric encryption (secretbox)\n return this.encryptSymmetric(message);\n } catch (error) {\n throw new EncryptError(\n `Failed to encrypt text: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n async decryptText(\n encrypted: string,\n options?: DecryptOptions,\n ): Promise<string> {\n try {\n this.log('Decrypting text', { length: encrypted.length });\n\n // Decode the encrypted message\n const encryptedData = decodeBase64(encrypted);\n\n // Extract nonce and ciphertext\n const nonceLength = nacl.secretbox.nonceLength;\n const nonce = encryptedData.slice(0, nonceLength);\n const ciphertext = encryptedData.slice(nonceLength);\n\n let decrypted: Uint8Array | null;\n\n // Try asymmetric decryption first if we have keys\n if (this.publicKey && this.secretKey) {\n // Check if there's a public key in the message (for box)\n if (ciphertext.length > nacl.box.publicKeyLength) {\n const senderPublicKey = ciphertext.slice(0, nacl.box.publicKeyLength);\n const actualCiphertext = ciphertext.slice(nacl.box.publicKeyLength);\n\n decrypted = nacl.box.open(\n actualCiphertext,\n nonce,\n senderPublicKey,\n this.secretKey,\n );\n\n if (decrypted) {\n this.log('Text decrypted successfully (asymmetric)');\n return encodeUTF8(decrypted);\n }\n }\n }\n\n // Try symmetric decryption\n if (this.secretKey) {\n decrypted = nacl.secretbox.open(ciphertext, nonce, this.secretKey);\n\n if (decrypted) {\n this.log('Text decrypted successfully (symmetric)');\n return encodeUTF8(decrypted);\n }\n }\n\n throw new DecryptError(\n 'Decryption failed: invalid key or corrupted ciphertext',\n this.adapterType,\n );\n } catch (error) {\n if (error instanceof DecryptError) {\n throw error;\n }\n throw new DecryptError(\n `Failed to decrypt text: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n async encryptBuffer(\n buffer: Buffer,\n options?: EncryptOptions,\n ): Promise<Buffer> {\n try {\n this.log('Encrypting buffer', { size: buffer.length });\n\n const message = new Uint8Array(buffer);\n\n // Check if asymmetric or symmetric encryption\n if (options?.recipientPublicKey) {\n // Asymmetric encryption (box)\n const encrypted = this.encryptAsymmetric(message, options);\n return Buffer.from(decodeBase64(encrypted));\n }\n\n // Symmetric encryption (secretbox)\n const encrypted = this.encryptSymmetric(message);\n return Buffer.from(decodeBase64(encrypted));\n } catch (error) {\n throw new EncryptError(\n `Failed to encrypt buffer: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n async decryptBuffer(\n buffer: Buffer,\n options?: DecryptOptions,\n ): Promise<Buffer> {\n try {\n this.log('Decrypting buffer', { size: buffer.length });\n\n // Decode the base64 buffer\n const decoded = decodeBase64(buffer.toString('base64'));\n\n // Extract nonce and ciphertext\n const nonce = decoded.slice(0, nacl.secretbox.nonceLength);\n const ciphertext = decoded.slice(nacl.secretbox.nonceLength);\n\n let decrypted: Uint8Array | null = null;\n\n // Try asymmetric decryption first if we have keys\n if (this.publicKey && this.secretKey) {\n // Check if there's a public key in the message (for box)\n if (ciphertext.length > nacl.box.publicKeyLength) {\n const senderPublicKey = ciphertext.slice(0, nacl.box.publicKeyLength);\n const actualCiphertext = ciphertext.slice(nacl.box.publicKeyLength);\n\n decrypted = nacl.box.open(\n actualCiphertext,\n nonce,\n senderPublicKey,\n this.secretKey,\n );\n\n if (decrypted) {\n this.log('Buffer decrypted successfully (asymmetric)');\n return Buffer.from(decrypted);\n }\n }\n }\n\n // Try symmetric decryption\n if (this.secretKey) {\n decrypted = nacl.secretbox.open(ciphertext, nonce, this.secretKey);\n\n if (decrypted) {\n this.log('Buffer decrypted successfully (symmetric)');\n return Buffer.from(decrypted);\n }\n }\n\n throw new DecryptError(\n 'Decryption failed: invalid key or corrupted ciphertext',\n this.adapterType,\n );\n } catch (error) {\n if (error instanceof DecryptError) {\n throw error;\n }\n throw new DecryptError(\n `Failed to decrypt buffer: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n /**\n * Symmetric encryption using secretbox\n */\n private encryptSymmetric(message: Uint8Array): string {\n if (!this.secretKey) {\n throw new KeyError(\n 'Secret key required for symmetric encryption',\n this.adapterType,\n );\n }\n\n // Generate random nonce\n const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);\n\n // Encrypt the message\n const ciphertext = nacl.secretbox(message, nonce, this.secretKey);\n\n // Combine nonce and ciphertext\n const encrypted = new Uint8Array(nonce.length + ciphertext.length);\n encrypted.set(nonce);\n encrypted.set(ciphertext, nonce.length);\n\n return encodeBase64(encrypted);\n }\n\n /**\n * Asymmetric encryption using box\n */\n private encryptAsymmetric(\n message: Uint8Array,\n options: EncryptOptions,\n ): string {\n if (!this.secretKey) {\n throw new KeyError(\n 'Secret key required for asymmetric encryption',\n this.adapterType,\n );\n }\n\n // Get recipient public key\n const recipientPublicKey = this.parseKey(\n options.recipientPublicKey as string | Uint8Array | Buffer,\n this.options.encoding || 'base64',\n );\n\n if (recipientPublicKey.length !== nacl.box.publicKeyLength) {\n throw new InvalidKeyError(\n `Recipient public key must be ${nacl.box.publicKeyLength} bytes`,\n this.adapterType,\n );\n }\n\n // Generate random nonce\n const nonce = nacl.randomBytes(nacl.box.nonceLength);\n\n // Encrypt the message\n const ciphertext = nacl.box(\n message,\n nonce,\n recipientPublicKey,\n this.secretKey,\n );\n\n // Include sender's public key in the message\n const senderPublicKey =\n this.publicKey ||\n nacl.box.keyPair.fromSecretKey(this.secretKey).publicKey;\n\n // Combine nonce, sender public key, and ciphertext\n const encrypted = new Uint8Array(\n nonce.length + senderPublicKey.length + ciphertext.length,\n );\n encrypted.set(nonce);\n encrypted.set(senderPublicKey, nonce.length);\n encrypted.set(ciphertext, nonce.length + senderPublicKey.length);\n\n return encodeBase64(encrypted);\n }\n\n async generateKeyPair(options?: KeyPairOptions): Promise<KeyPair> {\n try {\n this.log('Generating NaCl key pair', options);\n\n const keyType = options?.type || 'box';\n\n if (keyType === 'box' || keyType === 'ecdh') {\n // Generate encryption keypair\n const keypair = nacl.box.keyPair();\n\n this.log('Encryption key pair generated');\n\n return {\n publicKey: keypair.publicKey,\n privateKey: keypair.secretKey,\n };\n }\n\n if (keyType === 'ecdsa') {\n // Generate signing keypair\n const keypair = nacl.sign.keyPair();\n\n this.log('Signing key pair generated');\n\n return {\n publicKey: keypair.publicKey,\n privateKey: keypair.secretKey,\n };\n }\n\n throw new KeyError(\n `Unsupported key type for NaCl: ${keyType}. Use 'box' for encryption or 'sign' for signatures.`,\n this.adapterType,\n );\n } catch (error) {\n throw new KeyError(\n `Failed to generate NaCl key pair: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n async importKey(\n key: string | Buffer,\n options?: ImportKeyOptions,\n ): Promise<Key> {\n try {\n this.log('Importing NaCl key');\n\n const encoding = this.options.encoding || 'base64';\n const keyData = typeof key === 'string' ? key : key.toString(encoding);\n const keyBytes = this.parseKey(keyData, encoding);\n\n const keyType = options?.type || 'public';\n const format = (options?.format || 'armored') as\n | 'armored'\n | 'binary'\n | 'pem'\n | 'der';\n\n // Validate key length\n const expectedLength =\n keyType === 'public'\n ? nacl.box.publicKeyLength\n : nacl.box.secretKeyLength;\n\n if (keyBytes.length !== expectedLength) {\n throw new InvalidKeyError(\n `NaCl ${keyType} key must be ${expectedLength} bytes`,\n this.adapterType,\n );\n }\n\n this.log('Key imported successfully');\n\n return {\n type: keyType as 'public' | 'private',\n format,\n data: keyData,\n algorithm: 'nacl',\n };\n } catch (error) {\n throw new InvalidKeyError(\n `Failed to import NaCl key: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n async exportKey(\n key: Key,\n options?: ExportKeyOptions,\n ): Promise<string | Buffer> {\n try {\n this.log('Exporting NaCl key');\n\n const format = options?.format || key.format || 'armored';\n // Use NaCl encoding from options or default\n const encoding = this.options.encoding || 'base64';\n\n if (typeof key.data === 'string') {\n if (format === 'binary') {\n return Buffer.from(key.data, encoding);\n }\n return key.data;\n }\n\n if (Buffer.isBuffer(key.data)) {\n if (format === 'armored') {\n return key.data.toString(encoding);\n }\n return key.data;\n }\n\n if (key.data instanceof Uint8Array) {\n if (format === 'binary') {\n return Buffer.from(key.data);\n }\n return this.formatKey(key.data, encoding);\n }\n\n throw new InvalidKeyError(\n 'Invalid key data format for export',\n this.adapterType,\n );\n } catch (error) {\n throw new KeyError(\n `Failed to export NaCl key: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n /**\n * Sign data with signing key\n */\n async sign(\n data: string | Buffer,\n options?: SignOptions,\n ): Promise<string | Buffer> {\n try {\n this.log('Signing data');\n\n // Get signing key\n let signingKey: Uint8Array;\n\n if (options?.privateKey) {\n signingKey = this.parseKey(\n options.privateKey,\n this.options.encoding || 'base64',\n );\n } else if (this.secretKey) {\n signingKey = this.secretKey;\n } else {\n throw new KeyError('No signing key available', this.adapterType);\n }\n\n // Validate key length for signing\n if (signingKey.length !== nacl.sign.secretKeyLength) {\n throw new InvalidKeyError(\n `NaCl signing key must be ${nacl.sign.secretKeyLength} bytes`,\n this.adapterType,\n );\n }\n\n // Prepare message\n const message =\n typeof data === 'string' ? decodeUTF8(data) : new Uint8Array(data);\n\n // Sign the message\n const signed = nacl.sign(message, signingKey);\n\n this.log('Data signed successfully');\n\n if (typeof data === 'string') {\n return encodeBase64(signed);\n }\n\n return Buffer.from(signed);\n } catch (error) {\n throw new SignatureError(\n `Failed to sign data: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n /**\n * Verify signature\n */\n async verify(\n data: string | Buffer,\n signature: string | Buffer,\n options?: VerifyOptions,\n ): Promise<boolean> {\n try {\n this.log('Verifying signature');\n\n if (!options?.publicKey) {\n throw new KeyError(\n 'Public key required for signature verification',\n this.adapterType,\n );\n }\n\n // Get verification key\n const verificationKey = this.parseKey(\n options.publicKey,\n this.options.encoding || 'base64',\n );\n\n // Validate key length\n if (verificationKey.length !== nacl.sign.publicKeyLength) {\n throw new InvalidKeyError(\n `NaCl verification key must be ${nacl.sign.publicKeyLength} bytes`,\n this.adapterType,\n );\n }\n\n // Parse signed message\n const signedMessage =\n typeof signature === 'string'\n ? decodeBase64(signature)\n : new Uint8Array(signature);\n\n // Verify and open the signed message (extracts original message)\n const verified = nacl.sign.open(signedMessage, verificationKey);\n\n if (!verified) {\n this.log('Signature verification failed');\n return false;\n }\n\n // Compare extracted message with provided data\n const originalMessage =\n typeof data === 'string' ? decodeUTF8(data) : new Uint8Array(data);\n\n // Check if messages match\n if (verified.length !== originalMessage.length) {\n this.log('Signature verification failed: message mismatch');\n return false;\n }\n\n for (let i = 0; i < verified.length; i++) {\n if (verified[i] !== originalMessage[i]) {\n this.log('Signature verification failed: message mismatch');\n return false;\n }\n }\n\n this.log('Signature verified successfully');\n return true;\n } catch (error) {\n this.log('Signature verification failed', error);\n return false;\n }\n }\n\n async getCapabilities(): Promise<EncryptionCapabilities> {\n return {\n textEncryption: true,\n fileEncryption: true,\n bufferEncryption: true,\n streamEncryption: false,\n emailEncryption: false,\n signing: true,\n verification: true,\n keyGeneration: true,\n keyManagement: true,\n multipleRecipients: false,\n symmetricEncryption: true,\n asymmetricEncryption: true,\n };\n }\n}\n"],"names":["encrypted"],"mappings":"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"}
|