1
0
mirror of https://github.com/moparisthebest/mail synced 2024-11-26 02:42:17 -05:00

upgrade to openpgp.js v0.3.0

This commit is contained in:
Tankred Hase 2014-01-24 13:26:29 +01:00
parent 67127b8163
commit 6676e7bc01
5 changed files with 131 additions and 13686 deletions

View File

@ -4,12 +4,10 @@
define(function(require) {
'use strict';
var openpgp = require('openpgp').openpgp,
var openpgp = require('openpgp'),
util = require('openpgp').util;
var PGP = function() {
openpgp.init();
};
var PGP = function() {};
/**
* Generate a key pair for the user
@ -27,7 +25,7 @@ define(function(require) {
// generate keypair (keytype 1=RSA)
try {
userId = 'Whiteout User <' + options.emailAddress + '>';
keys = openpgp.generate_key_pair(1, options.keySize, userId, options.passphrase);
keys = openpgp.generateKeyPair(1, options.keySize, userId, options.passphrase);
} catch (e) {
callback({
errMsg: 'Keygeneration failed!',
@ -37,7 +35,7 @@ define(function(require) {
}
callback(null, {
keyId: util.hexstrdump(keys.privateKey.getKeyId()).toUpperCase(),
keyId: keys.key.getKeyPacket().getKeyId().toHex().toUpperCase(),
privateKeyArmored: keys.privateKeyArmored,
publicKeyArmored: keys.publicKeyArmored
});
@ -46,48 +44,53 @@ define(function(require) {
/**
* Show a user's fingerprint
*/
PGP.prototype.getFingerprint = function(publicKeyArmored) {
var publicKey, privateKey;
if (publicKeyArmored) {
// parse the optional public key parameter
publicKey = openpgp.read_publicKey(publicKeyArmored)[0];
return util.hexstrdump(publicKey.getFingerprint()).toUpperCase();
PGP.prototype.getFingerprint = function(keyArmored) {
function fingerprint(key) {
return util.hexstrdump(key.getKeyPacket().getFingerprint()).toUpperCase();
}
privateKey = openpgp.keyring.exportPrivateKey(0);
if (privateKey && privateKey.keyId) {
publicKey = openpgp.keyring.getPublicKeysForKeyId(privateKey.keyId)[0];
// process armored key input
if (keyArmored) {
return fingerprint(openpgp.key.readArmored(keyArmored).keys[0]);
}
if (!privateKey || !privateKey.keyId || !privateKey.armored || !publicKey || !publicKey.armored) {
console.error('Public key not available!');
return '';
if (!this._publicKey) {
throw new Error('No public key set for fingerprint generation!');
}
return util.hexstrdump(publicKey.obj.getFingerprint()).toUpperCase();
// get local fingerpring
return fingerprint(this._publicKey);
};
/**
* Show a user's key id
*/
PGP.prototype.getKeyId = function() {
var privateKey = openpgp.keyring.exportPrivateKey(0);
if (!privateKey || !privateKey.keyId) {
console.error('Public key not available!');
return '';
var pubKeyId, privKeyId;
// check keys
if (!this._privateKey || !this._publicKey) {
return;
}
return util.hexstrdump(privateKey.keyId).toUpperCase();
pubKeyId = this._publicKey.getKeyPacket().getKeyId().toHex().toUpperCase();
privKeyId = this._privateKey.getKeyPacket().getKeyId().toHex().toUpperCase();
if (!pubKeyId || !privKeyId || pubKeyId !== privKeyId) {
console.error('Key IDs do not match!');
return;
}
return pubKeyId;
};
/**
* Import the user's key pair
*/
PGP.prototype.importKeys = function(options, callback) {
var publicKey, privateKey;
var pubKeyId, privKeyId, self = this;
// check passphrase
// check options
if (typeof options.passphrase !== 'string' || !options.privateKeyArmored || !options.publicKeyArmored) {
callback({
errMsg: 'Importing keys failed. Not all options set!'
@ -95,25 +98,37 @@ define(function(require) {
return;
}
// clear any keypair already in the keychain
openpgp.keyring.init();
// unlock and import private key
if (!openpgp.keyring.importPrivateKey(options.privateKeyArmored, options.passphrase)) {
openpgp.keyring.init();
function resetKeys() {
self._publicKey = undefined;
self._privateKey = undefined;
}
// read armored keys
try {
this._publicKey = openpgp.key.readArmored(options.publicKeyArmored).keys[0];
this._privateKey = openpgp.key.readArmored(options.privateKeyArmored).keys[0];
} catch (e) {
resetKeys();
callback({
errMsg: 'Importing keys failed. Parsing error!'
});
return;
}
// decrypt private key with passphrase
if (!this._privateKey.decrypt(options.passphrase)) {
resetKeys();
callback({
errMsg: 'Incorrect passphrase!'
});
return;
}
// import public key
openpgp.keyring.importPublicKey(options.publicKeyArmored);
// check if keys have the same id
privateKey = openpgp.keyring.exportPrivateKey(0);
publicKey = openpgp.keyring.getPublicKeysForKeyId(privateKey.keyId)[0];
if (!privateKey || !privateKey.armored || !publicKey || !publicKey.armored || privateKey.keyId !== publicKey.keyId) {
// reset keyring
openpgp.keyring.init();
pubKeyId = this._publicKey.getKeyPacket().getKeyId().toHex();
privKeyId = this._privateKey.getKeyPacket().getKeyId().toHex();
if (!pubKeyId || !privKeyId || pubKeyId !== privKeyId) {
resetKeys();
callback({
errMsg: 'Key IDs dont match!'
});
@ -127,14 +142,7 @@ define(function(require) {
* Export the user's key pair
*/
PGP.prototype.exportKeys = function(callback) {
var publicKey, privateKey;
privateKey = openpgp.keyring.exportPrivateKey(0);
if (privateKey && privateKey.keyId) {
publicKey = openpgp.keyring.getPublicKeysForKeyId(privateKey.keyId)[0];
}
if (!privateKey || !privateKey.keyId || !privateKey.armored || !publicKey || !publicKey.armored) {
if (!this._publicKey || !this._privateKey) {
callback({
errMsg: 'Could not export keys!'
});
@ -142,26 +150,33 @@ define(function(require) {
}
callback(null, {
keyId: util.hexstrdump(privateKey.keyId).toUpperCase(),
privateKeyArmored: privateKey.armored,
publicKeyArmored: publicKey.armored
keyId: this._publicKey.getKeyPacket().getKeyId().toHex().toUpperCase(),
privateKeyArmored: this._privateKey.armor(),
publicKeyArmored: this._publicKey.armor()
});
};
/**
* Encrypt and sign a pgp message for a list of receivers
*/
PGP.prototype.encrypt = function(plaintext, receiverKeys, callback) {
var ct, i,
privateKey = openpgp.keyring.exportPrivateKey(0).obj;
PGP.prototype.encrypt = function(plaintext, publicKeysArmored, callback) {
var ciphertext, publicKeys = [];
for (i = 0; i < receiverKeys.length; i++) {
receiverKeys[i] = openpgp.read_publicKey(receiverKeys[i])[0];
// check keys
if (!this._privateKey || publicKeysArmored.length < 1) {
callback({
errMsg: 'Error encrypting. Keys must be set!'
});
return;
}
try {
// parse armored public keys
publicKeysArmored.forEach(function(pubkeyArmored) {
publicKeys.push(openpgp.key.readArmored(pubkeyArmored).keys[0]);
});
// encrypt and sign the plaintext
ct = openpgp.write_signed_and_encrypted_message(privateKey, receiverKeys, plaintext);
ciphertext = openpgp.signAndEncryptMessage(publicKeys, this._privateKey, plaintext);
} catch (err) {
callback({
errMsg: 'Error encrypting plaintext!',
@ -170,65 +185,28 @@ define(function(require) {
return;
}
callback(null, ct);
callback(null, ciphertext);
};
/**
* Decrypt and verify a pgp message for a single sender
*/
PGP.prototype.decrypt = function(ciphertext, senderKey, callback) {
var privateKey, publicKey, pubKeys, msg, keymat, sesskey, decrypted;
PGP.prototype.decrypt = function(ciphertext, publicKeyArmored, callback) {
var publicKey, message, decrypted, signaturesValid;
privateKey = openpgp.keyring.exportPrivateKey(0).obj;
publicKey = openpgp.read_publicKey(senderKey)[0];
pubKeys = [{
armored: senderKey,
obj: publicKey,
keyId: publicKey.getKeyId()
}];
try {
msg = openpgp.read_message(ciphertext)[0];
} catch (err) {
// check keys
if (!this._privateKey || !publicKeyArmored) {
callback({
errMsg: 'Error reading PGP message!',
err: err
errMsg: 'Error decrypting. Keys must be set!'
});
return;
}
// 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) {
callback({
errMsg: 'No private key found!'
});
return;
}
// decrypt and verify ciphertext
// decrypt and verify pgp message
try {
decrypted = msg.decryptAndVerifySignature(keymat, sesskey, pubKeys);
publicKey = openpgp.key.readArmored(publicKeyArmored).keys[0];
message = openpgp.message.readArmored(ciphertext);
decrypted = openpgp.decryptAndVerifyMessage(this._privateKey, [publicKey], message);
} catch (err) {
callback({
errMsg: 'Error decrypting PGP message!',
@ -237,14 +215,18 @@ define(function(require) {
return;
}
// check if signatures are ok
for (var k = 0; k < decrypted.validSignatures.length; k++) {
if (!decrypted.validSignatures[k]) {
callback({
errMsg: 'Error verifying PGP signature!'
});
return;
// check if signatures are valid
signaturesValid = true;
decrypted.signatures.forEach(function(sig) {
if (!sig.valid) {
signaturesValid = false;
}
});
if (!signaturesValid) {
callback({
errMsg: 'Verifying PGP signature failed!'
});
return;
}
// return decrypted plaintext

File diff suppressed because it is too large Load Diff

6
src/lib/openpgp/openpgp.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -20,7 +20,7 @@
angularTouch: 'angular/angular-touch.min',
moment: 'moment/moment.min',
uuid: 'uuid/uuid',
openpgp: 'openpgp/openpgp',
openpgp: 'openpgp/openpgp.min',
iscroll: 'iscroll/iscroll-min'
},
shim: {
@ -35,9 +35,6 @@
exports: 'angular',
deps: ['angular']
},
openpgp: {
exports: 'window'
},
iscroll: {
exports: 'IScroll'
},

View File

@ -10,33 +10,33 @@ define(function(require) {
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-----';
pubkey = '-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n' +
'Version: OpenPGP.js v0.3.0\r\n' +
'Comment: http://openpgpjs.org\r\n' +
'\r\n' +
'xk0EUlhMvAEB/2MZtCUOAYvyLFjDp3OBMGn3Ev8FwjzyPbIF0JUw+L7y2XR5\r\n' +
'RVGvbK88unV3cU/1tOYdNsXI6pSp/Ztjyv7vbBUAEQEAAc0pV2hpdGVvdXQg\r\n' +
'VXNlciA8d2hpdGVvdXQudGVzdEB0LW9ubGluZS5kZT7CXAQQAQgAEAUCUlhM\r\n' +
'vQkQ9vYOm0LN/0wAAAW4Af9C+kYW1AvNWmivdtr0M0iYCUjM9DNOQH1fcvXq\r\n' +
'IiN602mWrkd8jcEzLsW5IUNzVPLhrFIuKyBDTpLnC07Loce1\r\n' +
'=6XMW\r\n' +
'-----END PGP PUBLIC KEY BLOCK-----\r\n\r\n',
privkey = '-----BEGIN PGP PRIVATE KEY BLOCK-----\r\n' +
'Version: OpenPGP.js v0.3.0\r\n' +
'Comment: http://openpgpjs.org\r\n' +
'\r\n' +
'xcBeBFJYTLwBAf9jGbQlDgGL8ixYw6dzgTBp9xL/BcI88j2yBdCVMPi+8tl0\r\n' +
'eUVRr2yvPLp1d3FP9bTmHTbFyOqUqf2bY8r+72wVABEBAAH+AwMIhNB4ivtv\r\n' +
'Y2xg6VeMcjjHxZayESHACV+nQx5Tx6ev6xzIF1Qh72fNPDppLhFSFOuTTMsU\r\n' +
'kTN4c+BVYt29spH+cA1jcDAxQ2ULrNAXo+hheOqhpedTs8aCbcLFkJAS16hk\r\n' +
'YSk4OnJgp/z24rVju1SHRSFbgundPzmNgXeX9e8IkviGhhQ11Wc5YwVkx03t\r\n' +
'Z3MdDMF0jyhopbPIoBdyJB0dhvBh98w3JmwpYh9wjUA9MBHD1tvHpRmSZ3BM\r\n' +
'UCmATn2ZLWBRWiYqFbgDnL1GM80pV2hpdGVvdXQgVXNlciA8d2hpdGVvdXQu\r\n' +
'dGVzdEB0LW9ubGluZS5kZT7CXAQQAQgAEAUCUlhMvQkQ9vYOm0LN/0wAAAW4\r\n' +
'Af9C+kYW1AvNWmivdtr0M0iYCUjM9DNOQH1fcvXqIiN602mWrkd8jcEzLsW5\r\n' +
'IUNzVPLhrFIuKyBDTpLnC07Loce1\r\n' +
'=ULta\r\n' +
'-----END PGP PRIVATE KEY BLOCK-----\r\n';
beforeEach(function() {
pgp = new PGP();
@ -90,6 +90,7 @@ define(function(require) {
publicKeyArmored: pubkey
}, function(err) {
expect(err).to.exist;
expect(err.errMsg).to.equal('Incorrect passphrase!');
pgp.exportKeys(function(err, keys) {
expect(err).to.exist;
@ -109,15 +110,15 @@ define(function(require) {
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);
expect(keys.privateKeyArmored.replace(/\r/g, '')).to.equal(privkey.replace(/\r/g, ''));
expect(keys.publicKeyArmored.replace(/\r/g, '')).to.equal(pubkey.replace(/\r/g, ''));
done();
});
});
});
});
describe('Encryption', function() {
describe('Encrypt/Sign/Decrypt/Verify', function() {
var message = 'asdfs\n\nThursday, Nov 21, 2013 7:38 PM asdf@example.com wrote:\n' +
'> asdf\n' +
'> \n' +
@ -199,7 +200,7 @@ define(function(require) {
it('should work', function(done) {
pgp.decrypt(ciphertext, pubkey, function(err, pt) {
expect(err).to.not.exist;
expect(pt).to.equal(message.replace(/\r\n/g, '\n').replace(/\n/g, '\r\n'));
expect(pt).to.equal(message);
done();
});
});