@happyvertical/encryption 0.74.8

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pgp-BIhtvrNo.js","sources":["../../src/adapters/pgp.ts"],"sourcesContent":["import * as openpgp from 'openpgp';\nimport { BaseEncryption } from '../shared/base.js';\nimport {\n DecryptError,\n EncryptError,\n InvalidKeyError,\n KeyError,\n PassphraseError,\n SignatureError,\n VerificationError,\n} from '../shared/errors.js';\nimport type {\n DecryptOptions,\n EncryptionCapabilities,\n EncryptOptions,\n ExportKeyOptions,\n ImportKeyOptions,\n Key,\n KeyPair,\n KeyPairOptions,\n PGPOptions,\n SignOptions,\n VerifyOptions,\n} from '../shared/types.js';\n\n/**\n * PGP/OpenPGP encryption adapter\n *\n * Uses OpenPGP.js for encryption, decryption, signing, and key management.\n *\n * @example\n * ```typescript\n * const pgp = new PGPEncryption({\n * type: 'pgp',\n * publicKey: recipientPublicKey,\n * privateKey: myPrivateKey,\n * passphrase: 'my-passphrase'\n * });\n *\n * const encrypted = await pgp.encryptText('Secret message');\n * const decrypted = await pgp.decryptText(encrypted);\n * ```\n */\nexport class PGPEncryption extends BaseEncryption {\n private options: PGPOptions;\n private publicKeys?: openpgp.PublicKey[];\n private privateKeys?: openpgp.PrivateKey[];\n\n constructor(options: PGPOptions) {\n super('pgp', options.debug);\n this.options = options;\n }\n\n /**\n * Initialize keys from options\n */\n private async initializeKeys(): Promise<void> {\n if (this.publicKeys || this.privateKeys) {\n return; // Already initialized\n }\n\n try {\n // Load public keys\n if (this.options.publicKey) {\n const key = await openpgp.readKey({\n armoredKey: this.options.publicKey,\n });\n this.publicKeys = [key];\n } else if (this.options.publicKeys) {\n this.publicKeys = await Promise.all(\n this.options.publicKeys.map((k) =>\n openpgp.readKey({ armoredKey: k }),\n ),\n );\n }\n\n // Load private keys\n if (this.options.privateKey) {\n const key = await openpgp.readPrivateKey({\n armoredKey: this.options.privateKey,\n });\n\n // Decrypt private key if passphrase provided\n if (this.options.passphrase) {\n const decryptedKey = await openpgp.decryptKey({\n privateKey: key,\n passphrase: this.options.passphrase,\n });\n this.privateKeys = [decryptedKey];\n } else {\n this.privateKeys = [key];\n }\n } else if (this.options.privateKeys) {\n this.privateKeys = await Promise.all(\n this.options.privateKeys.map(async (k) => {\n const key = await openpgp.readPrivateKey({ armoredKey: k });\n if (this.options.passphrase) {\n return openpgp.decryptKey({\n privateKey: key,\n passphrase: this.options.passphrase,\n });\n }\n return key;\n }),\n );\n }\n } catch (error) {\n throw new KeyError(\n `Failed to initialize PGP keys: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n /**\n * Get public keys for encryption\n */\n private async getPublicKeys(\n options?: EncryptOptions,\n ): Promise<openpgp.PublicKey[]> {\n await this.initializeKeys();\n\n // Options override default keys\n if (options?.publicKeys) {\n return Promise.all(\n options.publicKeys.map((k) => openpgp.readKey({ armoredKey: k })),\n );\n }\n\n if (!this.publicKeys || this.publicKeys.length === 0) {\n throw new KeyError(\n 'No public keys available for encryption',\n this.adapterType,\n );\n }\n\n return this.publicKeys;\n }\n\n /**\n * Get private keys for decryption\n */\n private async getPrivateKeys(\n options?: DecryptOptions,\n ): Promise<openpgp.PrivateKey[]> {\n await this.initializeKeys();\n\n // Options override default keys\n if (options?.privateKey) {\n const key = await openpgp.readPrivateKey({\n armoredKey: options.privateKey as string,\n });\n\n if (options.passphrase) {\n const decryptedKey = await openpgp.decryptKey({\n privateKey: key,\n passphrase: options.passphrase,\n });\n return [decryptedKey];\n }\n\n return [key];\n }\n\n if (!this.privateKeys || this.privateKeys.length === 0) {\n throw new KeyError(\n 'No private keys available for decryption',\n this.adapterType,\n );\n }\n\n return this.privateKeys;\n }\n\n async encryptText(text: string, options?: EncryptOptions): Promise<string> {\n try {\n this.log('Encrypting text', { length: text.length });\n this.validateEncryptOptions(options);\n\n const publicKeys = await this.getPublicKeys(options);\n\n const format =\n options?.armor !== false ? ('armored' as const) : ('binary' as const);\n\n const encryptConfig: any = {\n message: await openpgp.createMessage({ text }),\n encryptionKeys: publicKeys,\n format,\n };\n\n // Add signing if requested\n if (options?.sign && options?.privateKey) {\n const signingKey = await openpgp.readPrivateKey({\n armoredKey: options.privateKey as string,\n });\n\n if (this.options.passphrase) {\n encryptConfig.signingKeys = await openpgp.decryptKey({\n privateKey: signingKey,\n passphrase: this.options.passphrase,\n });\n } else {\n encryptConfig.signingKeys = signingKey;\n }\n } else if (options?.sign && this.privateKeys) {\n encryptConfig.signingKeys = this.privateKeys;\n }\n\n const encrypted = await openpgp.encrypt(encryptConfig);\n\n this.log('Text encrypted successfully');\n\n // Convert binary output to base64 string for text encryption\n if (format === 'binary' && encrypted instanceof Uint8Array) {\n return Buffer.from(encrypted).toString('base64');\n }\n\n return encrypted as string;\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 this.validateDecryptOptions(options);\n\n const privateKeys = await this.getPrivateKeys(options);\n\n // Try to read as armored message first, fallback to binary\n let message: openpgp.Message<any>;\n try {\n message = await openpgp.readMessage({\n armoredMessage: encrypted,\n });\n } catch {\n // If armored fails, try base64-encoded binary\n try {\n message = await openpgp.readMessage({\n binaryMessage: Buffer.from(encrypted, 'base64'),\n });\n } catch {\n // Last resort: try raw binary\n message = await openpgp.readMessage({\n binaryMessage: Buffer.from(encrypted, 'binary'),\n });\n }\n }\n\n const decryptConfig: openpgp.DecryptOptions = {\n message,\n decryptionKeys: privateKeys,\n format: 'utf8',\n };\n\n // Add verification if requested\n if (options?.verify && options?.publicKey) {\n if (typeof options.publicKey === 'string') {\n decryptConfig.verificationKeys = await openpgp.readKey({\n armoredKey: options.publicKey,\n });\n } else {\n throw new InvalidKeyError(\n 'PGP verification requires armored public key string',\n this.adapterType,\n );\n }\n }\n\n const result = await openpgp.decrypt(decryptConfig);\n\n // Verify signature if requested\n if (options?.verify && result.signatures) {\n try {\n await result.signatures[0].verified;\n this.log('Signature verified successfully');\n } catch (error) {\n throw new VerificationError(\n 'Signature verification failed',\n this.adapterType,\n error,\n );\n }\n }\n\n this.log('Text decrypted successfully');\n return result.data as string;\n } catch (error) {\n if (error instanceof VerificationError) {\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 this.validateEncryptOptions(options);\n\n const publicKeys = await this.getPublicKeys(options);\n\n const format =\n options?.armor === true ? ('armored' as const) : ('binary' as const);\n\n const encryptConfig: any = {\n message: await openpgp.createMessage({ binary: buffer }),\n encryptionKeys: publicKeys,\n format,\n };\n\n // Add signing if requested\n if (options?.sign && options?.privateKey) {\n const signingKey = await openpgp.readPrivateKey({\n armoredKey: options.privateKey as string,\n });\n\n if (this.options.passphrase) {\n encryptConfig.signingKeys = await openpgp.decryptKey({\n privateKey: signingKey,\n passphrase: this.options.passphrase,\n });\n } else {\n encryptConfig.signingKeys = signingKey;\n }\n } else if (options?.sign && this.privateKeys) {\n encryptConfig.signingKeys = this.privateKeys;\n }\n\n const encrypted = await openpgp.encrypt(encryptConfig);\n\n this.log('Buffer encrypted successfully');\n\n if (typeof encrypted === 'string') {\n return Buffer.from(encrypted);\n }\n\n // Handle Uint8Array, WebStream, or NodeWebStream\n if (encrypted instanceof Uint8Array) {\n return Buffer.from(encrypted);\n }\n\n // Fallback for stream types (shouldn't happen with current config)\n return Buffer.from(encrypted as any);\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 this.validateDecryptOptions(options);\n\n const privateKeys = await this.getPrivateKeys(options);\n\n // Try to read as armored message first, fallback to binary\n let message: any;\n try {\n message = await openpgp.readMessage({\n armoredMessage: buffer.toString('utf8'),\n });\n } catch {\n message = await openpgp.readMessage({\n binaryMessage: buffer,\n });\n }\n\n const decryptConfig: openpgp.DecryptOptions = {\n message,\n decryptionKeys: privateKeys,\n format: 'binary',\n };\n\n // Add verification if requested\n if (options?.verify && options?.publicKey) {\n if (typeof options.publicKey === 'string') {\n decryptConfig.verificationKeys = await openpgp.readKey({\n armoredKey: options.publicKey,\n });\n } else {\n throw new InvalidKeyError(\n 'PGP verification requires armored public key string',\n this.adapterType,\n );\n }\n }\n\n const result = await openpgp.decrypt(decryptConfig);\n\n // Verify signature if requested\n if (options?.verify && result.signatures) {\n try {\n await result.signatures[0].verified;\n this.log('Signature verified successfully');\n } catch (error) {\n throw new VerificationError(\n 'Signature verification failed',\n this.adapterType,\n error,\n );\n }\n }\n\n this.log('Buffer decrypted successfully');\n return Buffer.from(result.data as Uint8Array);\n } catch (error) {\n if (error instanceof VerificationError) {\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 async generateKeyPair(options?: KeyPairOptions): Promise<KeyPair> {\n try {\n this.log('Generating PGP key pair', options);\n\n const keyType = options?.type || 'rsa';\n const keySize = options?.keySize || 4096;\n\n let generateOptions: Parameters<typeof openpgp.generateKey>[0];\n\n if (keyType === 'rsa') {\n generateOptions = {\n type: 'rsa',\n rsaBits: keySize,\n userIDs: [\n {\n name: options?.name || '',\n email: options?.email || '',\n },\n ],\n passphrase: options?.passphrase,\n format: 'object',\n };\n } else if (keyType === 'ecc' || keyType === 'ecdh') {\n generateOptions = {\n type: 'ecc',\n curve: (options?.curve as any) || 'curve25519',\n userIDs: [\n {\n name: options?.name || '',\n email: options?.email || '',\n },\n ],\n passphrase: options?.passphrase,\n format: 'object',\n };\n } else {\n throw new KeyError(\n `Unsupported key type for PGP: ${keyType}`,\n this.adapterType,\n );\n }\n\n const { privateKey: privKeyObj, publicKey: pubKeyObj } =\n await openpgp.generateKey(generateOptions);\n\n // Armor the keys for return\n const publicKey = pubKeyObj.armor();\n const privateKey = privKeyObj.armor();\n\n const fingerprint = pubKeyObj.getFingerprint();\n const keyId = pubKeyObj.getKeyID().toHex();\n\n this.log('Key pair generated successfully', { keyId, fingerprint });\n\n return {\n publicKey,\n privateKey,\n fingerprint,\n keyId,\n };\n } catch (error) {\n throw new KeyError(\n `Failed to generate PGP 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 PGP key');\n\n const armoredKey = typeof key === 'string' ? key : key.toString('utf8');\n\n const keyType = options?.type || 'public';\n\n if (keyType === 'public') {\n const pubKey = await openpgp.readKey({ armoredKey });\n\n const expirationTime = await pubKey.getExpirationTime();\n\n return {\n type: 'public',\n format: 'armored',\n data: armoredKey,\n fingerprint: pubKey.getFingerprint(),\n keyId: pubKey.getKeyID().toHex(),\n algorithm: pubKey.getAlgorithmInfo().algorithm,\n created: pubKey.getCreationTime(),\n expires: expirationTime instanceof Date ? expirationTime : undefined,\n userIds: pubKey.getUserIDs().map((uid: string) => {\n const match = uid.match(/^(.*?)\\s*<(.+?)>$/);\n if (match) {\n return { name: match[1], email: match[2] };\n }\n return { email: uid };\n }),\n };\n }\n\n // Private key\n const privKey = await openpgp.readPrivateKey({ armoredKey });\n\n // Decrypt if passphrase provided\n let decryptedKey = privKey;\n if (options?.passphrase) {\n try {\n decryptedKey = await openpgp.decryptKey({\n privateKey: privKey,\n passphrase: options.passphrase,\n });\n } catch (error) {\n throw new PassphraseError(\n 'Invalid passphrase for private key',\n this.adapterType,\n error,\n );\n }\n }\n\n this.log('Key imported successfully');\n\n const expirationTime = await decryptedKey.getExpirationTime();\n\n return {\n type: 'private',\n format: 'armored',\n data: armoredKey,\n fingerprint: decryptedKey.getFingerprint(),\n keyId: decryptedKey.getKeyID().toHex(),\n algorithm: decryptedKey.getAlgorithmInfo().algorithm,\n created: decryptedKey.getCreationTime(),\n expires: expirationTime instanceof Date ? expirationTime : undefined,\n userIds: decryptedKey.getUserIDs().map((uid: string) => {\n const match = uid.match(/^(.*?)\\s*<(.+?)>$/);\n if (match) {\n return { name: match[1], email: match[2] };\n }\n return { email: uid };\n }),\n };\n } catch (error) {\n if (error instanceof PassphraseError) {\n throw error;\n }\n throw new InvalidKeyError(\n `Failed to import PGP 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 PGP key');\n\n // PGP keys are already in armored format\n if (typeof key.data === 'string') {\n if (options?.format === 'binary') {\n return Buffer.from(key.data);\n }\n return key.data;\n }\n\n if (Buffer.isBuffer(key.data)) {\n if (options?.format === 'armored' || options?.armor) {\n return key.data.toString('utf8');\n }\n return key.data;\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 PGP key: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n /**\n * Sign data with private 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 await this.initializeKeys();\n\n let signingKey: openpgp.PrivateKey;\n\n if (options?.privateKey) {\n signingKey = await openpgp.readPrivateKey({\n armoredKey: options.privateKey as string,\n });\n\n if (options.passphrase) {\n signingKey = await openpgp.decryptKey({\n privateKey: signingKey,\n passphrase: options.passphrase,\n });\n }\n } else if (this.privateKeys && this.privateKeys.length > 0) {\n signingKey = this.privateKeys[0];\n } else {\n throw new KeyError(\n 'No private key available for signing',\n this.adapterType,\n );\n }\n\n const message =\n typeof data === 'string'\n ? await openpgp.createMessage({ text: data })\n : await openpgp.createMessage({ binary: data });\n\n const format =\n options?.armor !== false ? ('armored' as const) : ('binary' as const);\n\n // Sign with format\n const signed = await openpgp.sign({\n message,\n signingKeys: signingKey,\n detached: options?.detached,\n format,\n } as any);\n\n this.log('Data signed successfully');\n\n if (format === 'armored') {\n return signed as string;\n } else {\n // When format is 'binary', convert result to Buffer\n if (signed instanceof Uint8Array) {\n return Buffer.from(signed);\n }\n return Buffer.from(signed as any);\n }\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 const verificationKey = await openpgp.readKey({\n armoredKey: options.publicKey as string,\n });\n\n // Check if this is a detached signature\n const signatureStr =\n typeof signature === 'string' ? signature : signature.toString('utf8');\n const isDetached = signatureStr.includes('-----BEGIN PGP SIGNATURE-----');\n\n if (isDetached) {\n // Detached signature verification\n const message =\n typeof data === 'string'\n ? await openpgp.createMessage({ text: data })\n : await openpgp.createMessage({ binary: data });\n\n const sig = await openpgp.readSignature({\n armoredSignature: signatureStr,\n });\n\n const result = await openpgp.verify({\n message: message as any,\n signature: sig,\n verificationKeys: verificationKey,\n } as any);\n\n await result.signatures[0].verified;\n } else {\n // Inline signature verification (signature embedded in message)\n let message: any;\n\n if (signatureStr.includes('-----BEGIN PGP SIGNED MESSAGE-----')) {\n // Cleartext signature\n message = await openpgp.readCleartextMessage({\n cleartextMessage: signatureStr,\n });\n } else {\n // Binary or armored signed message\n try {\n message = await openpgp.readMessage({\n armoredMessage: signatureStr,\n });\n } catch {\n message = await openpgp.readMessage({\n binaryMessage:\n typeof signature === 'string'\n ? Buffer.from(signature, 'binary')\n : signature,\n });\n }\n }\n\n const result = await openpgp.verify({\n message,\n verificationKeys: verificationKey,\n } as any);\n\n await result.signatures[0].verified;\n }\n\n this.log('Signature verified successfully');\n return true;\n } catch (error) {\n if (error instanceof KeyError) {\n throw error;\n }\n this.log('Signature verification failed', error);\n return false;\n }\n }\n\n /**\n * Encrypt email message in PGP/MIME format\n */\n async encryptEmail(\n message: import('../shared/types.js').EmailMessage,\n options?: import('../shared/types.js').EncryptEmailOptions,\n ): Promise<import('../shared/types.js').EmailMessage> {\n try {\n this.log('Encrypting email message');\n\n // Serialize email content (subject, text, html, attachments)\n const emailContent = this.serializeEmailContent(message, options);\n\n // Get public keys for encryption\n const publicKeys = await this.getPublicKeys({\n publicKeys: options?.publicKeys,\n });\n\n // Get private key for signing if requested\n let signingKey: openpgp.PrivateKey | undefined;\n if (options?.sign) {\n await this.initializeKeys();\n if (options.privateKey) {\n const key = await openpgp.readPrivateKey({\n armoredKey: options.privateKey,\n });\n if (options.passphrase) {\n signingKey = await openpgp.decryptKey({\n privateKey: key,\n passphrase: options.passphrase,\n });\n } else {\n signingKey = key;\n }\n } else if (this.privateKeys && this.privateKeys.length > 0) {\n signingKey = this.privateKeys[0];\n }\n }\n\n // Encrypt the email content\n const encryptConfig: any = {\n message: await openpgp.createMessage({ text: emailContent }),\n encryptionKeys: publicKeys,\n format:\n options?.armor !== false ? ('armored' as const) : ('binary' as const),\n };\n\n if (signingKey) {\n encryptConfig.signingKeys = signingKey;\n }\n\n const encrypted = await openpgp.encrypt(encryptConfig);\n\n this.log('Email encrypted successfully');\n\n // Return encrypted message in PGP/MIME format\n return {\n ...message,\n text: encrypted as string,\n html: undefined, // Clear HTML when encrypted\n contentType:\n 'multipart/encrypted; protocol=\"application/pgp-encrypted\"',\n headers: {\n ...(message.headers || {}),\n 'Content-Type':\n 'multipart/encrypted; protocol=\"application/pgp-encrypted\"',\n },\n };\n } catch (error) {\n throw new EncryptError(\n `Failed to encrypt email: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n /**\n * Decrypt PGP/MIME email message\n */\n async decryptEmail(\n message: import('../shared/types.js').EmailMessage,\n options?: import('../shared/types.js').DecryptEmailOptions,\n ): Promise<import('../shared/types.js').DecryptedEmail> {\n try {\n this.log('Decrypting email message');\n\n if (!message.text) {\n throw new DecryptError(\n 'Email message has no text content to decrypt',\n this.adapterType,\n );\n }\n\n // Get private keys for decryption\n const privateKeys = await this.getPrivateKeys({\n privateKey: options?.privateKey,\n passphrase: options?.passphrase,\n });\n\n // Read encrypted message\n let encryptedMessage: openpgp.Message<any>;\n try {\n encryptedMessage = await openpgp.readMessage({\n armoredMessage: message.text,\n });\n } catch {\n encryptedMessage = await openpgp.readMessage({\n binaryMessage: Buffer.from(message.text, 'base64'),\n });\n }\n\n // Decrypt the message\n const decryptConfig: openpgp.DecryptOptions = {\n message: encryptedMessage,\n decryptionKeys: privateKeys,\n format: 'utf8',\n };\n\n // Add verification if requested\n if (options?.verify) {\n const verificationKey = options.publicKey || this.options.publicKey;\n if (verificationKey) {\n decryptConfig.verificationKeys = await openpgp.readKey({\n armoredKey: verificationKey,\n });\n }\n }\n\n const result = await openpgp.decrypt(decryptConfig);\n const decryptedContent = result.data as string;\n\n // Verify signature if requested\n let verified = false;\n let verificationError: string | undefined;\n let signerKeyId: string | undefined;\n let signerFingerprint: string | undefined;\n\n if (options?.verify) {\n const verificationKey = options.publicKey || this.options.publicKey;\n\n if (!verificationKey) {\n verificationError = 'Public key required for signature verification';\n this.log('Email signature verification skipped: no public key');\n } else if (!result.signatures || result.signatures.length === 0) {\n verificationError = 'No signature found in message';\n this.log('Email signature verification skipped: no signatures');\n } else {\n try {\n // Verify the signature\n await result.signatures[0].verified;\n verified = true;\n signerKeyId = result.signatures[0].keyID.toHex();\n // Get fingerprint from verification key\n const pubKey = await openpgp.readKey({\n armoredKey: verificationKey,\n });\n signerFingerprint = pubKey.getFingerprint();\n this.log('Email signature verified successfully');\n } catch (error) {\n verificationError =\n error instanceof Error ? error.message : String(error);\n this.log('Email signature verification failed', error);\n }\n }\n }\n\n // Deserialize email content\n const deserializedMessage = this.deserializeEmailContent(\n decryptedContent,\n message,\n );\n\n this.log('Email decrypted successfully');\n\n return {\n ...deserializedMessage,\n encrypted: true,\n signed: result.signatures && result.signatures.length > 0,\n verified: options?.verify ? verified : undefined,\n verificationError,\n signerKeyId,\n signerFingerprint,\n encryptionAlgorithm: 'pgp',\n };\n } catch (error) {\n if (error instanceof DecryptError) {\n throw error;\n }\n throw new DecryptError(\n `Failed to decrypt email: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n /**\n * Sign email message\n */\n async signEmail(\n message: import('../shared/types.js').EmailMessage,\n options?: import('../shared/types.js').SignEmailOptions,\n ): Promise<import('../shared/types.js').EmailMessage> {\n try {\n this.log('Signing email message');\n\n // Serialize email content\n const emailContent = this.serializeEmailContent(message);\n\n // Get signing key\n await this.initializeKeys();\n let signingKey: openpgp.PrivateKey;\n\n if (options?.privateKey) {\n const key = await openpgp.readPrivateKey({\n armoredKey: options.privateKey as string,\n });\n if (options.passphrase) {\n signingKey = await openpgp.decryptKey({\n privateKey: key,\n passphrase: options.passphrase,\n });\n } else {\n signingKey = key;\n }\n } else if (this.privateKeys && this.privateKeys.length > 0) {\n signingKey = this.privateKeys[0];\n } else {\n throw new KeyError(\n 'No private key available for signing email',\n this.adapterType,\n );\n }\n\n // Sign the message (cleartext signature)\n const signedMessageObj = await openpgp.sign({\n message: await openpgp.createCleartextMessage({ text: emailContent }),\n signingKeys: signingKey,\n format: 'object' as const,\n });\n\n // Convert to armored string\n const signedMessage = signedMessageObj.armor();\n\n this.log('Email signed successfully');\n\n return {\n ...message,\n text: signedMessage,\n contentType: 'text/plain; charset=utf-8',\n headers: {\n ...(message.headers || {}),\n 'Content-Type': 'text/plain; charset=utf-8',\n },\n };\n } catch (error) {\n throw new SignatureError(\n `Failed to sign email: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n /**\n * Verify email signature\n */\n async verifyEmail(\n message: import('../shared/types.js').EmailMessage,\n options?: import('../shared/types.js').VerifyEmailOptions,\n ): Promise<import('../shared/types.js').VerificationResult> {\n try {\n this.log('Verifying email signature');\n\n if (!message.text) {\n return {\n valid: false,\n message: 'Email message has no text content to verify',\n };\n }\n\n if (!options?.publicKey) {\n return {\n valid: false,\n message: 'Public key required for email signature verification',\n };\n }\n\n const verificationKey = await openpgp.readKey({\n armoredKey: options.publicKey as string,\n });\n\n // Read signed message\n const signedMessage = await openpgp.readCleartextMessage({\n cleartextMessage: message.text,\n });\n\n // Verify the signature\n const result = await openpgp.verify({\n message: signedMessage,\n verificationKeys: verificationKey,\n });\n\n await result.signatures[0].verified;\n\n const keyId = result.signatures[0].keyID.toHex();\n const fingerprint = verificationKey.getFingerprint();\n\n this.log('Email signature verified successfully');\n\n return {\n valid: true,\n keyId,\n keyFingerprint: fingerprint,\n timestamp: new Date(),\n algorithm: 'pgp',\n };\n } catch (error) {\n this.log('Email signature verification failed', error);\n return {\n valid: false,\n message: (error as Error).message,\n };\n }\n }\n\n /**\n * Serialize email content for encryption/signing\n */\n private serializeEmailContent(\n message: import('../shared/types.js').EmailMessage,\n options?: import('../shared/types.js').EncryptEmailOptions,\n ): string {\n const parts: string[] = [];\n\n // Add subject (optionally encrypt it)\n if (options?.encryptSubject) {\n parts.push(`Subject: ${message.subject}`);\n }\n\n // Add text content\n if (message.text) {\n parts.push(`\\n${message.text}`);\n }\n\n // Add HTML content\n if (message.html) {\n parts.push(`\\n--- HTML Content ---\\n${message.html}`);\n }\n\n // Add attachment metadata (not the actual content)\n if (message.attachments && message.attachments.length > 0) {\n parts.push('\\n--- Attachments ---');\n for (const attachment of message.attachments) {\n parts.push(\n `- ${attachment.filename || 'unnamed'} (${attachment.contentType}, ${attachment.size} bytes)`,\n );\n }\n }\n\n return parts.join('\\n');\n }\n\n /**\n * Deserialize email content after decryption\n */\n private deserializeEmailContent(\n content: string,\n originalMessage: import('../shared/types.js').EmailMessage,\n ): import('../shared/types.js').EmailMessage {\n const lines = content.split('\\n');\n let subject = originalMessage.subject;\n let text = '';\n let html: string | undefined;\n\n // Parse decrypted content\n let currentSection = 'text';\n for (const line of lines) {\n if (line.startsWith('Subject: ')) {\n subject = line.substring(9);\n } else if (line === '--- HTML Content ---') {\n currentSection = 'html';\n } else if (line === '--- Attachments ---') {\n break; // Stop at attachments\n } else if (currentSection === 'text' && line.trim()) {\n text += `${line}\\n`;\n } else if (currentSection === 'html') {\n if (!html) html = '';\n html += `${line}\\n`;\n }\n }\n\n return {\n ...originalMessage,\n subject,\n text: text.trim(),\n html: html?.trim(),\n };\n }\n\n async getCapabilities(): Promise<EncryptionCapabilities> {\n return {\n textEncryption: true,\n fileEncryption: true,\n bufferEncryption: true,\n streamEncryption: true,\n emailEncryption: true,\n signing: true,\n verification: true,\n keyGeneration: true,\n keyManagement: true,\n multipleRecipients: true,\n symmetricEncryption: false,\n asymmetricEncryption: true,\n };\n }\n}\n"],"names":["expirationTime"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=claude-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-context.d.ts","sourceRoot":"","sources":["../../src/cli/claude-context.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, mkdirSync, copyFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ const Dirname = dirname(fileURLToPath(import.meta.url));
6
+ const pkgRoot = join(Dirname, "../..");
7
+ const targetDir = join(process.cwd(), ".claude");
8
+ if (!existsSync(targetDir)) {
9
+ mkdirSync(targetDir, { recursive: true });
10
+ }
11
+ const pkgName = "encryption";
12
+ const agentMdSrc = existsSync(join(pkgRoot, "AGENT.md")) ? join(pkgRoot, "AGENT.md") : join(pkgRoot, "CLAUDE.md");
13
+ const metaSrc = existsSync(join(pkgRoot, "metadata.json")) ? join(pkgRoot, "metadata.json") : join(pkgRoot, ".claude-meta.json");
14
+ if (existsSync(agentMdSrc)) {
15
+ copyFileSync(agentMdSrc, join(targetDir, `have-${pkgName}.md`));
16
+ }
17
+ if (existsSync(metaSrc)) {
18
+ copyFileSync(metaSrc, join(targetDir, `have-${pkgName}.meta.json`));
19
+ }
20
+ console.log(`✓ Installed @happyvertical/${pkgName} context to .claude/`);
21
+ //# sourceMappingURL=claude-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-context.js","sources":["../../src/cli/claude-context.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI script to install agent context for @happyvertical/encryption\n * Run the published context installer binary for this package.\n */\nimport { copyFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst Dirname = dirname(fileURLToPath(import.meta.url));\nconst pkgRoot = join(Dirname, '../..');\nconst targetDir = join(process.cwd(), '.claude');\n\nif (!existsSync(targetDir)) {\n mkdirSync(targetDir, { recursive: true });\n}\n\nconst pkgName = 'encryption';\nconst agentMdSrc = existsSync(join(pkgRoot, 'AGENT.md'))\n ? join(pkgRoot, 'AGENT.md')\n : join(pkgRoot, 'CLAUDE.md');\nconst metaSrc = existsSync(join(pkgRoot, 'metadata.json'))\n ? join(pkgRoot, 'metadata.json')\n : join(pkgRoot, '.claude-meta.json');\n\nif (existsSync(agentMdSrc)) {\n copyFileSync(agentMdSrc, join(targetDir, `have-${pkgName}.md`));\n}\n\nif (existsSync(metaSrc)) {\n copyFileSync(metaSrc, join(targetDir, `have-${pkgName}.meta.json`));\n}\n\nconsole.log(`✓ Installed @happyvertical/${pkgName} context to .claude/`);\n"],"names":[],"mappings":";;;;AASA,MAAM,UAAU,QAAQ,cAAc,YAAY,GAAG,CAAC;AACtD,MAAM,UAAU,KAAK,SAAS,OAAO;AACrC,MAAM,YAAY,KAAK,QAAQ,IAAA,GAAO,SAAS;AAE/C,IAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,YAAU,WAAW,EAAE,WAAW,KAAA,CAAM;AAC1C;AAEA,MAAM,UAAU;AAChB,MAAM,aAAa,WAAW,KAAK,SAAS,UAAU,CAAC,IACnD,KAAK,SAAS,UAAU,IACxB,KAAK,SAAS,WAAW;AAC7B,MAAM,UAAU,WAAW,KAAK,SAAS,eAAe,CAAC,IACrD,KAAK,SAAS,eAAe,IAC7B,KAAK,SAAS,mBAAmB;AAErC,IAAI,WAAW,UAAU,GAAG;AAC1B,eAAa,YAAY,KAAK,WAAW,QAAQ,OAAO,KAAK,CAAC;AAChE;AAEA,IAAI,WAAW,OAAO,GAAG;AACvB,eAAa,SAAS,KAAK,WAAW,QAAQ,OAAO,YAAY,CAAC;AACpE;AAEA,QAAQ,IAAI,8BAA8B,OAAO,sBAAsB;"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @happyvertical/encryption
3
+ *
4
+ * Unified encryption and cryptography operations with adapter-based architecture.
5
+ *
6
+ * Supports multiple encryption methods (PGP, NaCl, Node crypto) and various use cases
7
+ * (text, files, buffers, streams, email).
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ export { BaseEncryption } from './shared/base.js';
12
+ export { AlgorithmError, DecryptError, EncryptError, EncryptionError, FormatError, InvalidKeyError, KeyError, KeyNotFoundError, PassphraseError, SignatureError, VerificationError, } from './shared/errors.js';
13
+ export { getEncryption, isNaClOptions, isNodeCryptoOptions, isPGPOptions, } from './shared/factory.js';
14
+ export type { AdapterType, Attachment, DecryptEmailOptions, DecryptedEmail, DecryptOptions, EmailAddress, EmailMessage, EncryptEmailOptions, Encryption, EncryptionCapabilities, EncryptionConfig, EncryptOptions, ExportKeyOptions, GetEncryptionOptions, ImportKeyOptions, Key, KeyPair, KeyPairOptions, NaClOptions, NodeCryptoOptions, PGPOptions, SignEmailOptions, SignOptions, VerificationResult, VerifyEmailOptions, VerifyOptions, } from './shared/types.js';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EACL,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,WAAW,EACX,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,YAAY,GACb,MAAM,qBAAqB,CAAC;AAG7B,YAAY,EACV,WAAW,EACX,UAAU,EACV,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACV,sBAAsB,EACtB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,GAAG,EACH,OAAO,EACP,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,GACd,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,356 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ class EncryptionError extends Error {
3
+ code;
4
+ adapter;
5
+ cause;
6
+ timestamp;
7
+ constructor(message, code, adapter, cause) {
8
+ super(message);
9
+ this.name = "EncryptionError";
10
+ this.code = code;
11
+ this.adapter = adapter;
12
+ this.cause = cause;
13
+ this.timestamp = /* @__PURE__ */ new Date();
14
+ if (Error.captureStackTrace) {
15
+ Error.captureStackTrace(this, this.constructor);
16
+ }
17
+ }
18
+ /**
19
+ * Convert error to JSON for logging/serialization
20
+ */
21
+ toJSON() {
22
+ return {
23
+ name: this.name,
24
+ message: this.message,
25
+ code: this.code,
26
+ adapter: this.adapter,
27
+ timestamp: this.timestamp.toISOString(),
28
+ stack: this.stack,
29
+ cause: this.cause
30
+ };
31
+ }
32
+ }
33
+ class KeyError extends EncryptionError {
34
+ constructor(message, adapter, cause) {
35
+ super(message, "KEY_ERROR", adapter, cause);
36
+ this.name = "KeyError";
37
+ }
38
+ }
39
+ class InvalidKeyError extends EncryptionError {
40
+ constructor(message, adapter, cause) {
41
+ super(message, "INVALID_KEY", adapter, cause);
42
+ this.name = "InvalidKeyError";
43
+ }
44
+ }
45
+ class KeyNotFoundError extends EncryptionError {
46
+ keyId;
47
+ constructor(message, keyId, adapter) {
48
+ super(message, "KEY_NOT_FOUND", adapter);
49
+ this.name = "KeyNotFoundError";
50
+ this.keyId = keyId;
51
+ }
52
+ toJSON() {
53
+ return {
54
+ ...super.toJSON(),
55
+ keyId: this.keyId
56
+ };
57
+ }
58
+ }
59
+ class PassphraseError extends EncryptionError {
60
+ constructor(message, adapter, cause) {
61
+ super(message, "PASSPHRASE_ERROR", adapter, cause);
62
+ this.name = "PassphraseError";
63
+ }
64
+ }
65
+ class EncryptError extends EncryptionError {
66
+ constructor(message, adapter, cause) {
67
+ super(message, "ENCRYPT_ERROR", adapter, cause);
68
+ this.name = "EncryptError";
69
+ }
70
+ }
71
+ class DecryptError extends EncryptionError {
72
+ constructor(message, adapter, cause) {
73
+ super(message, "DECRYPT_ERROR", adapter, cause);
74
+ this.name = "DecryptError";
75
+ }
76
+ }
77
+ class SignatureError extends EncryptionError {
78
+ constructor(message, adapter, cause) {
79
+ super(message, "SIGNATURE_ERROR", adapter, cause);
80
+ this.name = "SignatureError";
81
+ }
82
+ }
83
+ class VerificationError extends EncryptionError {
84
+ constructor(message, adapter, cause) {
85
+ super(message, "VERIFICATION_ERROR", adapter, cause);
86
+ this.name = "VerificationError";
87
+ }
88
+ }
89
+ class FormatError extends EncryptionError {
90
+ constructor(message, adapter, cause) {
91
+ super(message, "FORMAT_ERROR", adapter, cause);
92
+ this.name = "FormatError";
93
+ }
94
+ }
95
+ class AlgorithmError extends EncryptionError {
96
+ algorithm;
97
+ constructor(message, algorithm, adapter) {
98
+ super(message, "ALGORITHM_ERROR", adapter);
99
+ this.name = "AlgorithmError";
100
+ this.algorithm = algorithm;
101
+ }
102
+ toJSON() {
103
+ return {
104
+ ...super.toJSON(),
105
+ algorithm: this.algorithm
106
+ };
107
+ }
108
+ }
109
+ class BaseEncryption {
110
+ adapterType;
111
+ debug;
112
+ constructor(adapterType, debug = false) {
113
+ this.adapterType = adapterType;
114
+ this.debug = debug;
115
+ }
116
+ /**
117
+ * Get the adapter type
118
+ */
119
+ getAdapter() {
120
+ return this.adapterType;
121
+ }
122
+ /**
123
+ * Log debug messages if debug mode is enabled
124
+ */
125
+ log(message, ...args) {
126
+ if (this.debug) {
127
+ console.log(`[${this.adapterType}] ${message}`, ...args);
128
+ }
129
+ }
130
+ /**
131
+ * Validate that a key is provided
132
+ */
133
+ validateKey(key, keyType) {
134
+ if (!key) {
135
+ throw new KeyError(
136
+ `${keyType} key is required but was not provided`,
137
+ this.adapterType
138
+ );
139
+ }
140
+ if (typeof key === "string" && key.trim().length === 0) {
141
+ throw new InvalidKeyError(
142
+ `${keyType} key cannot be empty`,
143
+ this.adapterType
144
+ );
145
+ }
146
+ if (Buffer.isBuffer(key) && key.length === 0) {
147
+ throw new InvalidKeyError(
148
+ `${keyType} key cannot be empty`,
149
+ this.adapterType
150
+ );
151
+ }
152
+ if (key instanceof Uint8Array && key.length === 0) {
153
+ throw new InvalidKeyError(
154
+ `${keyType} key cannot be empty`,
155
+ this.adapterType
156
+ );
157
+ }
158
+ }
159
+ /**
160
+ * Validate encryption options
161
+ */
162
+ validateEncryptOptions(options) {
163
+ if (!options) return;
164
+ if (options.encoding && !["base64", "hex", "utf8"].includes(options.encoding)) {
165
+ throw new Error(
166
+ `Invalid encoding: ${options.encoding}. Must be 'base64', 'hex', or 'utf8'`
167
+ );
168
+ }
169
+ }
170
+ /**
171
+ * Validate decryption options
172
+ */
173
+ validateDecryptOptions(options) {
174
+ if (!options) return;
175
+ if (options.encoding && !["base64", "hex", "utf8"].includes(options.encoding)) {
176
+ throw new Error(
177
+ `Invalid encoding: ${options.encoding}. Must be 'base64', 'hex', or 'utf8'`
178
+ );
179
+ }
180
+ }
181
+ /**
182
+ * Convert Buffer to string based on encoding
183
+ */
184
+ bufferToString(buffer, encoding = "base64") {
185
+ return buffer.toString(encoding);
186
+ }
187
+ /**
188
+ * Convert string to Buffer based on encoding
189
+ */
190
+ stringToBuffer(str, encoding = "base64") {
191
+ return Buffer.from(str, encoding);
192
+ }
193
+ /**
194
+ * Wrap errors with adapter context
195
+ */
196
+ wrapError(error, operation) {
197
+ if (error instanceof Error) {
198
+ return error;
199
+ }
200
+ return new Error(
201
+ `${operation} failed in ${this.adapterType} adapter: ${String(error)}`
202
+ );
203
+ }
204
+ // =============================================================================
205
+ // File operations (default implementation using text/buffer methods)
206
+ // =============================================================================
207
+ async encryptFile(inputPath, outputPath, options) {
208
+ try {
209
+ this.log(`Encrypting file: ${inputPath} -> ${outputPath}`);
210
+ const input = await readFile(inputPath);
211
+ const encrypted = await this.encryptBuffer(input, options);
212
+ await writeFile(outputPath, encrypted);
213
+ this.log(`File encrypted successfully: ${outputPath}`);
214
+ } catch (error) {
215
+ throw new EncryptError(
216
+ `Failed to encrypt file: ${error.message}`,
217
+ this.adapterType,
218
+ error
219
+ );
220
+ }
221
+ }
222
+ async decryptFile(inputPath, outputPath, options) {
223
+ try {
224
+ this.log(`Decrypting file: ${inputPath} -> ${outputPath}`);
225
+ const input = await readFile(inputPath);
226
+ const decrypted = await this.decryptBuffer(input, options);
227
+ await writeFile(outputPath, decrypted);
228
+ this.log(`File decrypted successfully: ${outputPath}`);
229
+ } catch (error) {
230
+ throw new DecryptError(
231
+ `Failed to decrypt file: ${error.message}`,
232
+ this.adapterType,
233
+ error
234
+ );
235
+ }
236
+ }
237
+ }
238
+ function isPGPOptions(opts) {
239
+ return opts.type === "pgp";
240
+ }
241
+ function isNaClOptions(opts) {
242
+ return opts.type === "nacl";
243
+ }
244
+ function isNodeCryptoOptions(opts) {
245
+ return opts.type === "node";
246
+ }
247
+ function validateCommonOptions(options) {
248
+ if (!options.type) {
249
+ throw new Error("Encryption adapter type is required");
250
+ }
251
+ const validTypes = ["pgp", "nacl", "node"];
252
+ if (!validTypes.includes(options.type)) {
253
+ throw new Error(
254
+ `Invalid encryption adapter type: ${options.type}. Must be one of: ${validTypes.join(", ")}`
255
+ );
256
+ }
257
+ }
258
+ function validatePGPOptions(options) {
259
+ if (options.armor !== void 0 && typeof options.armor !== "boolean") {
260
+ throw new Error("PGP armor option must be a boolean");
261
+ }
262
+ if (options.compression !== void 0 && typeof options.compression !== "boolean") {
263
+ throw new Error("PGP compression option must be a boolean");
264
+ }
265
+ }
266
+ function validateNaClOptions(options) {
267
+ if (options.encoding) {
268
+ const validEncodings = ["base64", "hex", "utf8"];
269
+ if (!validEncodings.includes(options.encoding)) {
270
+ throw new Error(
271
+ `Invalid NaCl encoding: ${options.encoding}. Must be one of: ${validEncodings.join(", ")}`
272
+ );
273
+ }
274
+ }
275
+ if (typeof options.secretKey === "string" && options.secretKey.length === 0) {
276
+ throw new Error("NaCl secret key cannot be empty string");
277
+ }
278
+ if (typeof options.publicKey === "string" && options.publicKey.length === 0) {
279
+ throw new Error("NaCl public key cannot be empty string");
280
+ }
281
+ }
282
+ function validateNodeCryptoOptions(options) {
283
+ if (!options.algorithm) {
284
+ throw new Error("Node crypto algorithm is required");
285
+ }
286
+ if (options.encoding) {
287
+ const validEncodings = ["hex", "base64", "utf8"];
288
+ if (!validEncodings.includes(options.encoding)) {
289
+ throw new Error(
290
+ `Invalid Node crypto encoding: ${options.encoding}. Must be one of: ${validEncodings.join(", ")}`
291
+ );
292
+ }
293
+ }
294
+ if (options.keyDerivation) {
295
+ if (!options.keyDerivation.password || options.keyDerivation.password.trim().length === 0) {
296
+ throw new Error("Key derivation password is required");
297
+ }
298
+ if (options.keyDerivation.iterations !== void 0 && options.keyDerivation.iterations < 1e3) {
299
+ throw new Error(
300
+ "Key derivation iterations must be at least 1000 for security"
301
+ );
302
+ }
303
+ if (options.keyDerivation.keyLength !== void 0 && options.keyDerivation.keyLength < 16) {
304
+ throw new Error("Key derivation key length must be at least 16 bytes");
305
+ }
306
+ }
307
+ const symmetricAlgorithms = [
308
+ "aes-256-gcm",
309
+ "aes-256-cbc",
310
+ "aes-128-gcm",
311
+ "aes-128-cbc"
312
+ ];
313
+ const asymmetricAlgorithms = ["rsa", "rsa-oaep", "rsa-pss", "ecdh", "ecdsa"];
314
+ if (symmetricAlgorithms.includes(options.algorithm)) ;
315
+ else if (asymmetricAlgorithms.includes(options.algorithm)) ;
316
+ }
317
+ async function getEncryption(options) {
318
+ validateCommonOptions(options);
319
+ if (isPGPOptions(options)) {
320
+ validatePGPOptions(options);
321
+ const { PGPEncryption } = await import("./chunks/pgp-BIhtvrNo.js");
322
+ return new PGPEncryption(options);
323
+ }
324
+ if (isNaClOptions(options)) {
325
+ validateNaClOptions(options);
326
+ const { NaClEncryption } = await import("./chunks/nacl-CoiIhzki.js");
327
+ return new NaClEncryption(options);
328
+ }
329
+ if (isNodeCryptoOptions(options)) {
330
+ validateNodeCryptoOptions(options);
331
+ const { NodeCryptoEncryption } = await import("./chunks/node-nfBpcQQH.js");
332
+ return new NodeCryptoEncryption(options);
333
+ }
334
+ throw new Error(
335
+ `Unsupported encryption adapter type: ${options.type}`
336
+ );
337
+ }
338
+ export {
339
+ AlgorithmError,
340
+ BaseEncryption,
341
+ DecryptError,
342
+ EncryptError,
343
+ EncryptionError,
344
+ FormatError,
345
+ InvalidKeyError,
346
+ KeyError,
347
+ KeyNotFoundError,
348
+ PassphraseError,
349
+ SignatureError,
350
+ VerificationError,
351
+ getEncryption,
352
+ isNaClOptions,
353
+ isNodeCryptoOptions,
354
+ isPGPOptions
355
+ };
356
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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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"}