11# Dinamo HSM KMS Implementation Documentation
22
3- This document provides comprehensive documentation for the KMS API's integration with Dinamo HSM, covering the complete request-response flow from API handlers to HSM operations.
3+ This document provides a reference implementation for integrating the 4 KMS API's with Dinamo HSM, covering the complete request-response flow from API handlers to HSM operations.
44
55## Demo Scripts
66
@@ -32,7 +32,7 @@ API Request → Handler → KMS Provider → Dinamo HSM → Database → Respons
3232| ` POST /generateDataKey ` | ` generateDataKey.ts ` | ` generateDataKey() ` | Create/export AES key |
3333| ` POST /decryptDataKey ` | ` decryptDataKey.ts ` | ` decryptDataKey() ` | Local SJCL decryption |
3434
35- ## Envelope Encryption Pattern
35+ ## Envelope Encryption Pattern (Recommended)
3636
3737### Layer 1: Root Keys (HSM)
3838- ** Algorithm** : RSA-2048 asymmetric keys
@@ -78,12 +78,11 @@ private async withClient<T>(fn: (client) => Promise<T>): Promise<T> {
7878}
7979```
8080
81- ** Key Features:**
82- - Environment-based configuration
83- - Automatic connection cleanup using try/finally
84- - Error handling for disconnect failures
85- - Generic typing for return values
86- - Centralized connection logic for all HSM operations
81+ ** Why Connection Management is Critical:**
82+ - ** Prevents Resource Leaks** : Ensures HSM connections are properly closed to avoid dangling connections
83+ - ** HSM Connection Limits** : Hardware security modules have limited concurrent connection pools
84+ - ** Network Stability** : Prevents socket exhaustion and connection timeouts
85+ - ** Security Best Practice** : Minimizes attack surface by closing connections immediately after use
8786
8887### Root Key Creation
8988
@@ -119,7 +118,7 @@ async createRootKey(): Promise<{ rootKey: string }> {
119118
120119``` typescript
121120async generateDataKey (rootKey : string , keySpec : DataKeyTypeType ): Promise < GenerateDataKeyKmsRes > {
122- return await this.withClient(async (client ) => {
121+ return await this.withClient(async (client ) => { // Connection auto-managed to prevent dangling connections
123122 // 1. Create temporary AES key in HSM
124123 const dataKeyName = getRandomHash (32 );
125124 const created = await client .key .create (
@@ -132,11 +131,15 @@ async generateDataKey(rootKey: string, keySpec: DataKeyTypeType): Promise<Genera
132131 // 2. Export plaintext key material
133132 const exportedKey = await client .key .exportSymmetric (dataKeyName );
134133 const plaintextKey = exportedKey .toString (' base64' );
134+
135+ // **CRITICAL SECURITY NOTE**: The plaintextKey contains raw cryptographic material
136+ // and MUST be wiped from memory immediately after encryption operations.
137+ // In production, use secure memory allocation and explicit zeroing.
135138
136139 // 3. Encrypt with root key (envelope encryption)
137140 return {
138141 encryptedKey: encrypt (rootKey , plaintextKey ), // SJCL encryption
139- plaintextKey: plaintextKey , // For immediate use
142+ plaintextKey: plaintextKey , // For immediate use - WIPE AFTER USE
140143 };
141144 });
142145}
@@ -148,6 +151,50 @@ async generateDataKey(rootKey: string, keySpec: DataKeyTypeType): Promise<Genera
1481513 . ** Format Conversion** : Buffer → base64 string
1491524 . ** Envelope Encryption** : Encrypt plaintext with root key
1501535 . ** Automatic Cleanup** : HSM deletes temporary key
154+ 6 . ** ⚠️ MEMORY SECURITY** : Plaintext key must be wiped from memory after use
155+
156+ ### Memory Security Best Practices
157+
158+ ``` typescript
159+ // Example of secure memory handling (recommended for production)
160+ async secureDataKeyGeneration (rootKey : string ): Promise < GenerateDataKeyKmsRes > {
161+ let plaintextKey: string | null = null ;
162+
163+ try {
164+ const result = await this .generateDataKey (rootKey , ' AES-256' );
165+ plaintextKey = result .plaintextKey ;
166+
167+ // Use the plaintext key immediately
168+ const encryptedData = encrypt (plaintextKey , sensitiveData );
169+
170+ return {
171+ encryptedKey : result .encryptedKey ,
172+ encryptedData : encryptedData
173+ };
174+ } finally {
175+ // **CRITICAL**: Explicitly wipe plaintext key from memory
176+ if (plaintextKey ) {
177+ // Overwrite with random data multiple times
178+ for (let i = 0 ; i < 3 ; i ++ ) {
179+ plaintextKey = crypto .randomBytes (plaintextKey .length ).toString (' base64' );
180+ }
181+ plaintextKey = null ;
182+ }
183+
184+ // Force garbage collection (if available)
185+ if (global.gc) {
186+ global .gc ();
187+ }
188+ }
189+ }
190+ ```
191+
192+ ** Security Considerations:**
193+ - ** Immediate Use** : Plaintext keys should be used immediately after generation
194+ - ** Memory Overwriting** : Overwrite memory locations with random data before deallocation
195+ - ** Garbage Collection** : Force GC to clear memory pages containing sensitive data
196+ - ** Process Isolation** : Consider using separate processes for key operations
197+ - ** Hardware Security** : Use HSM-backed secure memory when available
151198
152199### Private Key Storage (POST /key)
153200
@@ -156,8 +203,14 @@ async postKey(rootKey: string, prv: string): Promise<PostKeyKmsRes> {
156203 // 1. Generate fresh data key for this private key
157204 const dataKey = await this .generateDataKey (rootKey , ' AES-256' );
158205
159- // 2. Encrypt private key with data key
160- const encryptedPrv = encrypt (dataKey .plaintextKey , prv );
206+ let encryptedPrv: string ;
207+ try {
208+ // 2. Encrypt private key with data key (use immediately)
209+ encryptedPrv = encrypt (dataKey .plaintextKey , prv );
210+ } finally {
211+ // **CRITICAL**: Wipe plaintext data key from memory immediately after use
212+ // Production code should implement secure memory wiping here
213+ }
161214
162215 return {
163216 encryptedPrv , // Encrypted private key
@@ -169,51 +222,11 @@ async postKey(rootKey: string, prv: string): Promise<PostKeyKmsRes> {
169222}
170223```
171224
172- ** Encryption Layers:**
173- - ** Layer 1** : Private Key → AES-256-CCM → Encrypted Private Key
174- - Uses plaintextKey from HSM-generated data key
175- - SJCL library for AES-256-CCM encryption
176- - ** Layer 2** : Data Key → Local AES → Encrypted Data Key
177- - Uses root key as password
178- - Custom encrypt() function from utils/encrypt.ts
179-
180- ### Private Key Retrieval (GET /key/{pub})
181-
182- ``` typescript
183- async getKey (rootKey : string , keyId : string , options : GetKeyOptions ): Promise < GetKeyKmsRes > {
184- // 1. Decrypt data key using root key
185- const decryptedKey = await this .decryptDataKey (rootKey , options .encryptedDataKey );
186-
187- // 2. Convert data key format
188- const aesKeyBuffer = Buffer .from (decryptedKey .plaintextKey , ' base64' );
189- const password = aesKeyBuffer .toString (' base64' );
190-
191- // 3. Decrypt private key with recovered data key
192- const decryptedPrv = decrypt (password , keyId );
193-
194- return { prv : decryptedPrv };
195- }
196- ```
197-
198- ** Decryption Process:**
199- 1 . ** Data Key Recovery** : Decrypt encrypted data key with root key
200- 2 . ** Format Conversion** : base64 → Buffer → base64 (consistent format)
201- 3 . ** Private Key Decryption** : Use recovered data key to decrypt private key
202-
203- ### Data Key Decryption
204-
205- ``` typescript
206- async decryptDataKey (rootKey : string , encryptedKey : string ): Promise < DecryptDataKeyKmsRes > {
207- return {
208- plaintextKey : decrypt (rootKey , encryptedKey ),
209- };
210- }
211- ```
212-
213- ** Implementation Notes:**
214- - ** Local Operation** : Uses SJCL decryption, not HSM
215- - ** Root Key as Password** : Simple symmetric decryption
216- - ** Performance** : Fast local operation vs. slower HSM calls
225+ ** Memory Security Notes:**
226+ - ** Immediate Encryption** : Use plaintext data key immediately for encryption
227+ - ** Secure Disposal** : Wipe plaintext key from memory after single use
228+ - ** No Persistence** : Never store plaintext data keys in variables or logs
229+ - ** Error Handling** : Ensure memory wiping occurs even if encryption fails
217230
218231## Database Schema
219232
0 commit comments