diff --git a/packages/keymaster/src/db-wallet-json-enc.js b/packages/keymaster/src/db-wallet-json-enc.js index 8de20d30..4fcbf0f4 100644 --- a/packages/keymaster/src/db-wallet-json-enc.js +++ b/packages/keymaster/src/db-wallet-json-enc.js @@ -1,10 +1,10 @@ import crypto from 'crypto'; -const algorithm = 'aes-256-cbc'; // Algorithm +const algorithm = 'aes-256-gcm'; // Algorithm const keyLength = 32; // 256 bit AES-256 -const ivLength = 16; // 128-bit AES block size +const ivLength = 12; // 96-bit IV, standard for AES-GCM const saltLength = 16; // 128-bit salt -const iterations = 200000; // PBKDF2 iterations +const iterations = 100000; // PBKDF2 iterations const digest = 'sha512'; // PBKDF2 hash function let baseWallet; @@ -20,7 +20,7 @@ export function setWallet(wallet) { export function saveWallet(wallet, overwrite = false) { if (!passphrase) { - throw new Error('Passphrase not set'); + throw new Error('KC_ENCRYPTED_PASSPHRASE not set'); } const walletJson = JSON.stringify(wallet, null, 4); @@ -29,13 +29,16 @@ export function saveWallet(wallet, overwrite = false) { const iv = crypto.randomBytes(ivLength); const cipher = crypto.createCipheriv(algorithm, key, iv); - let encrypted = cipher.update(walletJson, 'utf8', 'base64'); - encrypted += cipher.final('base64'); + let encrypted = cipher.update(walletJson, 'utf8'); + encrypted = Buffer.concat([encrypted, cipher.final()]); + + const authTag = cipher.getAuthTag(); + const combined = Buffer.concat([encrypted, authTag]); const encryptedData = { salt: salt.toString('base64'), iv: iv.toString('base64'), - data: encrypted + data: combined.toString('base64') }; return baseWallet.saveWallet(encryptedData, overwrite); @@ -43,7 +46,7 @@ export function saveWallet(wallet, overwrite = false) { export function loadWallet() { if (!passphrase) { - throw new Error('Passphrase not set'); + throw new Error('KC_ENCRYPTED_PASSPHRASE not set'); } const encryptedData = baseWallet.loadWallet(); @@ -57,13 +60,17 @@ export function loadWallet() { const salt = Buffer.from(encryptedData.salt, 'base64'); const iv = Buffer.from(encryptedData.iv, 'base64'); - const encryptedJSON = encryptedData.data; + const combined = Buffer.from(encryptedData.data, 'base64'); + + const authTag = combined.subarray(combined.length - 16); + const encryptedJSON = combined.subarray(0, combined.length - 16); const key = crypto.pbkdf2Sync(passphrase, salt, iterations, keyLength, digest); const decipher = crypto.createDecipheriv(algorithm, key, iv); + decipher.setAuthTag(authTag); let decrypted; try { - decrypted = decipher.update(encryptedJSON, 'base64', 'utf8'); + decrypted = decipher.update(encryptedJSON, null, 'utf8'); decrypted += decipher.final('utf8'); } catch (err) { throw new Error('Incorrect passphrase.'); diff --git a/packages/keymaster/src/db-wallet-web-enc.js b/packages/keymaster/src/db-wallet-web-enc.js index 04bfcff9..6448bdf5 100644 --- a/packages/keymaster/src/db-wallet-web-enc.js +++ b/packages/keymaster/src/db-wallet-web-enc.js @@ -2,7 +2,7 @@ const algorithm = 'AES-GCM'; const kdf = 'PBKDF2'; const hash = 'SHA-512'; const keyLength = 256; // 256 bit AES-256 -const ivLength = 12; // 128-bit AES block size +const ivLength = 12; // 96-bit IV, standard for AES-GCM const saltLength = 16; // 128-bit salt const iterations = 100000; // PBKDF2 iterations diff --git a/services/gatekeeper/client/src/App.js b/services/gatekeeper/client/src/App.js index 9a51f9cf..1d0c41ee 100644 --- a/services/gatekeeper/client/src/App.js +++ b/services/gatekeeper/client/src/App.js @@ -23,14 +23,13 @@ function App() { useEffect(() => { async function initializeWallet() { - let wallet = wallet_web; - const walletData = await wallet.loadWallet(); + const walletData = await wallet_web.loadWallet(); if (walletData && walletData.salt && walletData.iv && walletData.data) { setIsEncrypted(true); setModalAction('decrypt'); } else { - keymaster.start({ gatekeeper, wallet, cipher }); + keymaster.start({ gatekeeper, wallet_web, cipher }); setIsReady(true); } } diff --git a/tests/keymaster.test.js b/tests/keymaster.test.js index da5e0121..aafbb499 100644 --- a/tests/keymaster.test.js +++ b/tests/keymaster.test.js @@ -147,7 +147,7 @@ describe('loadWallet', () => { throw new ExpectedExceptionError(); } catch (error) { expect(ok).toBe(true); - expect(error.message).toBe('Passphrase not set'); + expect(error.message).toBe('KC_ENCRYPTED_PASSPHRASE not set'); } }); @@ -303,7 +303,7 @@ describe('saveWallet', () => { await keymaster.saveWallet(mockWallet); throw new ExpectedExceptionError(); } catch (error) { - expect(error.message).toBe('Passphrase not set'); + expect(error.message).toBe('KC_ENCRYPTED_PASSPHRASE not set'); } });