Rehydra uses AES-256-GCM encryption via the Web Crypto API for securing PII maps.
Key Providers
InMemoryKeyProvider
Generates a random key in memory. Key is lost when the process ends.
import { InMemoryKeyProvider } from 'rehydra' ;
const keyProvider = new InMemoryKeyProvider ();
const key = await keyProvider . getKey (); // Uint8Array (32 bytes)
Only for development/testing. The key is not persisted.
ConfigKeyProvider
Uses a pre-configured key from your environment.
import { ConfigKeyProvider } from 'rehydra' ;
// Generate key: openssl rand -base64 32
const keyBase64 = process . env . PII_ENCRYPTION_KEY ;
const keyProvider = new ConfigKeyProvider ( keyBase64 );
KeyProvider Interface
interface KeyProvider {
getKey () : Promise < Uint8Array >;
}
Implement for custom key storage:
class VaultKeyProvider implements KeyProvider {
async getKey () : Promise < Uint8Array > {
const secret = await vault . getSecret ( 'pii-encryption-key' );
return base64ToUint8Array ( secret );
}
}
Encryption Functions
encryptPIIMap()
Encrypts a PII map.
import { encryptPIIMap } from 'rehydra' ;
const piiMap = new Map ([
[ 'EMAIL:1' , '[email protected] ' ],
[ 'PERSON:1' , 'John Smith' ],
]);
const encrypted = await encryptPIIMap ( piiMap , key );
// { ciphertext: '...', iv: '...', authTag: '...' }
decryptPIIMap()
Decrypts a PII map.
import { decryptPIIMap } from 'rehydra' ;
const piiMap = await decryptPIIMap ( encrypted , key );
// Map { 'EMAIL:1' => '[email protected] ', ... }
Key Generation
generateKey()
Generate a random 256-bit key.
import { generateKey } from 'rehydra' ;
const key = generateKey (); // Uint8Array (32 bytes)
generateSalt()
Generate a random salt for key derivation.
import { generateSalt } from 'rehydra' ;
const salt = generateSalt (); // Uint8Array (16 bytes)
deriveKey()
Derive a key from a password using PBKDF2.
import { deriveKey , generateSalt } from 'rehydra' ;
const password = 'user-password' ;
const salt = generateSalt ();
const key = await deriveKey ( password , salt );
// Store salt with encrypted data for later derivation
Utility Functions
validateKey()
Check if a key is valid.
import { validateKey } from 'rehydra' ;
if ( validateKey ( key )) {
console . log ( 'Key is valid' );
} else {
throw new Error ( 'Invalid key' );
}
secureCompare()
Constant-time comparison to prevent timing attacks.
import { secureCompare } from 'rehydra' ;
if ( secureCompare ( key1 , key2 )) {
console . log ( 'Keys match' );
}
uint8ArrayToBase64()
Convert Uint8Array to Base64.
import { uint8ArrayToBase64 } from 'rehydra' ;
const base64 = uint8ArrayToBase64 ( key );
// Store this string securely
base64ToUint8Array()
Convert Base64 to Uint8Array.
import { base64ToUint8Array } from 'rehydra' ;
const key = base64ToUint8Array ( base64 );
EncryptedPIIMap Structure
interface EncryptedPIIMap {
ciphertext : string ; // Base64-encoded encrypted data
iv : string ; // Base64-encoded initialization vector
authTag : string ; // Base64-encoded authentication tag
}
Complete Example
import {
generateKey ,
encryptPIIMap ,
decryptPIIMap ,
uint8ArrayToBase64 ,
base64ToUint8Array
} from 'rehydra' ;
// Generate and store key
const key = generateKey ();
const keyBase64 = uint8ArrayToBase64 ( key );
// Store keyBase64 securely (env var, keychain, etc.)
// Later: encrypt
const piiMap = new Map ([[ 'EMAIL:1' , '[email protected] ' ]]);
const encrypted = await encryptPIIMap ( piiMap , key );
// Later: decrypt
const restoredKey = base64ToUint8Array ( keyBase64 );
const decrypted = await decryptPIIMap ( encrypted , restoredKey );
Security Notes
Never commit keys to version control
Use environment variables or secrets managers
Consider platform keystores (iOS Keychain, Android Keystore)
Implement key rotation for long-running applications: // Re-encrypt with new key
const piiMap = await decryptPIIMap ( encrypted , oldKey );
const newEncrypted = await encryptPIIMap ( piiMap , newKey );
In browsers:
Keys in memory can be accessed by malicious scripts
Consider using SubtleCrypto key wrapping
Clear keys when no longer needed