2014-10-02 16:05:44 -04:00
|
|
|
'use strict';
|
|
|
|
|
2014-11-18 12:44:00 -05:00
|
|
|
var ngModule = angular.module('woServices');
|
|
|
|
ngModule.service('privateKey', PrivateKey);
|
|
|
|
module.exports = PrivateKey;
|
|
|
|
|
2014-11-25 11:46:33 -05:00
|
|
|
function PrivateKey(privateKeyRestDao) {
|
|
|
|
this._restDao = privateKeyRestDao;
|
2014-11-18 12:44:00 -05:00
|
|
|
}
|
2014-10-02 16:05:44 -04:00
|
|
|
|
|
|
|
//
|
|
|
|
// Device registration functions
|
|
|
|
//
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Request registration of a new device by fetching registration session key.
|
|
|
|
* @param {String} options.userId The user's email address
|
|
|
|
* @param {String} options.deviceName The device's memorable name
|
|
|
|
* @return {Object} {encryptedRegSessionKey:[base64]}
|
|
|
|
*/
|
2014-12-11 13:07:04 -05:00
|
|
|
PrivateKey.prototype.requestDeviceRegistration = function(options) {
|
|
|
|
var self = this;
|
|
|
|
return new Promise(function(resolve) {
|
|
|
|
if (!options.userId || !options.deviceName) {
|
|
|
|
throw new Error('Incomplete arguments!');
|
|
|
|
}
|
|
|
|
resolve();
|
2014-10-02 16:05:44 -04:00
|
|
|
|
2014-12-11 13:07:04 -05:00
|
|
|
}).then(function() {
|
|
|
|
var uri = '/device/user/' + options.userId + '/devicename/' + options.deviceName;
|
|
|
|
return self._restDao.post(undefined, uri);
|
|
|
|
});
|
2014-10-02 16:05:44 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Authenticate device registration by uploading the deviceSecret encrypted with the regSessionKeys.
|
|
|
|
* @param {String} options.userId The user's email address
|
|
|
|
* @param {String} options.deviceName The device's memorable name
|
|
|
|
* @param {String} options.encryptedDeviceSecret The base64 encoded encrypted device secret
|
|
|
|
* @param {String} options.iv The iv used for encryption
|
|
|
|
*/
|
2014-12-11 13:07:04 -05:00
|
|
|
PrivateKey.prototype.uploadDeviceSecret = function(options) {
|
|
|
|
var self = this;
|
|
|
|
return new Promise(function(resolve) {
|
|
|
|
if (!options.userId || !options.deviceName || !options.encryptedDeviceSecret || !options.iv) {
|
|
|
|
throw new Error('Incomplete arguments!');
|
|
|
|
}
|
|
|
|
resolve();
|
2014-10-02 16:05:44 -04:00
|
|
|
|
2014-12-11 13:07:04 -05:00
|
|
|
}).then(function() {
|
|
|
|
var uri = '/device/user/' + options.userId + '/devicename/' + options.deviceName;
|
|
|
|
return self._restDao.put(options, uri);
|
|
|
|
});
|
2014-10-02 16:05:44 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// Private key functions
|
|
|
|
//
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Request authSessionKeys required for upload the encrypted private PGP key.
|
|
|
|
* @param {String} options.userId The user's email address
|
|
|
|
* @return {Object} {sessionId, encryptedAuthSessionKey:[base64 encoded], encryptedChallenge:[base64 encoded]}
|
|
|
|
*/
|
2014-12-11 13:07:04 -05:00
|
|
|
PrivateKey.prototype.requestAuthSessionKey = function(options) {
|
|
|
|
var self = this;
|
|
|
|
return new Promise(function(resolve) {
|
|
|
|
if (!options.userId) {
|
|
|
|
throw new Error('Incomplete arguments!');
|
|
|
|
}
|
|
|
|
resolve();
|
2014-10-02 16:05:44 -04:00
|
|
|
|
2014-12-11 13:07:04 -05:00
|
|
|
}).then(function() {
|
|
|
|
var uri = '/auth/user/' + options.userId;
|
|
|
|
return self._restDao.post(undefined, uri);
|
|
|
|
});
|
2014-10-02 16:05:44 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Verifiy authentication by uploading the challenge and deviceSecret encrypted with the authSessionKeys as a response.
|
|
|
|
* @param {String} options.userId The user's email address
|
|
|
|
* @param {String} options.encryptedChallenge The server's base64 encoded challenge encrypted using the authSessionKey
|
|
|
|
* @param {String} options.encryptedDeviceSecret The server's base64 encoded deviceSecret encrypted using the authSessionKey
|
|
|
|
* @param {String} options.iv The iv used for encryption
|
|
|
|
*/
|
2014-12-11 13:07:04 -05:00
|
|
|
PrivateKey.prototype.verifyAuthentication = function(options) {
|
|
|
|
var self = this;
|
|
|
|
return new Promise(function(resolve) {
|
|
|
|
if (!options.userId || !options.sessionId || !options.encryptedChallenge || !options.encryptedDeviceSecret || !options.iv) {
|
|
|
|
throw new Error('Incomplete arguments!');
|
|
|
|
}
|
|
|
|
resolve();
|
2014-10-02 16:05:44 -04:00
|
|
|
|
2014-12-11 13:07:04 -05:00
|
|
|
}).then(function() {
|
|
|
|
var uri = '/auth/user/' + options.userId + '/session/' + options.sessionId;
|
|
|
|
return self._restDao.put(options, uri);
|
|
|
|
});
|
2014-10-02 16:05:44 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Upload the encrypted private PGP key.
|
|
|
|
* @param {String} options._id The hex encoded capital 16 char key id
|
|
|
|
* @param {String} options.userId The user's email address
|
|
|
|
* @param {String} options.encryptedPrivateKey The base64 encoded encrypted private PGP key
|
|
|
|
* @param {String} options.sessionId The session id
|
|
|
|
*/
|
2014-12-11 13:07:04 -05:00
|
|
|
PrivateKey.prototype.upload = function(options) {
|
|
|
|
var self = this;
|
|
|
|
return new Promise(function(resolve) {
|
|
|
|
if (!options._id || !options.userId || !options.encryptedPrivateKey || !options.sessionId || !options.salt || !options.iv) {
|
|
|
|
throw new Error('Incomplete arguments!');
|
|
|
|
}
|
|
|
|
resolve();
|
2014-10-02 16:05:44 -04:00
|
|
|
|
2014-12-11 13:07:04 -05:00
|
|
|
}).then(function() {
|
|
|
|
var uri = '/privatekey/user/' + options.userId + '/session/' + options.sessionId;
|
|
|
|
return self._restDao.post(options, uri);
|
|
|
|
});
|
2014-10-02 16:05:44 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Query if an encrypted private PGP key exists on the server without initializing the recovery procedure.
|
|
|
|
* @param {String} options.userId The user's email address
|
|
|
|
* @param {String} options.keyId The private PGP key id
|
|
|
|
* @return {Boolean} whether the key was found on the server or not.
|
|
|
|
*/
|
2014-12-11 13:07:04 -05:00
|
|
|
PrivateKey.prototype.hasPrivateKey = function(options) {
|
|
|
|
var self = this;
|
|
|
|
return new Promise(function(resolve) {
|
|
|
|
if (!options.userId || !options.keyId) {
|
|
|
|
throw new Error('Incomplete arguments!');
|
2014-06-06 12:36:23 -04:00
|
|
|
}
|
2014-12-11 13:07:04 -05:00
|
|
|
resolve();
|
|
|
|
|
|
|
|
}).then(function() {
|
|
|
|
return self._restDao.get({
|
|
|
|
uri: '/privatekey/user/' + options.userId + '/key/' + options.keyId + '?ignoreRecovery=true',
|
|
|
|
});
|
2014-06-06 12:36:23 -04:00
|
|
|
|
2014-12-11 13:07:04 -05:00
|
|
|
}).then(function() {
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}).catch(function(err) {
|
|
|
|
// 404: there is no encrypted private key on the server
|
|
|
|
if (err.code && err.code !== 200) {
|
|
|
|
return false;
|
2014-06-06 12:36:23 -04:00
|
|
|
}
|
|
|
|
|
2014-12-11 13:07:04 -05:00
|
|
|
throw err;
|
2014-10-02 16:05:44 -04:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Request download for the encrypted private PGP key.
|
|
|
|
* @param {String} options.userId The user's email address
|
|
|
|
* @param {String} options.keyId The private PGP key id
|
|
|
|
* @return {Boolean} whether the key was found on the server or not.
|
|
|
|
*/
|
2014-12-11 13:07:04 -05:00
|
|
|
PrivateKey.prototype.requestDownload = function(options) {
|
|
|
|
var self = this;
|
|
|
|
return new Promise(function(resolve) {
|
|
|
|
if (!options.userId || !options.keyId) {
|
|
|
|
throw new Error('Incomplete arguments!');
|
2014-06-06 12:36:23 -04:00
|
|
|
}
|
2014-12-11 13:07:04 -05:00
|
|
|
resolve();
|
2014-06-06 12:36:23 -04:00
|
|
|
|
2014-12-11 13:07:04 -05:00
|
|
|
}).then(function() {
|
|
|
|
return self._restDao.get({
|
|
|
|
uri: '/privatekey/user/' + options.userId + '/key/' + options.keyId
|
|
|
|
});
|
|
|
|
|
|
|
|
}).then(function() {
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}).catch(function(err) {
|
|
|
|
// 404: there is no encrypted private key on the server
|
|
|
|
if (err.code && err.code !== 200) {
|
|
|
|
return false;
|
2014-06-06 12:36:23 -04:00
|
|
|
}
|
|
|
|
|
2014-12-11 13:07:04 -05:00
|
|
|
throw err;
|
2014-10-02 16:05:44 -04:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Verify the download request for the private PGP key using the recovery token sent via email. This downloads the actual encrypted private key.
|
|
|
|
* @param {String} options.userId The user's email address
|
|
|
|
* @param {String} options.keyId The private key id
|
|
|
|
* @param {String} options.recoveryToken The token proving the user own the email account
|
|
|
|
* @return {Object} {_id:[hex encoded capital 16 char key id], encryptedPrivateKey:[base64 encoded], encryptedUserId: [base64 encoded]}
|
|
|
|
*/
|
2014-12-11 13:07:04 -05:00
|
|
|
PrivateKey.prototype.download = function(options) {
|
|
|
|
var self = this;
|
|
|
|
return new Promise(function(resolve) {
|
|
|
|
if (!options.userId || !options.keyId || !options.recoveryToken) {
|
|
|
|
throw new Error('Incomplete arguments!');
|
|
|
|
}
|
|
|
|
resolve();
|
|
|
|
|
|
|
|
}).then(function() {
|
|
|
|
return self._restDao.get({
|
|
|
|
uri: '/privatekey/user/' + options.userId + '/key/' + options.keyId + '/recovery/' + options.recoveryToken
|
|
|
|
});
|
|
|
|
});
|
2014-11-18 12:44:00 -05:00
|
|
|
};
|