( value: string, publicKeyPem: string | Buffer, aad?: string )
| 42 | * 4. Return both encrypted data and encrypted DEK |
| 43 | */ |
| 44 | export function encryptWithPublicKey( |
| 45 | value: string, |
| 46 | publicKeyPem: string | Buffer, |
| 47 | aad?: string |
| 48 | ): EncryptedEnvelope { |
| 49 | if (!publicKeyPem) { |
| 50 | throw new EncryptionConfigurationError('Public key parameter is required'); |
| 51 | } |
| 52 | |
| 53 | try { |
| 54 | const dek = generateKeySync('aes', { length: 256 }); |
| 55 | const dekBuffer = dek.export(); |
| 56 | |
| 57 | const iv = randomBytes(16); |
| 58 | const cipher = createCipheriv('aes-256-gcm', dekBuffer, iv); |
| 59 | if (aad !== undefined) { |
| 60 | cipher.setAAD(Buffer.from(aad, 'utf8')); |
| 61 | } |
| 62 | |
| 63 | let encrypted = cipher.update(value, 'utf8'); |
| 64 | encrypted = Buffer.concat([encrypted, cipher.final()]); |
| 65 | |
| 66 | const authTag = cipher.getAuthTag(); |
| 67 | |
| 68 | // Combine iv, encrypted data, and authTag for storage |
| 69 | const encryptedDataBuffer = Buffer.concat([iv, encrypted, authTag]); |
| 70 | const encryptedData = encryptedDataBuffer.toString('base64'); |
| 71 | |
| 72 | // Encrypt DEK with RSA public key |
| 73 | const encryptedDEKBuffer = publicEncrypt( |
| 74 | { |
| 75 | key: publicKeyPem, |
| 76 | padding: constants.RSA_PKCS1_OAEP_PADDING, |
| 77 | oaepHash: 'sha256', |
| 78 | }, |
| 79 | dekBuffer |
| 80 | ); |
| 81 | const encryptedDEK = encryptedDEKBuffer.toString('base64'); |
| 82 | |
| 83 | return { |
| 84 | encryptedData, |
| 85 | encryptedDEK, |
| 86 | algorithm: 'rsa-aes-256-gcm', |
| 87 | version: 1, |
| 88 | }; |
| 89 | } catch (error) { |
| 90 | if (error instanceof Error) { |
| 91 | throw new EncryptionConfigurationError(`Encryption failed: ${error.message}`, { |
| 92 | cause: error, |
| 93 | }); |
| 94 | } |
| 95 | throw new EncryptionConfigurationError('Encryption failed with unknown error'); |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | /** |
| 100 | * Decrypts envelope-encrypted data using RSA private key |
no test coverage detected