Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save marclundgren/b508c766301774ddbc046119575443be to your computer and use it in GitHub Desktop.
Save marclundgren/b508c766301774ddbc046119575443be to your computer and use it in GitHub Desktop.
/* https://functional.works-hub.com/learn/how-i-encrypted-a-database-without-storing-the-keys-anywhere-9da75?utm_source=reddit&utm_medium=organicsocial&utm_campaign=j.kaplan */
const crypto = require('crypto');
// Uses the PBKDF2 algorithm to stretch the string 's' to an arbitrary size,
// in a way that is completely deterministic yet impossible to guess without
// knowing the original string
function stretchString(s, salt, outputLength) {
return crypto.pbkdf2Sync(s, salt, 100000, outputLength, 'sha512');
}
// Stretches the password in order to generate a key (for encrypting)
// and a large salt (for hashing)
function keyFromPassword(password){
// We need 24 bytes for the key, and another 48 bytes for the salt
const keyPlusHashingSalt = stretchString(password, 'salt', 24 + 48);
return {
cipherKey: keyPlusHashingSalt.slice(0,24),
hashingSalt: keyPlusHashingSalt.slice(24)
};
}
// Encrypts data using the key generated using the 'keyFromPassword' function
function encrypt(key, sourceData){
const iv = Buffer.alloc(16, 0); // Initialization vector
const cipher = crypto.createCipheriv('aes-192-cbc', key.cipherKey, iv);
let encrypted = cipher.update(sourceData, 'binary', 'binary');
encrypted += cipher.final('binary');
return encrypted;
}
// Decrypts data using the key generated using the 'keyFromPassword' function
function decrypt(key, encryptedData){
const iv = Buffer.alloc(16, 0); // Initialization vector
const decipher = crypto.createDecipheriv('aes-192-cbc', key.cipherKey, iv);
let decrypted = decipher.update(encryptedData, 'binary', 'binary');
decrypted += decipher.final('binary');
return decrypted;
}
// Computes a unique (integer) hash from the given data, using the salt
// we generated from the password (using 'keyFromPassword')
function hash(key, sourceData){
const hashBuffer = stretchString(sourceData, key.hashingSalt, 8);
return hashBuffer.readUIntLE(0, 6);
}
const key = keyFromPassword('Our password');
const encryptedTest = encrypt(key, 'This is a test');
// prints 'This is a test', after encrypting it and decrypting it again
console.log(
decrypt(key, encryptedTest)
);
// Prints the hash 120042280565918, generated from 'This is another test'
console.log(
hash(key, 'This is another test')
);
@marclundgren
Copy link
Author

marclundgren commented May 17, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment