@@ -30,7 +30,10 @@ export async function encryptWithCipher({
3030 algorithm ?: string ;
3131 initializationVectorSize ?: number ;
3232} ) {
33- // Derive a cryptographic key from the input key using SHA-256
33+ // Generate a random salt for PBKDF2
34+ const salt = crypto . getRandomValues ( new Uint8Array ( initializationVectorSize ) ) ;
35+
36+ // Derive a cryptographic key from the input key using PBKDF2
3437 const keyMaterial = await crypto . subtle . importKey (
3538 'raw' ,
3639 new TextEncoder ( ) . encode ( key ) ,
@@ -42,7 +45,7 @@ export async function encryptWithCipher({
4245 const cryptoKey = await crypto . subtle . deriveKey (
4346 {
4447 name : 'PBKDF2' ,
45- salt : new Uint8Array ( initializationVectorSize ) , // Use a fixed salt for simplicity
48+ salt,
4649 iterations : 100000 ,
4750 hash : 'SHA-256' ,
4851 } ,
@@ -62,9 +65,10 @@ export async function encryptWithCipher({
6265 new TextEncoder ( ) . encode ( data ) ,
6366 ) ;
6467
65- // Return the encrypted data as a base64 string
68+ // Return the encrypted data as a base64 string with salt included
6669 return JSON . stringify ( {
6770 iv : Buffer . from ( iv ) . toString ( 'base64' ) ,
71+ salt : Buffer . from ( salt ) . toString ( 'base64' ) ,
6872 ciphertext : Buffer . from ( encrypted ) . toString ( 'base64' ) ,
6973 } ) ;
7074}
@@ -77,12 +81,27 @@ export async function decryptWithCipher({
7781 key : string ;
7882 algorithm ?: string ;
7983} ) {
84+ // Parse the encrypted data JSON - salt is optional for backward compatibility
8085 const _encryptedData : {
8186 iv : string ;
87+ salt ?: string ;
8288 ciphertext : string ;
8389 } = JSON . parse ( encryptedDataJSON ) ;
8490
85- // Derive a cryptographic key from the input key using SHA-256
91+ // Decode IV from base64
92+ const decodedIv = Buffer . from ( _encryptedData . iv , 'base64' ) ;
93+
94+ // Handle salt - support both new format (with salt) and legacy format (without salt)
95+ let salt : BufferSource ;
96+ if ( _encryptedData . salt && _encryptedData . salt !== '' ) {
97+ // New format: use the provided salt
98+ salt = Buffer . from ( _encryptedData . salt , 'base64' ) ;
99+ } else {
100+ // Legacy format: use zero-filled salt of IV length for backward compatibility
101+ salt = new Uint8Array ( decodedIv . length ) ;
102+ }
103+
104+ // Derive a cryptographic key from the input key using PBKDF2
86105 const keyMaterial = await crypto . subtle . importKey (
87106 'raw' ,
88107 new TextEncoder ( ) . encode ( key ) ,
@@ -94,7 +113,7 @@ export async function decryptWithCipher({
94113 const cryptoKey = await crypto . subtle . deriveKey (
95114 {
96115 name : 'PBKDF2' ,
97- salt : new Uint8Array ( Buffer . from ( _encryptedData . iv , 'base64' ) . length ) , // Use the same salt size as IV
116+ salt,
98117 iterations : 100000 ,
99118 hash : 'SHA-256' ,
100119 } ,
@@ -104,8 +123,7 @@ export async function decryptWithCipher({
104123 [ 'decrypt' ] ,
105124 ) ;
106125
107- // Decode the IV and encrypted data from base64
108- const decodedIv = Buffer . from ( _encryptedData . iv , 'base64' ) ;
126+ // Decode the ciphertext from base64
109127 const decodedEncryptedData = Buffer . from ( _encryptedData . ciphertext , 'base64' ) ;
110128
111129 // Decrypt the data
0 commit comments