Generate random salt for volume headers and check volumes for such header

This commit is contained in:
Johannes Zellner
2013-11-28 21:16:10 -08:00
parent d6f2a3ec48
commit cbb80c6b01
3 changed files with 56 additions and 23 deletions
+24 -11
View File
@@ -5,30 +5,43 @@ var crypto = require('crypto');
// This code is taken from https://github.com/fabdrol/node-aes-helper
module.exports = {
algorithm: 'AES-256-CBC',
salt: 'RgA{[A0+#I@]CK|U)}>yv9Y58CkJp3}UOV#xK,Lz@8@VE>?9fR;K]isV*+qX10o4',
key: function (password) {
var key = this.salt + password;
key: function (password, salt) {
var key = salt.toString('utf8') + password;
var hash = crypto.createHash('sha1');
hash.update(key, 'utf8');
return hash.digest('hex');
},
encrypt: function (plain, password) {
var key = this.key(password);
encrypt: function (plain, password, salt) {
var key = this.key(password, salt);
var cipher = crypto.createCipher(this.algorithm, key);
var crypted = cipher.update(plain, 'utf8', 'hex');
crypted += cipher.final('hex');
var crypted;
try {
crypted = cipher.update(plain, 'utf8', 'hex');
crypted += cipher.final('hex');
} catch (e) {
console.error('Encryption error:', e);
crypted = '';
}
return crypted;
},
decrypt: function (crypted, password) {
var key = this.key(password);
decrypt: function (crypted, password, salt) {
var key = this.key(password, salt);
var decipher = crypto.createDecipher(this.algorithm, key);
var decoded = decipher.update(crypted, 'hex', 'utf8');
decoded += decipher.final('utf8');
var decoded;
try {
decoded = decipher.update(crypted, 'hex', 'utf8');
decoded += decipher.final('utf8');
} catch (e) {
console.error('Decryption error:', e);
decoded = '';
}
return decoded;
}
+3
View File
@@ -64,6 +64,9 @@ Server.prototype._requirePassword = function (req, res, next) {
return next(new HttpError(401, 'Wrong password entered'));
}
// add password to the request's user object for further use
req.user.password = req.body.password;
next();
});
};
+29 -12
View File
@@ -24,6 +24,8 @@ exports = module.exports = {
};
var REPO_SUBFOLDER = 'repo';
var VOLUME_META_FILENAME = '.meta';
var CRYPTO_SALT_SIZE = 64; // 512-bit salt
// http://dustinsenos.com/articles/customErrorsInNode
// http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
@@ -77,7 +79,7 @@ Volume.prototype._resolveVolumeMountPoint = function() {
};
Volume.prototype._initMetaDatabase = function () {
this.meta = new db.Table(this.dataPath + '/.meta', {
this.meta = new db.Table(path.join(this.dataPath, VOLUME_META_FILENAME), {
username: { type: 'String', hashKey: true },
passwordCypher: { type: 'String', priv: true }
});
@@ -122,7 +124,8 @@ Volume.prototype.open = function (username, password, callback) {
return callback(error);
}
var volPassword = aes.decrypt(record.passwordCypher, password);
var saltBuffer = new Buffer(record.salt, 'hex');
var volPassword = aes.decrypt(record.passwordCypher, password, saltBuffer);
that.encfs.mount(volPassword, function (error, result) {
if (error) {
@@ -263,24 +266,32 @@ Volume.prototype.listFiles = function (directory, callback) {
};
Volume.prototype.addUser = function (user, password, callback) {
var that = this;
if (!this.meta) {
debug('Invalid volume "' + this.name + '". Misses the meta database.');
return callback(new VolumeError(null, VolumeError.META_MISSING));
}
// TODO salt is currently fixed in aes-helper module - Johannes
var record = {
username: user.username,
passwordCypher: aes.encrypt(password, user.password)
};
this.meta.put(record, function (error) {
crypto.randomBytes(CRYPTO_SALT_SIZE, function (error, salt) {
if (error) {
debug('Unable to add user to meta db. ' + safe.JSON.stringify(error));
return callback(error);
return callback(new VolumeError('Failed to generate random bytes', VolumeError.INTERNAL_ERROR));
}
return callback(null, record);
var record = {
username: user.username,
salt: salt.toString('hex'),
passwordCypher: aes.encrypt(password, user.password, salt),
};
that.meta.put(record, function (error) {
if (error) {
debug('Unable to add user to meta db. ' + safe.JSON.stringify(error));
return callback(error);
}
return callback(null, record);
});
});
};
@@ -407,6 +418,12 @@ function getVolume(name, username, config) {
return null;
}
// Check if that volume has a meta information file, if not it is not created properly or broken
if (!safe.fs.existsSync(path.join(vol.dataPath, VOLUME_META_FILENAME))) {
debug('Volume "' + name + '" for user "' + username + '" does not have meta information, it is possibly broken.');
return null;
}
vol.repo = new Repo(path.join(vol.mountPoint, REPO_SUBFOLDER), vol.tmpPath);
return vol;