Skip to content

Commit

Permalink
Use AES encryption/decryption with the aes-256-gcm by using random in…
Browse files Browse the repository at this point in the history
…it vector, salt, and user encryption key
  • Loading branch information
bjarneo committed Jul 9, 2021
1 parent a148c7c commit 43ec153
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 29 deletions.
55 changes: 32 additions & 23 deletions src/server/helpers/crypto.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,54 @@
const crypto = require('crypto');
const config = require('config');

const ALGORITHM = 'aes-256-ctr';
const ALGORITHM = 'aes-256-gcm';
const SECRET_KEY = config.get('secret_key');

// Change algorithm? https://stackoverflow.com/questions/1220751/how-to-choose-an-aes-encryption-mode-cbc-ecb-ctr-ocb-cfb
function encrypt(text, userEncryptionKey) {
const iv = crypto.randomBytes(16);

function encrypt(text, key) {
const IV = crypto.randomBytes(16);
const salt = crypto.randomBytes(64);

// We need a 32 length key for the cipher
const MASTER_KEY = crypto
.createHash('sha256')
.update(SECRET_KEY + key)
.digest('hex')
.substring(0, 32);
.update(SECRET_KEY + userEncryptionKey)
.digest('hex');

const key = crypto.pbkdf2Sync(MASTER_KEY, salt, 2145, 32, 'sha512');

const cipher = crypto.createCipheriv(ALGORITHM, key, iv);

const cipher = crypto.createCipheriv(ALGORITHM, MASTER_KEY, IV);
// encrypt the given text
const encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]);

const encrypted = Buffer.concat([cipher.update(text), cipher.final()]);
// extract the auth tag
const tag = cipher.getAuthTag();

return {
iv: IV.toString('hex'),
content: encrypted.toString('hex'),
};
// generate output
return Buffer.concat([salt, iv, tag, encrypted]).toString('hex');
}

function decrypt(hash, key) {
function decrypt(encryptedData, userEncryptionKey) {
const data = Buffer.from(encryptedData, 'hex');

// We need a 32 length key for the cipher
const MASTER_KEY = crypto
.createHash('sha256')
.update(SECRET_KEY + key)
.digest('hex')
.substring(0, 32);
.update(SECRET_KEY + userEncryptionKey)
.digest('hex');

// convert data to buffers
const salt = data.slice(0, 64);
const iv = data.slice(64, 80);
const tag = data.slice(80, 96);
const text = data.slice(96);

const key = crypto.pbkdf2Sync(MASTER_KEY, salt, 2145, 32, 'sha512');

const decipher = crypto.createDecipheriv(ALGORITHM, MASTER_KEY, Buffer.from(hash.iv, 'hex'));
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
decipher.setAuthTag(tag);

const decrypted = Buffer.concat([
decipher.update(Buffer.from(hash.content, 'hex')),
decipher.final(),
]);
const decrypted = Buffer.concat([decipher.update(Buffer.from(text, 'hex')), decipher.final()]);

return decrypted;
}
Expand Down
6 changes: 4 additions & 2 deletions src/server/services/do.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ async function upload(encryptionKey, fileUpload) {
.upload({
Bucket: config.get('do.spaces.bucket'),
Key: `${config.get('do.spaces.folder')}/images/${filename}.json`,
Body: JSON.stringify(encryptedFile),
Body: JSON.stringify({ encryptedFile }),
})
.promise();

Expand All @@ -41,7 +41,9 @@ async function download(key, encryptionKey) {
})
.promise();

return decrypt(JSON.parse(data.Body), encryptionKey);
const { encryptedFile } = JSON.parse(data.Body);

return decrypt(encryptedFile, encryptionKey);
}

async function remove(key) {
Expand Down
4 changes: 0 additions & 4 deletions tests/server/helpers/crypto.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ describe('Crypto', () => {
describe('#encrypt(string)', () => {
it('should encrypt, and decrypt a secret', async () => {
const encrypted = await encrypt(SECRET, RANDOM_KEY);

assert.equal('iv' in encrypted, true);
assert.equal('content' in encrypted, true);

const decrypted = await decrypt(encrypted, RANDOM_KEY);

assert.equal(decrypted, SECRET);
Expand Down

0 comments on commit 43ec153

Please sign in to comment.