SEARCH-116-GCM

1. Removed the key creation in crypto
2. Hash SHA256
3. Changed the encrypted zip name
This commit is contained in:
Keerthi Niranjan 2017-08-21 13:39:07 +05:30 committed by Keerthi Niranjan
parent 5e738a3eed
commit e01e334fa9
3 changed files with 32 additions and 73 deletions

View File

@ -2,9 +2,6 @@
* AES GCM Stream
* This module exports encrypt and decrypt stream constructors which can be
* used to protect data with authenticated encryption.
*
* Helper methods are also provided to do things like generate secure keys
* and salt.
*/
'use strict';
@ -12,11 +9,8 @@ let stream = require('stream');
let Transform = stream.Transform;
let util = require('util');
let crypto = require('crypto');
let forge = require('node-forge');
let PBKDF2_PASS_LENGTH = 256;
let PBKDF2_SALT_LENGTH = 32;
let PBKDF2_ITERATIONS = 5000;
let PBKDF2_DIGEST = 'sha256';
let KEY_LENGTH = 32; // bytes
let GCM_NONCE_LENGTH = 12; //bytes
let GCM_MAC_LENGTH = 16; //bytes
@ -34,44 +28,33 @@ let validateAndConvertKey = function(key) {
if (key && key instanceof Buffer && key.length === KEY_LENGTH) {
return key;
} else if (key && typeof key === 'string') {
// Because we don't have a reliable way to test string encoding, we assume that a string type
// key was created by the createEncodedKey method and that it is using the keyEncoding which
// has been set on the module, whether that's the default or something explicitly set by the
// user via the setKeyEncoding method.
let bufKey = new Buffer(key, keyEncoding);
let md = forge.md.sha256.create();
md.update(key);
let bufKey = new Buffer(bits2b64(md.digest().getBytes()), keyEncoding);
if (bufKey.length !== KEY_LENGTH) {
let encodingErrorMessage = 'Provided key string is either of an unknown encoding (expected: ' +
keyEncoding + ') or the wrong length.';
throw new Error(encodingErrorMessage);
}
return bufKey;
} else {
let message = 'The key options property is required! Expected ' +
keyEncoding + ' encoded string or a buffer.';
throw new Error(message);
}
let message = 'The key options property is required! Expected ' +
keyEncoding + ' encoded string or a buffer.';
throw new Error(message);
};
/**
* encode bits to b64
* @param bits
* @returns {*}
*/
let bits2b64 = function (bits) {
return forge.util.encode64(bits);
};
exports.encrypt = EncryptionStream;
exports.decrypt = DecryptionStream;
/**
* getEncoding
* Helper which returns the current encoding being used for keys
* @returns {string}
*/
exports.getKeyEncoding = function() {
return keyEncoding;
};
/**
* setEncoding
* Helper to set the encoding being used for keys
* @param enc
*/
exports.setKeyEncoding = function(enc) {
keyEncoding = Buffer.isEncoding(enc) ? enc : keyEncoding;
};
/**
* createSalt
@ -88,32 +71,6 @@ exports.createSalt = function(length) {
}
};
/**
* createKeyBuffer
* Method which returns a buffer representing a secure key generated with PBKDF2
* @returns Buffer
*/
exports.createKeyBuffer = function() {
try {
let passphrase = crypto.randomBytes(PBKDF2_PASS_LENGTH);
let salt = this.createSalt(PBKDF2_SALT_LENGTH);
return crypto.pbkdf2Sync(passphrase, salt, PBKDF2_ITERATIONS, KEY_LENGTH, PBKDF2_DIGEST);
} catch (ex) {
console.error('Problem reading random data and generating a key!');
throw ex;
}
};
/**
* createEncodedKey
* Helper method that returns an encoded key
* @returns string
* @throws error
*/
exports.createEncodedKey = function() {
return exports.createKeyBuffer().toString(keyEncoding);
};
/**
* EncryptionStream
* A constructor which returns an encryption stream
@ -151,7 +108,6 @@ EncryptionStream.prototype._flush = function(cb) {
cb();
};
/**
* DecryptionStream
* A constructor which returns a decryption stream
@ -179,13 +135,14 @@ util.inherits(DecryptionStream, Transform);
DecryptionStream.prototype._transform = function(chunk, enc, cb) {
let chunkLength = chunk.length;
let chunkOffset = 0;
let _chunk = chunk;
if (!this._started) {
if (this._nonceBytesRead < GCM_NONCE_LENGTH) {
let nonceRemaining = GCM_NONCE_LENGTH - this._nonceBytesRead;
chunkOffset = chunkLength <= nonceRemaining ? chunkLength : nonceRemaining;
chunk.copy(this._nonce, this._nonceBytesRead, 0, chunkOffset);
chunk = chunk.slice(chunkOffset);
chunkLength = chunk.length;
_chunk.copy(this._nonce, this._nonceBytesRead, 0, chunkOffset);
_chunk = _chunk.slice(chunkOffset);
chunkLength = _chunk.length;
this._nonceBytesRead += chunkOffset;
}
@ -199,7 +156,7 @@ DecryptionStream.prototype._transform = function(chunk, enc, cb) {
// We can't use an else because we have no idea how long our chunks will be
// all we know is that once we've got a nonce we can start storing cipher text
if (this._started) {
this._cipherTextChunks.push(chunk);
this._cipherTextChunks.push(_chunk);
}
cb();
@ -222,7 +179,7 @@ DecryptionStream.prototype._flush = function(cb) {
decrypted.forEach(function(item) {
this.push(item);
}, this);
cb();
return cb();
};
function pullOutMac(array) {
@ -242,7 +199,7 @@ function pullOutMac(array) {
}
}
if (macByteCount !== GCM_MAC_LENGTH) {
return;
return null;
}
macBits.reverse();
return Buffer.concat(macBits, GCM_MAC_LENGTH);

View File

@ -24,6 +24,7 @@ class Crypto {
// will be handling after implementing in client app
this.indexDataFolder = INDEX_DATA_FOLDER + '_' + userId + '_' + INDEX_VERSION;
this.permanentIndexFolderName = 'search_index_' + userId + '_' + INDEX_VERSION;
this.dump = TEMPORARY_PATH;
this.key = "XrwVgWR4czB1a9scwvgRUNbXiN3W0oWq7oUBenyq7bo="; // temporary only
this.encryptedIndex = 'encryptedIndex.enc';
@ -44,18 +45,18 @@ class Crypto {
return;
}
let output = fs.createWriteStream(`${this.dump}/content.zip`);
let output = fs.createWriteStream(`${this.dump}/${this.permanentIndexFolderName}.zip`);
zipArchive.on('end', () => {
if (!fs.existsSync(`${this.dump}/content.zip`)){
if (!fs.existsSync(`${this.dump}/${this.permanentIndexFolderName}.zip`)){
// will be handling after implementing in client app
reject();
return;
}
const input = fs.createReadStream(`${this.dump}/content.zip`);
const input = fs.createReadStream(`${this.dump}/${this.permanentIndexFolderName}.zip`);
const outputEncryption = fs.createWriteStream(this.encryptedIndex);
let config = {
key: this.key
@ -67,7 +68,7 @@ class Crypto {
reject(new Error(err));
}
if (!this.zipErrored) {
fs.unlinkSync(`${this.dump}/content.zip`);
fs.unlinkSync(`${this.dump}/${this.permanentIndexFolderName}.zip`);
Crypto.deleteFolderRecursive(this.indexDataFolder)
.then(function () {
resolve(res);

View File

@ -89,17 +89,18 @@
"dependencies": {
"@paulcbetts/system-idle-time": "^1.0.4",
"appdirectory": "^0.1.0",
"archiver": "^2.0.0",
"async.map": "^0.5.2",
"async.mapseries": "^0.5.2",
"auto-launch": "^5.0.1",
"electron-dl": "^1.9.0",
"electron-spellchecker": "^1.2.0",
"electron-squirrel-startup": "^1.0.0",
"extract-zip": "^1.6.5",
"filesize": "^3.5.10",
"keymirror": "0.1.1",
"winreg": "^1.2.3",
"archiver": "latest",
"extract-zip": "latest"
"node-forge": "^0.7.1",
"winreg": "^1.2.3"
},
"optionalDependencies": {
"screen-snippet": "git+https://github.com/symphonyoss/ScreenSnippet.git#v1.0.1"