mirror of
https://github.com/moparisthebest/mail
synced 2024-12-26 01:08:50 -05:00
integrate and test openpgp.js
This commit is contained in:
parent
9ed7a696b4
commit
5666671d2f
@ -4,7 +4,6 @@
|
||||
"globalstrict": true,
|
||||
"node": true,
|
||||
"browser": true,
|
||||
"camelcase": true,
|
||||
"nonew": true,
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
|
146
src/js/crypto/pgp.js
Normal file
146
src/js/crypto/pgp.js
Normal file
@ -0,0 +1,146 @@
|
||||
/**
|
||||
* High level crypto api that handles all calls to OpenPGP.js
|
||||
*/
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var openpgp = require('openpgp').openpgp,
|
||||
openpgpUtil = require('openpgp').util,
|
||||
util = require('cryptoLib/util');
|
||||
|
||||
var PGP = function() {
|
||||
openpgp.init();
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a key pair for the user
|
||||
*/
|
||||
PGP.prototype.generateKeys = function(options, callback) {
|
||||
var userId, keys;
|
||||
|
||||
if (!util.validateEmailAddress(options.emailAddress) || !options.keySize || typeof options.passphrase !== 'string') {
|
||||
callback({
|
||||
errMsg: 'Crypto init failed. Not all options set!'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// generate keypair (keytype 1=RSA)
|
||||
userId = 'Whiteout User <' + options.emailAddress + '>';
|
||||
keys = openpgp.generate_key_pair(1, options.keySize, userId, options.passphrase);
|
||||
|
||||
callback(null, {
|
||||
keyId: openpgpUtil.hexstrdump(keys.privateKey.getKeyId()).toUpperCase(),
|
||||
privateKeyArmored: keys.privateKeyArmored,
|
||||
publicKeyArmored: keys.publicKeyArmored
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Import the user's key pair
|
||||
*/
|
||||
PGP.prototype.importKeys = function(options, callback) {
|
||||
// check passphrase
|
||||
if (typeof options.passphrase !== 'string' || !options.privateKeyArmored || !options.publicKeyArmored) {
|
||||
callback({
|
||||
errMsg: 'Importing keys failed. Not all options set!'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// unlock and import private key
|
||||
if (!openpgp.keyring.importPrivateKey(options.privateKeyArmored, options.passphrase)) {
|
||||
callback({
|
||||
errMsg: 'Incorrect passphrase!'
|
||||
});
|
||||
return;
|
||||
}
|
||||
// import public key
|
||||
openpgp.keyring.importPublicKey(options.publicKeyArmored);
|
||||
callback();
|
||||
};
|
||||
|
||||
/**
|
||||
* Export the user's key pair
|
||||
*/
|
||||
PGP.prototype.exportKeys = function(callback) {
|
||||
var publicKey, privateKey;
|
||||
|
||||
privateKey = openpgp.keyring.exportPrivateKey(0);
|
||||
publicKey = openpgp.keyring.getPublicKeysForKeyId(privateKey.keyId)[0];
|
||||
|
||||
if (privateKey && privateKey.keyId && privateKey.armored && publicKey && publicKey.armored) {
|
||||
callback(null, {
|
||||
keyId: openpgpUtil.hexstrdump(privateKey.keyId).toUpperCase(),
|
||||
privateKeyArmored: privateKey.armored,
|
||||
publicKeyArmored: publicKey.armored
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
callback({
|
||||
errMsg: 'Could not export keys!'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Encrypt and sign a pgp message for a list of receivers
|
||||
*/
|
||||
PGP.prototype.encrypt = function(plaintext, receiverPublicKeys, callback) {
|
||||
var ct, i,
|
||||
privateKey = openpgp.keyring.exportPrivateKey(0).obj;
|
||||
|
||||
for (i = 0; i < receiverPublicKeys.length; i++) {
|
||||
receiverPublicKeys[i] = openpgp.read_publicKey(receiverPublicKeys[i])[0];
|
||||
}
|
||||
|
||||
ct = openpgp.write_signed_and_encrypted_message(privateKey, receiverPublicKeys, plaintext);
|
||||
|
||||
callback(null, ct);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypt and verify a pgp message for a single sender
|
||||
*/
|
||||
PGP.prototype.decrypt = function(ciphertext, senderPublicKey, callback) {
|
||||
var privateKey = openpgp.keyring.exportPrivateKey(0).obj;
|
||||
senderPublicKey = openpgp.read_publicKey(senderPublicKey)[0];
|
||||
|
||||
var msg = openpgp.read_message(ciphertext)[0];
|
||||
var keymat = null;
|
||||
var sesskey = null;
|
||||
|
||||
// Find the private (sub)key for the session key of the message
|
||||
for (var i = 0; i < msg.sessionKeys.length; i++) {
|
||||
if (privateKey.privateKeyPacket.publicKey.getKeyId() === msg.sessionKeys[i].keyId.bytes) {
|
||||
keymat = {
|
||||
key: privateKey,
|
||||
keymaterial: privateKey.privateKeyPacket
|
||||
};
|
||||
sesskey = msg.sessionKeys[i];
|
||||
break;
|
||||
}
|
||||
for (var j = 0; j < privateKey.subKeys.length; j++) {
|
||||
if (privateKey.subKeys[j].publicKey.getKeyId() === msg.sessionKeys[i].keyId.bytes) {
|
||||
keymat = {
|
||||
key: privateKey,
|
||||
keymaterial: privateKey.subKeys[j]
|
||||
};
|
||||
sesskey = msg.sessionKeys[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (keymat !== null) {
|
||||
var decrypted = msg.decryptAndVerifySignature(keymat, sesskey, senderPublicKey);
|
||||
callback(null, decrypted.text);
|
||||
|
||||
} else {
|
||||
callback({
|
||||
errMsg: 'No private key found!'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return PGP;
|
||||
});
|
13466
src/lib/openpgp/openpgp.js
Normal file
13466
src/lib/openpgp/openpgp.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -19,12 +19,16 @@
|
||||
angularRoute: 'angular/angular-route.min',
|
||||
angularTouch: 'angular/angular-touch.min',
|
||||
moment: 'moment/moment.min',
|
||||
uuid: 'uuid/uuid'
|
||||
uuid: 'uuid/uuid',
|
||||
openpgp: 'openpgp/openpgp'
|
||||
},
|
||||
shim: {
|
||||
angular: {
|
||||
exports: 'angular'
|
||||
},
|
||||
openpgp: {
|
||||
exports: 'window'
|
||||
},
|
||||
angularRoute: {
|
||||
exports: 'angular',
|
||||
deps: ['angular']
|
||||
|
@ -21,7 +21,8 @@ function startTests() {
|
||||
require(
|
||||
[
|
||||
'test/new-unit/email-dao-test',
|
||||
'test/new-unit/app-controller-test'
|
||||
'test/new-unit/app-controller-test',
|
||||
'test/new-unit/pgp-test'
|
||||
], function() {
|
||||
//Tests loaded, run tests
|
||||
mocha.run();
|
||||
|
122
test/new-unit/pgp-test.js
Normal file
122
test/new-unit/pgp-test.js
Normal file
@ -0,0 +1,122 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var PGP = require('js/crypto/pgp'),
|
||||
expect = chai.expect;
|
||||
|
||||
describe('PGP Crypto Api unit tests', function() {
|
||||
var pgp,
|
||||
user = "whiteout.test@t-online.de",
|
||||
passphrase = 'asdf',
|
||||
keySize = 512,
|
||||
keyId = 'F6F60E9B42CDFF4C',
|
||||
pubkey = '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' +
|
||||
'Version: OpenPGP.js v.1.20131011\n' +
|
||||
'Comment: http://openpgpjs.org\n' +
|
||||
'\n' +
|
||||
'xk0EUlhMvAEB/2MZtCUOAYvyLFjDp3OBMGn3Ev8FwjzyPbIF0JUw+L7y2XR5\n' +
|
||||
'RVGvbK88unV3cU/1tOYdNsXI6pSp/Ztjyv7vbBUAEQEAAc0pV2hpdGVvdXQg\n' +
|
||||
'VXNlciA8d2hpdGVvdXQudGVzdEB0LW9ubGluZS5kZT7CXAQQAQgAEAUCUlhM\n' +
|
||||
'vQkQ9vYOm0LN/0wAAAW4Af9C+kYW1AvNWmivdtr0M0iYCUjM9DNOQH1fcvXq\n' +
|
||||
'IiN602mWrkd8jcEzLsW5IUNzVPLhrFIuKyBDTpLnC07Loce1\n' +
|
||||
'=6XMW\n' +
|
||||
'-----END PGP PUBLIC KEY BLOCK-----',
|
||||
privkey = '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' +
|
||||
'Version: OpenPGP.js v.1.20131011\n' +
|
||||
'Comment: http://openpgpjs.org\n' +
|
||||
'\n' +
|
||||
'xcBeBFJYTLwBAf9jGbQlDgGL8ixYw6dzgTBp9xL/BcI88j2yBdCVMPi+8tl0\n' +
|
||||
'eUVRr2yvPLp1d3FP9bTmHTbFyOqUqf2bY8r+72wVABEBAAH+AwMIhNB4ivtv\n' +
|
||||
'Y2xg6VeMcjjHxZayESHACV+nQx5Tx6ev6xzIF1Qh72fNPDppLhFSFOuTTMsU\n' +
|
||||
'kTN4c+BVYt29spH+cA1jcDAxQ2ULrNAXo+hheOqhpedTs8aCbcLFkJAS16hk\n' +
|
||||
'YSk4OnJgp/z24rVju1SHRSFbgundPzmNgXeX9e8IkviGhhQ11Wc5YwVkx03t\n' +
|
||||
'Z3MdDMF0jyhopbPIoBdyJB0dhvBh98w3JmwpYh9wjUA9MBHD1tvHpRmSZ3BM\n' +
|
||||
'UCmATn2ZLWBRWiYqFbgDnL1GM80pV2hpdGVvdXQgVXNlciA8d2hpdGVvdXQu\n' +
|
||||
'dGVzdEB0LW9ubGluZS5kZT7CXAQQAQgAEAUCUlhMvQkQ9vYOm0LN/0wAAAW4\n' +
|
||||
'Af9C+kYW1AvNWmivdtr0M0iYCUjM9DNOQH1fcvXqIiN602mWrkd8jcEzLsW5\n' +
|
||||
'IUNzVPLhrFIuKyBDTpLnC07Loce1\n' +
|
||||
'=ULta\n' +
|
||||
'-----END PGP PRIVATE KEY BLOCK-----';
|
||||
|
||||
beforeEach(function() {
|
||||
pgp = new PGP();
|
||||
});
|
||||
|
||||
afterEach(function() {});
|
||||
|
||||
describe('Generate key pair', function() {
|
||||
it('should work', function(done) {
|
||||
pgp.generateKeys({
|
||||
emailAddress: user,
|
||||
keySize: keySize,
|
||||
passphrase: passphrase
|
||||
}, function(err, keys) {
|
||||
expect(err).to.not.exist;
|
||||
expect(keys.keyId).to.exist;
|
||||
expect(keys.privateKeyArmored).to.exist;
|
||||
expect(keys.publicKeyArmored).to.exist;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Import/Export key pair', function() {
|
||||
it('should work', function(done) {
|
||||
pgp.importKeys({
|
||||
passphrase: passphrase,
|
||||
privateKeyArmored: privkey,
|
||||
publicKeyArmored: pubkey
|
||||
}, function(err) {
|
||||
expect(err).to.not.exist;
|
||||
|
||||
pgp.exportKeys(function(err, keys) {
|
||||
expect(err).to.not.exist;
|
||||
expect(keys.keyId).to.equal(keyId);
|
||||
expect(keys.privateKeyArmored).to.equal(privkey);
|
||||
expect(keys.publicKeyArmored).to.equal(pubkey);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Encryption', function() {
|
||||
var message = 'Hello, World!',
|
||||
ciphertext;
|
||||
|
||||
beforeEach(function(done) {
|
||||
pgp.importKeys({
|
||||
passphrase: passphrase,
|
||||
privateKeyArmored: privkey,
|
||||
publicKeyArmored: pubkey
|
||||
}, function(err) {
|
||||
expect(err).to.not.exist;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Encrypt', function() {
|
||||
it('should work', function(done) {
|
||||
pgp.encrypt(message, [pubkey], function(err, ct) {
|
||||
expect(err).to.not.exist;
|
||||
expect(ct).to.exist;
|
||||
ciphertext = ct;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Decrypt', function() {
|
||||
it('should work', function(done) {
|
||||
pgp.decrypt(ciphertext, pubkey, function(err, pt) {
|
||||
expect(err).to.not.exist;
|
||||
expect(pt).to.equal(message);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user