mirror of https://github.com/BTCPrivate/copay.git
fix compatibility issues
This commit is contained in:
parent
7207f03bd1
commit
7942048dd1
|
@ -65,6 +65,13 @@ var defaultConfig = {
|
|||
EncryptedInsightStorage: {
|
||||
url: 'https://insight.bitpay.com:443/api/email',
|
||||
//url: 'http://localhost:3001/api/email'
|
||||
|
||||
// This KDF parameters are for the passphrase for Insight authentication
|
||||
// Are not related to encryption itself.
|
||||
//
|
||||
// WARN: Changing this parameters would prevent accesing previously created profiles.
|
||||
iterations: 1000,
|
||||
salt: 'jBbYTj8zTrOt6V',
|
||||
},
|
||||
|
||||
GoogleDrive: {
|
||||
|
|
|
@ -93,7 +93,9 @@ angular.module('copayApp.controllers').controller('SettingsController', function
|
|||
defaultLanguage: $scope.selectedLanguage.isoCode,
|
||||
plugins: plugins,
|
||||
logLevel: $scope.selectedLogLevel.name,
|
||||
EncryptedInsightStorage: {url: insightSettings.livenet.url + '/api/email' },
|
||||
EncryptedInsightStorage: _.extend(config.EncryptedInsightStorage, {
|
||||
url: insightSettings.livenet.url + '/api/email'
|
||||
}),
|
||||
}));
|
||||
|
||||
// Go home reloading the application
|
||||
|
|
|
@ -7,15 +7,29 @@ function EncryptedInsightStorage(config) {
|
|||
}
|
||||
inherits(EncryptedInsightStorage, InsightStorage);
|
||||
|
||||
|
||||
EncryptedInsightStorage.prototype._brokenDecrypt = function(body) {
|
||||
var key = cryptoUtil.kdf(this.password + this.email, 'mjuBtGybi/4=', 100);
|
||||
log.debug('Trying legacy decrypt')
|
||||
var decryptedJson = cryptoUtil.decrypt(key, body);
|
||||
return decryptedJson;
|
||||
};
|
||||
|
||||
EncryptedInsightStorage.prototype.getItem = function(name, callback) {
|
||||
var key = cryptoUtil.kdf(this.password + this.email);
|
||||
InsightStorage.prototype.getItem.apply(this, [name,
|
||||
function(err, body) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
var decryptedJson = cryptoUtil.decrypt(key, body);
|
||||
var decryptedJson = cryptoUtil.decrypt(this.password, body);
|
||||
log.debug('Could not decrypt value using current decryption schema');
|
||||
|
||||
if (!decryptedJson) {
|
||||
decryptedJson = this._brokenDecrypt(body);
|
||||
}
|
||||
|
||||
if (!decryptedJson) {
|
||||
log.debug('Could not decrypt value.');
|
||||
return callback('PNOTFOUND');
|
||||
}
|
||||
return callback(null, decryptedJson);
|
||||
|
@ -24,13 +38,11 @@ EncryptedInsightStorage.prototype.getItem = function(name, callback) {
|
|||
};
|
||||
|
||||
EncryptedInsightStorage.prototype.setItem = function(name, value, callback) {
|
||||
var key = cryptoUtil.kdf(this.password + this.email);
|
||||
var record = cryptoUtil.encrypt(key, value);
|
||||
var record = cryptoUtil.encrypt(this.password, value);
|
||||
InsightStorage.prototype.setItem.apply(this, [name, record, callback]);
|
||||
};
|
||||
|
||||
EncryptedInsightStorage.prototype.removeItem = function(name, callback) {
|
||||
var key = cryptoUtil.kdf(this.password + this.email);
|
||||
InsightStorage.prototype.removeItem.apply(this, [name, callback]);
|
||||
};
|
||||
|
||||
|
|
|
@ -7,26 +7,47 @@ function EncryptedLocalStorage(config) {
|
|||
}
|
||||
inherits(EncryptedLocalStorage, LocalStorage);
|
||||
|
||||
|
||||
EncryptedLocalStorage.prototype._brokenDecrypt = function(body) {
|
||||
var key = cryptoUtil.kdf(this.password + this.email, 'mjuBtGybi/4=', 100);
|
||||
log.debug('Trying legacy decrypt')
|
||||
var decryptedJson = cryptoUtil.decrypt(key, body);
|
||||
return decryptedJson;
|
||||
};
|
||||
|
||||
|
||||
EncryptedLocalStorage.prototype.getItem = function(name, callback) {
|
||||
var key = cryptoUtil.kdf(this.password + this.email);
|
||||
LocalStorage.prototype.getItem.apply(this, [name,
|
||||
function(err, body) {
|
||||
var decryptedJson = cryptoUtil.decrypt(key, body);
|
||||
var decryptedJson = cryptoUtil.decrypt(this.password, body);
|
||||
log.debug('Could not decrypt value using current decryption schema');
|
||||
|
||||
if (!decryptedJson) {
|
||||
decryptedJson = this._brokenDecrypt(body);
|
||||
}
|
||||
|
||||
if (!decryptedJson) {
|
||||
log.debug('Could not decrypt value.');
|
||||
return callback('PNOTFOUND');
|
||||
}
|
||||
|
||||
return callback(null, decryptedJson);
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
EncryptedLocalStorage.prototype.setItem = function(name, value, callback) {
|
||||
var key = cryptoUtil.kdf(this.password + this.email);
|
||||
if (!_.isString(value)) {
|
||||
value = JSON.stringify(value);
|
||||
}
|
||||
var record = cryptoUtil.encrypt(key, value);
|
||||
var record = cryptoUtil.encrypt(this.password, value);
|
||||
LocalStorage.prototype.setItem.apply(this, [name, record, callback]);
|
||||
};
|
||||
|
||||
EncryptedLocalStorage.prototype.removeItem = function(name, callback) {
|
||||
InsightStorage.prototype.removeItem.apply(this, [name, callback]);
|
||||
};
|
||||
|
||||
|
||||
|
||||
module.exports = EncryptedLocalStorage;
|
||||
|
|
|
@ -5,14 +5,18 @@ var querystring = require('querystring');
|
|||
var Identity = require('../models/Identity');
|
||||
|
||||
var SEPARATOR = '|';
|
||||
var BODY = 'IR7GCUVgaLGe4LCtXjtUo4hsH8BO67jIrBKCeFiYOQ7CKWVPx3FshqTM';
|
||||
|
||||
function InsightStorage(config) {
|
||||
this.type = 'DB';
|
||||
this.storeUrl = config.url || 'https://insight.bitpay.com:443/api/email',
|
||||
this.request = config.request || request;
|
||||
|
||||
this.iterations = config.iterations || 1000;
|
||||
this.salt = config.salt || 'jBbYTj8zTrOt6V';
|
||||
}
|
||||
|
||||
InsightStorage.prototype.init = function () {};
|
||||
InsightStorage.prototype.init = function() {};
|
||||
|
||||
InsightStorage.prototype.setCredentials = function(email, password, opts) {
|
||||
this.email = email;
|
||||
|
@ -49,16 +53,34 @@ InsightStorage.prototype.getItem = function(name, callback) {
|
|||
});
|
||||
};
|
||||
|
||||
/* This key has not need to have the same
|
||||
* settings(salt,iterations) as the kdf for wallet/profile encryption
|
||||
* in Encrpted*Storage. And, actually, it good for the user to be able
|
||||
* to change the settings con config.js to modify salt / iterations but
|
||||
* mantain the same key & passphrase. This is why those settings are
|
||||
* not shared.
|
||||
*/
|
||||
InsightStorage.prototype.getKey = function() {
|
||||
if (!this._cachedKey) {
|
||||
this._cachedKey = cryptoUtil.kdf(this.password + SEPARATOR + this.email, this.salt, this.iterations);
|
||||
}
|
||||
return this._cachedKey;
|
||||
};
|
||||
|
||||
InsightStorage.prototype.getPassphrase = function() {
|
||||
return cryptoUtil.hmac(this.getKey(), this.password);
|
||||
return cryptoUtil.hmac(this.getKey(), BODY);
|
||||
};
|
||||
|
||||
InsightStorage.prototype._makeGetRequest = function(passphrase, key, callback) {
|
||||
var authHeader = new buffers.Buffer(this.email + ':' + passphrase).toString('base64');
|
||||
var retrieveUrl = this.storeUrl + '/retrieve';
|
||||
this.request.get({
|
||||
url: retrieveUrl + '?' + querystring.encode({key: key}),
|
||||
headers: {'Authorization': authHeader}
|
||||
url: retrieveUrl + '?' + querystring.encode({
|
||||
key: key
|
||||
}),
|
||||
headers: {
|
||||
'Authorization': authHeader
|
||||
}
|
||||
},
|
||||
function(err, response, body) {
|
||||
if (err) {
|
||||
|
@ -91,16 +113,9 @@ InsightStorage.prototype._brokenGetItem = function(name, callback) {
|
|||
});
|
||||
};
|
||||
|
||||
InsightStorage.prototype.getKey = function() {
|
||||
if (!this._cachedKey) {
|
||||
this._cachedKey = cryptoUtil.kdf(this.password + SEPARATOR + this.email);
|
||||
}
|
||||
return this._cachedKey;
|
||||
};
|
||||
|
||||
InsightStorage.prototype._makeBrokenSecret = function() {
|
||||
var key = cryptoUtil.kdf(this.password + this.email);
|
||||
return cryptoUtil.kdf(key, this.password);
|
||||
var key = cryptoUtil.kdf(this.password + this.email, 'mjuBtGybi/4=', 100);
|
||||
return cryptoUtil.kdf(key, this.password, 100);
|
||||
};
|
||||
|
||||
InsightStorage.prototype._changePassphrase = function(callback) {
|
||||
|
@ -111,7 +126,9 @@ InsightStorage.prototype._changePassphrase = function(callback) {
|
|||
var url = this.storeUrl + '/change_passphrase';
|
||||
this.request.post({
|
||||
url: url,
|
||||
headers: {'Authorization': authHeader},
|
||||
headers: {
|
||||
'Authorization': authHeader
|
||||
},
|
||||
body: querystring.encode({
|
||||
newPassphrase: newPassphrase
|
||||
})
|
||||
|
@ -135,7 +152,9 @@ InsightStorage.prototype.setItem = function(name, value, callback) {
|
|||
var registerUrl = this.storeUrl + '/save';
|
||||
this.request.post({
|
||||
url: registerUrl,
|
||||
headers: {'Authorization': authHeader},
|
||||
headers: {
|
||||
'Authorization': authHeader
|
||||
},
|
||||
body: querystring.encode({
|
||||
key: name,
|
||||
record: value
|
||||
|
|
|
@ -5,16 +5,17 @@ var querystring = require('querystring');
|
|||
describe('insight storage plugin', function() {
|
||||
|
||||
var requestMock = sinon.stub();
|
||||
var storage = new InsightStorage({request: requestMock});
|
||||
var storage = new InsightStorage({
|
||||
request: requestMock
|
||||
});
|
||||
var email = 'john@doe.com';
|
||||
var password = '1234';
|
||||
|
||||
var data = '{"random": true}';
|
||||
var namespace = 'profile::0000000000000000000000000000000000000000';
|
||||
|
||||
var oldSecret = 'rFA+F/N+ZvKXp717zBdfCKYQ5v9Fjry0W6tautj5etIH'
|
||||
+ 'KLQliZBEYXA7AXjTJ9K3DglzGWJKost3QJUCMbhM/A=='
|
||||
var newSecret = '+72pwnQ/ukrXVXZ/L4vFeiykwn522uVz0J6p81TGXvI=';
|
||||
var oldSecret = 'rFA+F/N+ZvKXp717zBdfCKYQ5v9Fjry0W6tautj5etIH' + 'KLQliZBEYXA7AXjTJ9K3DglzGWJKost3QJUCMbhM/A=='
|
||||
var newSecret = 'rcNEqxJZV1fsrZgpwpET8D9aCsCIYXS7XOGlsONgEiA=';
|
||||
|
||||
var setupStorageCredentials = function() {
|
||||
storage.setCredentials(email, password);
|
||||
|
@ -29,7 +30,9 @@ describe('insight storage plugin', function() {
|
|||
|
||||
var setupForCreation = function() {
|
||||
requestMock.get.onFirstCall().callsArgWith(1, 'Not found');
|
||||
requestMock.post.onFirstCall().callsArgWith(1, null, {statusCode: 200});
|
||||
requestMock.post.onFirstCall().callsArgWith(1, null, {
|
||||
statusCode: 200
|
||||
});
|
||||
};
|
||||
|
||||
it('should be able to create a namespace for storage', function(done) {
|
||||
|
@ -43,7 +46,9 @@ describe('insight storage plugin', function() {
|
|||
});
|
||||
|
||||
var setupForRetrieval = function() {
|
||||
requestMock.get.onFirstCall().callsArgWith(1, null, {statusCode: 200}, data);
|
||||
requestMock.get.onFirstCall().callsArgWith(1, null, {
|
||||
statusCode: 200
|
||||
}, data);
|
||||
};
|
||||
|
||||
it('should be able to retrieve data in a namespace', function(done) {
|
||||
|
@ -57,8 +62,10 @@ describe('insight storage plugin', function() {
|
|||
});
|
||||
});
|
||||
|
||||
var setupForSave = function () {
|
||||
requestMock.post.onFirstCall().callsArgWith(1, null, {statusCode: 200});
|
||||
var setupForSave = function() {
|
||||
requestMock.post.onFirstCall().callsArgWith(1, null, {
|
||||
statusCode: 200
|
||||
});
|
||||
};
|
||||
|
||||
it('should be able to overwrite data when using same password', function(done) {
|
||||
|
@ -95,10 +102,16 @@ describe('insight storage plugin', function() {
|
|||
|
||||
var setupForOldData = function() {
|
||||
requestMock.get = sinon.stub();
|
||||
requestMock.get.onFirstCall().callsArgWith(1, null, {statusCode: 403});
|
||||
requestMock.get.onSecondCall().callsArgWith(1, null, {statusCode: 200}, data);
|
||||
requestMock.get.onFirstCall().callsArgWith(1, null, {
|
||||
statusCode: 403
|
||||
});
|
||||
requestMock.get.onSecondCall().callsArgWith(1, null, {
|
||||
statusCode: 200
|
||||
}, data);
|
||||
requestMock.post = sinon.stub();
|
||||
requestMock.post.onFirstCall().callsArgWith(1, null, {statusCode: 200});
|
||||
requestMock.post.onFirstCall().callsArgWith(1, null, {
|
||||
statusCode: 200
|
||||
});
|
||||
}
|
||||
|
||||
it('should be able to restore 0.7.2 data', function(done) {
|
||||
|
@ -120,11 +133,9 @@ describe('insight storage plugin', function() {
|
|||
var receivedArgs = requestMock.post.firstCall.args[0].body;
|
||||
var url = requestMock.post.firstCall.args[0].url;
|
||||
var args = querystring.decode(receivedArgs);
|
||||
assert(url.indexOf('change_passphrase') !== -1);
|
||||
assert(requestMock.post.firstCall.args[0].headers.Authorization
|
||||
===
|
||||
new Buffer(email + ':' + oldSecret).toString('base64'));
|
||||
assert(args.newPassphrase === newSecret);
|
||||
url.indexOf('change_passphrase').should.not.be.equal(-1);
|
||||
requestMock.post.firstCall.args[0].headers.Authorization.should.be.equal( new Buffer(email + ':' + oldSecret).toString('base64'));
|
||||
args.newPassphrase.should.be.equal(newSecret);
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ describe('crypto utils', function() {
|
|||
phrase.should.equal(t.phrase);
|
||||
});
|
||||
it('should generate a passphrase from weird chars', function() {
|
||||
var phrase = cryptoUtils.kdf('Pwd123!@#$%^&*(){}[]\|/?.>,<=+-_`~åéþ䲤þçæ¶');
|
||||
var phrase = cryptoUtils.kdf('Pwd123!@#$%^&*(){}[]\|/?.>,<=+-_`~åéþ䲤þçæ¶', tests[0].salt, 100);
|
||||
var expected = 'CZwb5KdikvZHVsEoZUdJckAy+yyzGnd++XhyqxJXbc30'
|
||||
+ 'pEoO+WqHgqBbdf0gn2wiyWZv3zymB+7L75Xnz3uSlg==';
|
||||
phrase.should.equal(expected);
|
||||
|
|
Loading…
Reference in New Issue