Refactor key generation to use callback

* TODO: reactive native web crypto in rsa.js:142
* TODO: generate publicExponent Uint8Array from argument E in rsa.js:148
* TODO: signing with generated web crypto key fails with "Could not find valid key packet for signing in key"
This commit is contained in:
Tankred Hase 2014-09-30 15:38:02 +02:00
parent d6963f2017
commit cbe4a17ccb
12 changed files with 650 additions and 583 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "openpgp", "name": "openpgp",
"description": "OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.", "description": "OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.",
"version": "0.7.2", "version": "0.8.0-dev",
"homepage": "http://openpgpjs.org/", "homepage": "http://openpgpjs.org/",
"engines": { "engines": {
"node": ">=0.8" "node": ">=0.8"

View File

@ -178,15 +178,19 @@ module.exports = {
} }
}, },
generateMpi: function(algo, bits) { generateMpi: function(algo, bits, callback) {
var result = (function() { switch (algo) {
switch (algo) { case 'rsa_encrypt':
case 'rsa_encrypt': case 'rsa_encrypt_sign':
case 'rsa_encrypt_sign': case 'rsa_sign':
case 'rsa_sign': //remember "publicKey" refers to the crypto/public_key dir
//remember "publicKey" refers to the crypto/public_key dir var rsa = new publicKey.rsa();
var rsa = new publicKey.rsa(); rsa.generate(bits, "10001", function(err, keyObject) {
var keyObject = rsa.generate(bits, "10001"); if (err) {
callback(err);
return;
}
var output = []; var output = [];
output.push(keyObject.n); output.push(keyObject.n);
output.push(keyObject.ee); output.push(keyObject.ee);
@ -194,17 +198,21 @@ module.exports = {
output.push(keyObject.p); output.push(keyObject.p);
output.push(keyObject.q); output.push(keyObject.q);
output.push(keyObject.u); output.push(keyObject.u);
return output;
default:
throw new Error('Unsupported algorithm for key generation.');
}
})();
return result.map(function(bn) { callback(null, mapResult(output));
var mpi = new type_mpi(); });
mpi.fromBigInteger(bn); break;
return mpi; default:
}); callback(new Error('Unsupported algorithm for key generation.'));
}
function mapResult(result) {
return result.map(function(bn) {
var mpi = new type_mpi();
mpi.fromBigInteger(bn);
return mpi;
});
}
}, },

View File

@ -133,13 +133,15 @@ function RSA() {
// Generate a new random private key B bits long, using public expt E // Generate a new random private key B bits long, using public expt E
function generate(B, E) { function generate(B, E, callback) {
// //
// Web Crypto RSA keygen proposal example // Native RSA keygen using Web Crypto
// //
if (typeof window !== 'undefined' && window.crypto && window.crypto.subtle) { if (false && typeof window !== 'undefined' && window.crypto && (window.crypto.subtle || window.crypto.webkitSubtle)) {
var subtle = window.crypto.subtle || window.crypto.webkitSubtle;
var keyGenOpt = { var keyGenOpt = {
name: 'RSASSA-PKCS1-v1_5', name: 'RSASSA-PKCS1-v1_5',
modulusLength: B, // the specified keysize in bits modulusLength: B, // the specified keysize in bits
@ -151,52 +153,34 @@ function RSA() {
var extractable = true; // make generated key extractable var extractable = true; // make generated key extractable
window.crypto.subtle.generateKey(keyGenOpt, extractable, ['sign', 'verify']) subtle.generateKey(keyGenOpt, extractable, ['sign', 'verify'])
.then(onGenerated) .then(onGenerated, callback)
.then(onExported); .then(onExported, callback);
return;
} }
function onGenerated(key) { function onGenerated(key) {
// export the generated keys as JsonWebKey (JWK) // export the generated keys as JsonWebKey (JWK)
// https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33
var p1 = window.crypto.subtle.exportKey('jwk', key.privateKey); return subtle.exportKey('jwk', key.privateKey);
var p2 = window.crypto.subtle.exportKey('jwk', key.publicKey);
return window.Promise.all([p1, p2]);
} }
function onExported(exported) { function onExported(jwk) {
// Exported JWK has the following encoded parameters: n, p, q, qi, ...
var privKey = exported[0];
var pubKey = exported[1];
console.log('Exported private key: ', privKey);
console.log('Exported public key: ', pubKey);
var d = privKey.d;
var dp = privKey.dp;
var dq = privKey.dq;
var e = privKey.e;
var n = privKey.n;
var p = privKey.p;
var q = privKey.q;
var qi = privKey.qi;
// map JWK parameters to local BigInteger type system // map JWK parameters to local BigInteger type system
var key = new keyObject(); var key = new keyObject();
key.n = new BigInteger(util.hexstrdump(base64(n)), 16); key.n = new BigInteger(util.hexstrdump(base64(jwk.n)), 16);
key.ee = new BigInteger(E, 16); key.ee = new BigInteger(E, 16);
key.d = new BigInteger(util.hexstrdump(base64(d)), 16); key.d = new BigInteger(util.hexstrdump(base64(jwk.d)), 16);
key.p = new BigInteger(util.hexstrdump(base64(p)), 16); key.p = new BigInteger(util.hexstrdump(base64(jwk.p)), 16);
key.q = new BigInteger(util.hexstrdump(base64(q)), 16); key.q = new BigInteger(util.hexstrdump(base64(jwk.q)), 16);
key.u = key.p.modInverse(key.q); key.u = key.p.modInverse(key.q);
function base64(base64url) { function base64(base64url) {
return base64url.replace(/-/g, '+').replace(/_/g, '/') return base64url.replace(/-/g, '+').replace(/_/g, '/');
} }
// TODO: add async style callback callback(null, key);
} }
// //
@ -236,7 +220,8 @@ function RSA() {
break; break;
} }
} }
return key;
callback(null, key);
} }
this.encrypt = encrypt; this.encrypt = encrypt;

View File

@ -910,7 +910,9 @@ function readArmored(armoredText) {
* @return {module:key~Key} * @return {module:key~Key}
* @static * @static
*/ */
function generate(options) { function generate(options, callback) {
var packetlist, secretKeyPacket, userIdPacket, dataToSign, signaturePacket, secretSubkeyPacket, subkeySignaturePacket;
options.keyType = options.keyType || enums.publicKey.rsa_encrypt_sign; options.keyType = options.keyType || enums.publicKey.rsa_encrypt_sign;
// RSA Encrypt-Only and RSA Sign-Only are deprecated and SHOULD NOT be generated // RSA Encrypt-Only and RSA Sign-Only are deprecated and SHOULD NOT be generated
if (options.keyType !== enums.publicKey.rsa_encrypt_sign) { if (options.keyType !== enums.publicKey.rsa_encrypt_sign) {
@ -921,74 +923,90 @@ function generate(options) {
options.unlocked = true; options.unlocked = true;
} }
var packetlist = new packet.List(); packetlist = new packet.List();
var secretKeyPacket = new packet.SecretKey(); secretKeyPacket = new packet.SecretKey();
secretKeyPacket.algorithm = enums.read(enums.publicKey, options.keyType); secretKeyPacket.algorithm = enums.read(enums.publicKey, options.keyType);
secretKeyPacket.generate(options.numBits); secretKeyPacket.generate(options.numBits, onSecretKeyGenerated);
if (options.passphrase) {
secretKeyPacket.encrypt(options.passphrase); function onSecretKeyGenerated(err) {
if (err) {
callback(err);
return;
}
if (options.passphrase) {
secretKeyPacket.encrypt(options.passphrase);
}
userIdPacket = new packet.Userid();
userIdPacket.read(options.userId);
dataToSign = {};
dataToSign.userid = userIdPacket;
dataToSign.key = secretKeyPacket;
signaturePacket = new packet.Signature();
signaturePacket.signatureType = enums.signature.cert_generic;
signaturePacket.publicKeyAlgorithm = options.keyType;
signaturePacket.hashAlgorithm = config.prefer_hash_algorithm;
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data];
signaturePacket.preferredSymmetricAlgorithms = [];
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes256);
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes192);
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes128);
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.cast5);
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.tripledes);
signaturePacket.preferredHashAlgorithms = [];
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha256);
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha1);
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha512);
signaturePacket.preferredCompressionAlgorithms = [];
signaturePacket.preferredCompressionAlgorithms.push(enums.compression.zlib);
signaturePacket.preferredCompressionAlgorithms.push(enums.compression.zip);
if (config.integrity_protect) {
signaturePacket.features = [];
signaturePacket.features.push(1); // Modification Detection
}
signaturePacket.sign(secretKeyPacket, dataToSign);
secretSubkeyPacket = new packet.SecretSubkey();
secretSubkeyPacket.algorithm = enums.read(enums.publicKey, options.keyType);
secretSubkeyPacket.generate(options.numBits, onSecretSubkeyGenerated);
} }
var userIdPacket = new packet.Userid(); function onSecretSubkeyGenerated(err) {
userIdPacket.read(options.userId); if (err) {
callback(err);
return;
}
var dataToSign = {}; if (options.passphrase) {
dataToSign.userid = userIdPacket; secretSubkeyPacket.encrypt(options.passphrase);
dataToSign.key = secretKeyPacket; }
var signaturePacket = new packet.Signature();
signaturePacket.signatureType = enums.signature.cert_generic; dataToSign = {};
signaturePacket.publicKeyAlgorithm = options.keyType; dataToSign.key = secretKeyPacket;
signaturePacket.hashAlgorithm = config.prefer_hash_algorithm; dataToSign.bind = secretSubkeyPacket;
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data]; subkeySignaturePacket = new packet.Signature();
signaturePacket.preferredSymmetricAlgorithms = []; subkeySignaturePacket.signatureType = enums.signature.subkey_binding;
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes256); subkeySignaturePacket.publicKeyAlgorithm = options.keyType;
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes192); subkeySignaturePacket.hashAlgorithm = config.prefer_hash_algorithm;
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes128); subkeySignaturePacket.keyFlags = [enums.keyFlags.encrypt_communication | enums.keyFlags.encrypt_storage];
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.cast5); subkeySignaturePacket.sign(secretKeyPacket, dataToSign);
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.tripledes);
signaturePacket.preferredHashAlgorithms = []; packetlist.push(secretKeyPacket);
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha256); packetlist.push(userIdPacket);
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha1); packetlist.push(signaturePacket);
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha512); packetlist.push(secretSubkeyPacket);
signaturePacket.preferredCompressionAlgorithms = []; packetlist.push(subkeySignaturePacket);
signaturePacket.preferredCompressionAlgorithms.push(enums.compression.zlib);
signaturePacket.preferredCompressionAlgorithms.push(enums.compression.zip); if (!options.unlocked) {
if (config.integrity_protect) { secretKeyPacket.clearPrivateMPIs();
signaturePacket.features = []; secretSubkeyPacket.clearPrivateMPIs();
signaturePacket.features.push(1); // Modification Detection }
callback(null, new Key(packetlist));
} }
signaturePacket.sign(secretKeyPacket, dataToSign);
var secretSubkeyPacket = new packet.SecretSubkey();
secretSubkeyPacket.algorithm = enums.read(enums.publicKey, options.keyType);
secretSubkeyPacket.generate(options.numBits);
if (options.passphrase) {
secretSubkeyPacket.encrypt(options.passphrase);
}
dataToSign = {};
dataToSign.key = secretKeyPacket;
dataToSign.bind = secretSubkeyPacket;
var subkeySignaturePacket = new packet.Signature();
subkeySignaturePacket.signatureType = enums.signature.subkey_binding;
subkeySignaturePacket.publicKeyAlgorithm = options.keyType;
subkeySignaturePacket.hashAlgorithm = config.prefer_hash_algorithm;
subkeySignaturePacket.keyFlags = [enums.keyFlags.encrypt_communication | enums.keyFlags.encrypt_storage];
subkeySignaturePacket.sign(secretKeyPacket, dataToSign);
packetlist.push(secretKeyPacket);
packetlist.push(userIdPacket);
packetlist.push(signaturePacket);
packetlist.push(secretSubkeyPacket);
packetlist.push(subkeySignaturePacket);
if (!options.unlocked) {
secretKeyPacket.clearPrivateMPIs();
secretSubkeyPacket.clearPrivateMPIs();
}
return new Key(packetlist);
} }
/** /**

View File

@ -224,24 +224,28 @@ function verifyClearSignedMessage(publicKeys, msg, callback) {
* @param {String} options.userId assumes already in form of "User Name <username@email.com>" * @param {String} options.userId assumes already in form of "User Name <username@email.com>"
* @param {String} options.passphrase The passphrase used to encrypt the resulting private key * @param {String} options.passphrase The passphrase used to encrypt the resulting private key
* @param {Boolean} [options.unlocked=false] The secret part of the generated key is unlocked * @param {Boolean} [options.unlocked=false] The secret part of the generated key is unlocked
* @param {function} callback (optional) callback(error, result) for async style * @param {function} callback(error, result) The required callback
* @return {Object} {key: module:key~Key, privateKeyArmored: String, publicKeyArmored: String} * @return {Object} {key: module:key~Key, privateKeyArmored: String, publicKeyArmored: String}
* @static * @static
*/ */
function generateKeyPair(options, callback) { function generateKeyPair(options, callback) {
if (useWorker(callback)) { if (!callback) {
throw new Error('Callback must be set for key generation!');
}
// use web worker if web crypto apis are not supported
if (!useWebCrypto() && useWorker(callback)) {
asyncProxy.generateKeyPair(options, callback); asyncProxy.generateKeyPair(options, callback);
return; return;
} }
return execute(function() { key.generate(options, function(err, newKey) {
var result = {}; var result = {};
var newKey = key.generate(options);
result.key = newKey; result.key = newKey;
result.privateKeyArmored = newKey.armor(); result.privateKeyArmored = newKey.armor();
result.publicKeyArmored = newKey.toPublic().armor(); result.publicKeyArmored = newKey.toPublic().armor();
return result; callback(null, result);
}, callback); });
} }
// //
@ -257,12 +261,20 @@ function useWorker(callback) {
} }
if (!asyncProxy) { if (!asyncProxy) {
throw new Error('You need to set the worker path!'); console.log('You need to set the worker path!');
return false;
} }
return true; return true;
} }
/**
* Check for WebCrypto support
*/
function useWebCrypto() {
return typeof window !== 'undefined' && window.crypto && (window.crypto.subtle || window.crypto.webkitSubtle);
}
/** /**
* Command pattern that handles async calls gracefully * Command pattern that handles async calls gracefully
*/ */

View File

@ -270,9 +270,19 @@ SecretKey.prototype.decrypt = function (passphrase) {
return true; return true;
}; };
SecretKey.prototype.generate = function (bits) { SecretKey.prototype.generate = function (bits, callback) {
this.mpi = crypto.generateMpi(this.algorithm, bits); var self = this;
this.isDecrypted = true;
crypto.generateMpi(self.algorithm, bits, function(err, mpi) {
if (err) {
callback(err);
return;
}
self.mpi = mpi;
self.isDecrypted = true;
callback();
});
}; };
/** /**

View File

@ -110,12 +110,20 @@ onmessage = function (event) {
break; break;
case 'generate-key-pair': case 'generate-key-pair':
try { try {
data = window.openpgp.generateKeyPair(msg.options); window.openpgp.generateKeyPair(msg.options, function(error, data) {
data.key = data.key.toPacketlist(); if (error) {
err = error.message;
response({event: 'method-return', data: data, err: err});
return;
}
data.key = data.key.toPacketlist();
response({event: 'method-return', data: data, err: err});
});
} catch (e) { } catch (e) {
err = e.message; err = e.message;
response({event: 'method-return', data: data, err: err});
} }
response({event: 'method-return', data: data, err: err});
break; break;
case 'decrypt-key': case 'decrypt-key':
try { try {

View File

@ -8,57 +8,61 @@ var chai = require('chai'),
describe('Basic', function() { describe('Basic', function() {
describe("Key generation/encryption/decryption", function() { describe("Key generation/encryption/decryption", function() {
var testHelper = function(passphrase, userid, message) { var testHelper = function(passphrase, userid, message, done) {
var key = openpgp.generateKeyPair({numBits: 512, userId: userid, passphrase: passphrase}); var opt = {numBits: 512, userId: userid, passphrase: passphrase};
expect(key).to.exist; openpgp.generateKeyPair(opt, function(err, key) {
expect(key.key).to.exist; expect(err).to.not.exist;
expect(key.privateKeyArmored).to.exist;
expect(key.publicKeyArmored).to.exist;
var info = '\npassphrase: ' + passphrase + '\n' + 'userid: ' + userid + '\n' + 'message: ' + message; expect(key).to.exist;
expect(key.key).to.exist;
expect(key.privateKeyArmored).to.exist;
expect(key.publicKeyArmored).to.exist;
var privKeys = openpgp.key.readArmored(key.privateKeyArmored); var info = '\npassphrase: ' + passphrase + '\n' + 'userid: ' + userid + '\n' + 'message: ' + message;
var publicKeys = openpgp.key.readArmored(key.publicKeyArmored);
expect(privKeys).to.exist; var privKeys = openpgp.key.readArmored(key.privateKeyArmored);
expect(privKeys.err).to.not.exist; var publicKeys = openpgp.key.readArmored(key.publicKeyArmored);
expect(privKeys.keys).to.have.length(1);
var privKey = privKeys.keys[0]; expect(privKeys).to.exist;
var pubKey = publicKeys.keys[0]; expect(privKeys.err).to.not.exist;
expect(privKeys.keys).to.have.length(1);
expect(privKey).to.exist; var privKey = privKeys.keys[0];
expect(pubKey).to.exist; var pubKey = publicKeys.keys[0];
var success = privKey.decrypt(passphrase); expect(privKey).to.exist;
expect(pubKey).to.exist;
expect(success).to.be.true; var success = privKey.decrypt(passphrase);
var encrypted = openpgp.signAndEncryptMessage([pubKey], privKey, message); expect(success).to.be.true;
expect(encrypted).to.exist; var encrypted = openpgp.signAndEncryptMessage([pubKey], privKey, message);
var msg = openpgp.message.readArmored(encrypted); expect(encrypted).to.exist;
expect(msg).to.exist; var msg = openpgp.message.readArmored(encrypted);
var keyids = msg.getEncryptionKeyIds(); expect(msg).to.exist;
expect(keyids).to.exist; var keyids = msg.getEncryptionKeyIds();
var decrypted = openpgp.decryptAndVerifyMessage(privKey, [pubKey], msg); expect(keyids).to.exist;
expect(decrypted).to.exist;
expect(decrypted.signatures[0].valid).to.be.true; var decrypted = openpgp.decryptAndVerifyMessage(privKey, [pubKey], msg);
expect(decrypted.text).to.equal(message); expect(decrypted).to.exist;
expect(decrypted.signatures[0].valid).to.be.true;
expect(decrypted.text).to.equal(message);
done();
});
}; };
it('ASCII Text', function (done) { it('ASCII Text', function (done) {
testHelper('password', 'Test McTestington <test@example.com>', 'hello world'); testHelper('password', 'Test McTestington <test@example.com>', 'hello world', done);
done();
}); });
it('Unicode Text', function (done) { it('Unicode Text', function (done) {
testHelper('●●●●', '♔♔♔♔ <test@example.com>', 'łäóć'); testHelper('●●●●', '♔♔♔♔ <test@example.com>', 'łäóć', done);
done();
}); });
it('should fail to verify signature for wrong public key', function (done) { it('should fail to verify signature for wrong public key', function (done) {
@ -66,29 +70,35 @@ describe('Basic', function() {
var passphrase = 'password'; var passphrase = 'password';
var message = 'hello world'; var message = 'hello world';
var key = openpgp.generateKeyPair({numBits: 512, userId: userid, passphrase: passphrase}); var opt = {numBits: 512, userId: userid, passphrase: passphrase};
openpgp.generateKeyPair(opt, function(err, key) {
expect(err).to.not.exist;
var privKeys = openpgp.key.readArmored(key.privateKeyArmored); var privKeys = openpgp.key.readArmored(key.privateKeyArmored);
var publicKeys = openpgp.key.readArmored(key.publicKeyArmored); var publicKeys = openpgp.key.readArmored(key.publicKeyArmored);
var privKey = privKeys.keys[0]; var privKey = privKeys.keys[0];
var pubKey = publicKeys.keys[0]; var pubKey = publicKeys.keys[0];
var success = privKey.decrypt(passphrase); var success = privKey.decrypt(passphrase);
var encrypted = openpgp.signAndEncryptMessage([pubKey], privKey, message); var encrypted = openpgp.signAndEncryptMessage([pubKey], privKey, message);
var msg = openpgp.message.readArmored(encrypted); var msg = openpgp.message.readArmored(encrypted);
expect(msg).to.exist; expect(msg).to.exist;
var anotherKey = openpgp.generateKeyPair({numBits: 512, userId: userid, passphrase: passphrase}); openpgp.generateKeyPair(opt, function(err, anotherKey) {
var anotherPubKey = openpgp.key.readArmored(anotherKey.publicKeyArmored).keys[0]; expect(err).to.not.exist;
var decrypted = openpgp.decryptAndVerifyMessage(privKey, [anotherPubKey], msg); var anotherPubKey = openpgp.key.readArmored(anotherKey.publicKeyArmored).keys[0];
expect(decrypted).to.exist;
expect(decrypted.signatures[0].valid).to.be.null; var decrypted = openpgp.decryptAndVerifyMessage(privKey, [anotherPubKey], msg);
expect(decrypted.text).to.equal(message); expect(decrypted).to.exist;
done(); expect(decrypted.signatures[0].valid).to.be.null;
expect(decrypted.text).to.equal(message);
done();
});
});
}); });
it('Performance test', function (done) { it('Performance test', function (done) {
@ -103,46 +113,49 @@ describe('Basic', function() {
var userid = 'Test McTestington <test@example.com>'; var userid = 'Test McTestington <test@example.com>';
var passphrase = 'password'; var passphrase = 'password';
var key = openpgp.generateKeyPair({numBits: 512, userId: userid, passphrase: passphrase}); var opt = {numBits: 512, userId: userid, passphrase: passphrase};
openpgp.generateKeyPair(opt, function(err, key) {
expect(err).to.not.exist;
var info = '\npassphrase: ' + passphrase + '\n' + 'userid: ' + userid + '\n' + 'message: ' + message; var info = '\npassphrase: ' + passphrase + '\n' + 'userid: ' + userid + '\n' + 'message: ' + message;
var privKeys = openpgp.key.readArmored(key.privateKeyArmored); var privKeys = openpgp.key.readArmored(key.privateKeyArmored);
var publicKeys = openpgp.key.readArmored(key.publicKeyArmored); var publicKeys = openpgp.key.readArmored(key.publicKeyArmored);
var privKey = privKeys.keys[0]; var privKey = privKeys.keys[0];
var pubKey = publicKeys.keys[0]; var pubKey = publicKeys.keys[0];
var success = privKey.decrypt(passphrase); var success = privKey.decrypt(passphrase);
if (console.profile) { if (console.profile) {
console.profile("encrypt/sign/verify/decrypt"); console.profile("encrypt/sign/verify/decrypt");
} }
// sign and encrypt // sign and encrypt
var msg, encrypted; var msg, encrypted;
msg = openpgp.message.fromBinary(message); msg = openpgp.message.fromBinary(message);
msg = msg.sign([privKey]); msg = msg.sign([privKey]);
msg = msg.encrypt([pubKey]); msg = msg.encrypt([pubKey]);
encrypted = openpgp.armor.encode(openpgp.enums.armor.message, msg.packets.write()); encrypted = openpgp.armor.encode(openpgp.enums.armor.message, msg.packets.write());
if (console.profileEnd) { if (console.profileEnd) {
console.profileEnd(); console.profileEnd();
} }
msg = openpgp.message.readArmored(encrypted); msg = openpgp.message.readArmored(encrypted);
var keyids = msg.getEncryptionKeyIds(); var keyids = msg.getEncryptionKeyIds();
expect(keyids).to.exist; expect(keyids).to.exist;
var decrypted = openpgp.decryptAndVerifyMessage(privKey, [pubKey], msg); var decrypted = openpgp.decryptAndVerifyMessage(privKey, [pubKey], msg);
expect(decrypted).to.exist; expect(decrypted).to.exist;
expect(decrypted.signatures[0].valid).to.be.true; expect(decrypted.signatures[0].valid).to.be.true;
expect(decrypted.text).to.equal(message); expect(decrypted.text).to.equal(message);
done(); done();
});
}); });
}); });

View File

@ -618,7 +618,7 @@ var pgp_desktop_priv =
expect(prefAlgo).to.equal(openpgp.config.encryption_cipher); expect(prefAlgo).to.equal(openpgp.config.encryption_cipher);
}); });
it('Preferences of generated key', function() { it('Preferences of generated key', function(done) {
var testPref = function(key) { var testPref = function(key) {
// key flags // key flags
var keyFlags = openpgp.enums.keyFlags; var keyFlags = openpgp.enums.keyFlags;
@ -633,10 +633,14 @@ var pgp_desktop_priv =
var compr = openpgp.enums.compression; var compr = openpgp.enums.compression;
expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip]); expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip]);
expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.integrity_protect ? [1] : null); // modification detection expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.integrity_protect ? [1] : null); // modification detection
} };
var key = openpgp.generateKeyPair({numBits: 512, userId: 'test', passphrase: 'hello'}); var opt = {numBits: 512, userId: 'test', passphrase: 'hello'};
testPref(key.key); openpgp.generateKeyPair(opt, function(err, key) {
testPref(openpgp.key.readArmored(key.publicKeyArmored).keys[0]); expect(err).to.not.exist;
testPref(key.key);
testPref(openpgp.key.readArmored(key.publicKeyArmored).keys[0]);
done();
});
}); });
it('User attribute packet read & write', function() { it('User attribute packet read & write', function() {
@ -653,11 +657,15 @@ var pgp_desktop_priv =
expect(primUser.selfCertificate).to.be.an.instanceof(openpgp.packet.Signature); expect(primUser.selfCertificate).to.be.an.instanceof(openpgp.packet.Signature);
}); });
it('Generated key is not unlocked by default', function() { it('Generated key is not unlocked by default', function(done) {
var key = openpgp.generateKeyPair({numBits: 512, userId: 'test', passphrase: '123'}); var opt = {numBits: 512, userId: 'test', passphrase: '123'};
var msg = openpgp.message.fromText('hello').encrypt([key.key]); openpgp.generateKeyPair(opt, function(err, key) {
msg = msg.decrypt.bind(msg, key.key); expect(err).to.not.exist;
expect(msg).to.throw('Private key is not decrypted.'); var msg = openpgp.message.fromText('hello').encrypt([key.key]);
msg = msg.decrypt.bind(msg, key.key);
expect(msg).to.throw('Private key is not decrypted.');
done();
});
}); });
}); });

View File

@ -6,445 +6,452 @@ var chai = require('chai'),
expect = chai.expect; expect = chai.expect;
describe("Packet", function() { describe("Packet", function() {
var armored_key = var armored_key =
'-----BEGIN PGP PRIVATE KEY BLOCK-----\n' + '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' +
'Version: GnuPG v2.0.19 (GNU/Linux)\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' +
'\n' + '\n' +
'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\n' +
'YRlci72GHhlyos8YHA==\n' + 'YRlci72GHhlyos8YHA==\n' +
'=KXkj\n' + '=KXkj\n' +
'-----END PGP PRIVATE KEY BLOCK-----'; '-----END PGP PRIVATE KEY BLOCK-----';
it('Symmetrically encrypted packet', function(done) { it('Symmetrically encrypted packet', function(done) {
var message = new openpgp.packet.List(); var message = new openpgp.packet.List();
var literal = new openpgp.packet.Literal(); var literal = new openpgp.packet.Literal();
literal.setText('Hello world'); literal.setText('Hello world');
var enc = new openpgp.packet.SymmetricallyEncrypted(); var enc = new openpgp.packet.SymmetricallyEncrypted();
message.push(enc); message.push(enc);
enc.packets.push(literal); enc.packets.push(literal);
var key = '12345678901234567890123456789012', var key = '12345678901234567890123456789012',
algo = 'aes256'; algo = 'aes256';
enc.encrypt(algo, key); enc.encrypt(algo, key);
var msg2 = new openpgp.packet.List(); var msg2 = new openpgp.packet.List();
msg2.read(message.write()); msg2.read(message.write());
msg2[0].decrypt(algo, key); msg2[0].decrypt(algo, key);
expect(msg2[0].packets[0].data).to.equal(literal.data); expect(msg2[0].packets[0].data).to.equal(literal.data);
done(); done();
}); });
it('Sym. encrypted integrity protected packet', function(done) { it('Sym. encrypted integrity protected packet', function(done) {
var key = '12345678901234567890123456789012', var key = '12345678901234567890123456789012',
algo = 'aes256'; algo = 'aes256';
var literal = new openpgp.packet.Literal(), var literal = new openpgp.packet.Literal(),
enc = new openpgp.packet.SymEncryptedIntegrityProtected(), enc = new openpgp.packet.SymEncryptedIntegrityProtected(),
msg = new openpgp.packet.List(); msg = new openpgp.packet.List();
msg.push(enc); msg.push(enc);
literal.setText('Hello world!'); literal.setText('Hello world!');
enc.packets.push(literal); enc.packets.push(literal);
enc.encrypt(algo, key); enc.encrypt(algo, key);
var msg2 = new openpgp.packet.List(); var msg2 = new openpgp.packet.List();
msg2.read(msg.write()); msg2.read(msg.write());
msg2[0].decrypt(algo, key); msg2[0].decrypt(algo, key);
expect(msg2[0].packets[0].data).to.equal(literal.data); expect(msg2[0].packets[0].data).to.equal(literal.data);
done(); done();
}); });
it('Sym encrypted session key with a compressed packet', function(done) { it('Sym encrypted session key with a compressed packet', function(done) {
var msg = var msg =
'-----BEGIN PGP MESSAGE-----\n' + '-----BEGIN PGP MESSAGE-----\n' +
'Version: GnuPG v2.0.19 (GNU/Linux)\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' +
'\n' + '\n' +
'jA0ECQMCpo7I8WqsebTJ0koBmm6/oqdHXJU9aPe+Po+nk/k4/PZrLmlXwz2lhqBg\n' + 'jA0ECQMCpo7I8WqsebTJ0koBmm6/oqdHXJU9aPe+Po+nk/k4/PZrLmlXwz2lhqBg\n' +
'GAlY9rxVStLBrg0Hn+5gkhyHI9B85rM1BEYXQ8pP5CSFuTwbJ3O2s67dzQ==\n' + 'GAlY9rxVStLBrg0Hn+5gkhyHI9B85rM1BEYXQ8pP5CSFuTwbJ3O2s67dzQ==\n' +
'=VZ0/\n' + '=VZ0/\n' +
'-----END PGP MESSAGE-----'; '-----END PGP MESSAGE-----';
var msgbytes = openpgp.armor.decode(msg).data; var msgbytes = openpgp.armor.decode(msg).data;
var parsed = new openpgp.packet.List(); var parsed = new openpgp.packet.List();
parsed.read(msgbytes); parsed.read(msgbytes);
parsed[0].decrypt('test'); parsed[0].decrypt('test');
var key = parsed[0].sessionKey; var key = parsed[0].sessionKey;
parsed[1].decrypt(parsed[0].sessionKeyAlgorithm, key); parsed[1].decrypt(parsed[0].sessionKeyAlgorithm, key);
var compressed = parsed[1].packets[0]; var compressed = parsed[1].packets[0];
var result = compressed.packets[0].data; var result = compressed.packets[0].data;
expect(result).to.equal('Hello world!\n'); expect(result).to.equal('Hello world!\n');
done(); done();
}); });
it('Public key encrypted symmetric key packet', function(done) { it('Public key encrypted symmetric key packet', function(done) {
var rsa = new openpgp.crypto.publicKey.rsa(), var rsa = new openpgp.crypto.publicKey.rsa();
mpi = rsa.generate(512, "10001")
var mpi = [mpi.n, mpi.ee, mpi.d, mpi.p, mpi.q, mpi.u]; rsa.generate(512, "10001", function(error, mpiGen) {
expect(error).to.not.exist;
mpi = mpi.map(function(k) { var mpi = [mpiGen.n, mpiGen.ee, mpiGen.d, mpiGen.p, mpiGen.q, mpiGen.u];
var mpi = new openpgp.MPI();
mpi.fromBigInteger(k);
return mpi;
});
var enc = new openpgp.packet.PublicKeyEncryptedSessionKey(), mpi = mpi.map(function(k) {
msg = new openpgp.packet.List(), var mpi = new openpgp.MPI();
msg2 = new openpgp.packet.List(); mpi.fromBigInteger(k);
return mpi;
});
enc.sessionKey = '12345678901234567890123456789012'; var enc = new openpgp.packet.PublicKeyEncryptedSessionKey(),
enc.publicKeyAlgorithm = 'rsa_encrypt'; msg = new openpgp.packet.List(),
enc.sessionKeyAlgorithm = 'aes256'; msg2 = new openpgp.packet.List();
enc.publicKeyId.bytes = '12345678';
enc.encrypt({ mpi: mpi });
msg.push(enc); enc.sessionKey = '12345678901234567890123456789012';
enc.publicKeyAlgorithm = 'rsa_encrypt';
enc.sessionKeyAlgorithm = 'aes256';
enc.publicKeyId.bytes = '12345678';
enc.encrypt({ mpi: mpi });
msg2.read(msg.write()); msg.push(enc);
msg2[0].decrypt({ mpi: mpi }); msg2.read(msg.write());
expect(msg2[0].sessionKey).to.equal(enc.sessionKey); msg2[0].decrypt({ mpi: mpi });
expect(msg2[0].sessionKeyAlgorithm).to.equal(enc.sessionKeyAlgorithm);
done(); expect(msg2[0].sessionKey).to.equal(enc.sessionKey);
expect(msg2[0].sessionKeyAlgorithm).to.equal(enc.sessionKeyAlgorithm);
done();
});
}); });
it('Secret key packet (reading, unencrpted)', function(done) { it('Secret key packet (reading, unencrpted)', function(done) {
var armored_key = var armored_key =
'-----BEGIN PGP PRIVATE KEY BLOCK-----\n' + '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' +
'Version: GnuPG v2.0.19 (GNU/Linux)\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' +
'\n' + '\n' +
'lQHYBFF33iMBBAC9YfOYahJlWrVj2J1TjQiZLunWljI4G9e6ARTyD99nfOkV3swh\n' + 'lQHYBFF33iMBBAC9YfOYahJlWrVj2J1TjQiZLunWljI4G9e6ARTyD99nfOkV3swh\n' +
'0WaOse4Utj7BfTqdYcoezhCaQpuExUupKWZqmduBcwSmEBfNu1XyKcxlDQuuk0Vk\n' + '0WaOse4Utj7BfTqdYcoezhCaQpuExUupKWZqmduBcwSmEBfNu1XyKcxlDQuuk0Vk\n' +
'viGC3kFRce/cJaKVFSRU8V5zPgt6KQNv/wNz7ydEisaSoNbk51vQt5oGfwARAQAB\n' + 'viGC3kFRce/cJaKVFSRU8V5zPgt6KQNv/wNz7ydEisaSoNbk51vQt5oGfwARAQAB\n' +
'AAP5AVL8xWMuKgLj9g7/wftMH+jO7vhAxje2W3Y+8r8TnOSn0536lQvzl/eQyeLC\n' + 'AAP5AVL8xWMuKgLj9g7/wftMH+jO7vhAxje2W3Y+8r8TnOSn0536lQvzl/eQyeLC\n' +
'VK2k3+7+trgO7I4KuXCXZqgAbEi3niDYXDaCJ+8gdR9qvPM2gi9NM71TGXZvGE0w\n' + 'VK2k3+7+trgO7I4KuXCXZqgAbEi3niDYXDaCJ+8gdR9qvPM2gi9NM71TGXZvGE0w\n' +
'X8gIZfqLTQWKm9TIS/3tdrth4nwhiye0ASychOboIiN6VIECAMbCQ4/noxGV6yTK\n' + 'X8gIZfqLTQWKm9TIS/3tdrth4nwhiye0ASychOboIiN6VIECAMbCQ4/noxGV6yTK\n' +
'VezsGSz+iCMxz2lV270/Ac2C5WPk+OlxXloxUXeEkGIr6Xkmhhpceed2KL41UC8Y\n' + 'VezsGSz+iCMxz2lV270/Ac2C5WPk+OlxXloxUXeEkGIr6Xkmhhpceed2KL41UC8Y\n' +
'w5ttGIECAPPsahniKGyqp9CHy6W0B83yhhcIbmLlaVG2ftKyUEDxIggzOlXuVrue\n' + 'w5ttGIECAPPsahniKGyqp9CHy6W0B83yhhcIbmLlaVG2ftKyUEDxIggzOlXuVrue\n' +
'z9XRd6wFqwDd1QMFW0uUyHPDCIFPnv8CAJaDFSZutuWdWMt15NZXjfgRgfJuDrtv\n' + 'z9XRd6wFqwDd1QMFW0uUyHPDCIFPnv8CAJaDFSZutuWdWMt15NZXjfgRgfJuDrtv\n' +
'E7yFY/p0el8lCihOT8WoHbTn1PbCYMzNBc0IhHaZKAtA2pjkE+wzz9ClP7QbR2Vv\n' + 'E7yFY/p0el8lCihOT8WoHbTn1PbCYMzNBc0IhHaZKAtA2pjkE+wzz9ClP7QbR2Vv\n' +
'cmdlIDxnZW9yZ2VAZXhhbXBsZS5jb20+iLkEEwECACMFAlF33iMCGwMHCwkIBwMC\n' + 'cmdlIDxnZW9yZ2VAZXhhbXBsZS5jb20+iLkEEwECACMFAlF33iMCGwMHCwkIBwMC\n' +
'AQYVCAIJCgsEFgIDAQIeAQIXgAAKCRBcqs36fwJCXRbvA/9LPiK6WFKcFoNBnLEJ\n' + 'AQYVCAIJCgsEFgIDAQIeAQIXgAAKCRBcqs36fwJCXRbvA/9LPiK6WFKcFoNBnLEJ\n' +
'mS/CNkL8yTpkslpCP6+TwJMc8uXqwYl9/PW2+CwmzZjs6JsvTzMcR/ZbfZJuSW6Y\n' + 'mS/CNkL8yTpkslpCP6+TwJMc8uXqwYl9/PW2+CwmzZjs6JsvTzMcR/ZbfZJuSW6Y\n' +
'EsLNejsSpgcY9aiewGtE+53e5oKYnlmVMTWOPywciIgMvXlzdGhxcwqJ8u0hT+ug\n' + 'EsLNejsSpgcY9aiewGtE+53e5oKYnlmVMTWOPywciIgMvXlzdGhxcwqJ8u0hT+ug\n' +
'9CjcAfuX9yw85LwXtdGwNh7J8Q==\n' + '9CjcAfuX9yw85LwXtdGwNh7J8Q==\n' +
'=lKiS\n' + '=lKiS\n' +
'-----END PGP PRIVATE KEY BLOCK-----'; '-----END PGP PRIVATE KEY BLOCK-----';
var key = new openpgp.packet.List(); var key = new openpgp.packet.List();
key.read(openpgp.armor.decode(armored_key).data); key.read(openpgp.armor.decode(armored_key).data);
key = key[0]; key = key[0];
var enc = new openpgp.packet.PublicKeyEncryptedSessionKey(), var enc = new openpgp.packet.PublicKeyEncryptedSessionKey(),
secret = '12345678901234567890123456789012'; secret = '12345678901234567890123456789012';
enc.sessionKey = secret; enc.sessionKey = secret;
enc.publicKeyAlgorithm = 'rsa_encrypt'; enc.publicKeyAlgorithm = 'rsa_encrypt';
enc.sessionKeyAlgorithm = 'aes256'; enc.sessionKeyAlgorithm = 'aes256';
enc.publicKeyId.bytes = '12345678'; enc.publicKeyId.bytes = '12345678';
enc.encrypt(key); enc.encrypt(key);
enc.decrypt(key); enc.decrypt(key);
expect(enc.sessionKey).to.equal(secret); expect(enc.sessionKey).to.equal(secret);
done(); done();
}); });
it('Public key encrypted packet (reading, GPG)', function(done) { it('Public key encrypted packet (reading, GPG)', function(done) {
var armored_key = var armored_key =
'-----BEGIN PGP PRIVATE KEY BLOCK-----\n' + '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' +
'Version: GnuPG v2.0.19 (GNU/Linux)\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' +
'\n' + '\n' +
'lQHYBFF6gtkBBADKUOWZK6/V75MNwBS+hLYicoS0Sojbo3qWXXpS7eM+uhiDm4bP\n' + 'lQHYBFF6gtkBBADKUOWZK6/V75MNwBS+hLYicoS0Sojbo3qWXXpS7eM+uhiDm4bP\n' +
'DNjdNVA0R+TCjvhWbc3W6cvdHYTmHRMhTIOefncZRt3OwF7AvVk53fKKPiNNv5C9\n' + 'DNjdNVA0R+TCjvhWbc3W6cvdHYTmHRMhTIOefncZRt3OwF7AvVk53fKKPiNNv5C9\n' +
'IK8bcDhAknSOg1TXRSpXLHtYy36A6iDgffNSjoCOVaeKpuRDMA37PvJWFQARAQAB\n' + 'IK8bcDhAknSOg1TXRSpXLHtYy36A6iDgffNSjoCOVaeKpuRDMA37PvJWFQARAQAB\n' +
'AAP+KxHbOwcrnPPuXppCYEew3Xb7LMWESpvMFFgsmxx1COzFnLjek1P1E+yOWT7n\n' + 'AAP+KxHbOwcrnPPuXppCYEew3Xb7LMWESpvMFFgsmxx1COzFnLjek1P1E+yOWT7n\n' +
'4opcsEuaazLk+TrYSMOuR6O6DgGg5c+ctVPU+NGNNCiiTkOzuD+8ow8NgsoINOxi\n' + '4opcsEuaazLk+TrYSMOuR6O6DgGg5c+ctVPU+NGNNCiiTkOzuD+8ow8NgsoINOxi\n' +
'481qLK0NYpc5sEg394J3fRuzpfEi6DTS/RzCN7YDiGFccNECAM71NuaAzH5LrZ+B\n' + '481qLK0NYpc5sEg394J3fRuzpfEi6DTS/RzCN7YDiGFccNECAM71NuaAzH5LrZ+B\n' +
'4Okwy9CQQbgoYrdaia24CjEaUODaROnyNsvOb0ydEebVAbGzrsBr6LrisTidyZsG\n' + '4Okwy9CQQbgoYrdaia24CjEaUODaROnyNsvOb0ydEebVAbGzrsBr6LrisTidyZsG\n' +
't2T+L7ECAPpCFzZIwwk6giZ10HmXEhXZLXYmdhQD/1fwegpTrEciMA6MCcdkcCyO\n' + 't2T+L7ECAPpCFzZIwwk6giZ10HmXEhXZLXYmdhQD/1fwegpTrEciMA6MCcdkcCyO\n' +
'2/J+S+NXM62ykMGDhg2cjhU1rj/uaaUCAJfCjkwpxMsDKHYDFDXyjJFy2vEmA3s8\n' + '2/J+S+NXM62ykMGDhg2cjhU1rj/uaaUCAJfCjkwpxMsDKHYDFDXyjJFy2vEmA3s8\n' +
'cnmAUDF1caPyEcPEZmYJRE+KdroOD6IGhzp7oA34Ef3D6HOCovH9YaCgbbQbSm9o\n' + 'cnmAUDF1caPyEcPEZmYJRE+KdroOD6IGhzp7oA34Ef3D6HOCovH9YaCgbbQbSm9o\n' +
'bm55IDxqb2hubnlAZXhhbXBsZS5jb20+iLkEEwECACMFAlF6gtkCGwMHCwkIBwMC\n' + 'bm55IDxqb2hubnlAZXhhbXBsZS5jb20+iLkEEwECACMFAlF6gtkCGwMHCwkIBwMC\n' +
'AQYVCAIJCgsEFgIDAQIeAQIXgAAKCRA6HTM8yP08keZgA/4vL273zrqnmOrqmo/K\n' + 'AQYVCAIJCgsEFgIDAQIeAQIXgAAKCRA6HTM8yP08keZgA/4vL273zrqnmOrqmo/K\n' +
'UxQgD0vMhM58d25UjGYI6LAZkAls/k4FvFt5GUHVWJR3HBRuuNlB7UndH/uYlU7j\n' + 'UxQgD0vMhM58d25UjGYI6LAZkAls/k4FvFt5GUHVWJR3HBRuuNlB7UndH/uYlU7j\n' +
'm/bQLiP4uvFQuRGuG76f0O5t/KyeUdzrpNiJpe8tYDAnoPxUzENYsIv0fm2ZISo1\n' + 'm/bQLiP4uvFQuRGuG76f0O5t/KyeUdzrpNiJpe8tYDAnoPxUzENYsIv0fm2ZISo1\n' +
'QnnXX2WuVZGMZH1YhQoakZxbnp0B2ARReoLZAQQAvQvPp2MLu9vnRvZ3Py559kQf\n' + 'QnnXX2WuVZGMZH1YhQoakZxbnp0B2ARReoLZAQQAvQvPp2MLu9vnRvZ3Py559kQf\n' +
'0Z5AnEXVokALTn5A2m51dLekQ9T3Rhz8p9I6C/XjVQwBkp1USOaDUz+L7lsbNdY4\n' + '0Z5AnEXVokALTn5A2m51dLekQ9T3Rhz8p9I6C/XjVQwBkp1USOaDUz+L7lsbNdY4\n' +
'YbUi3eIA5RImVXeTIrD1hE4CllDNKmqT5wFN07eEu7QhDEuYioO+4gtjjhUDYeIA\n' + 'YbUi3eIA5RImVXeTIrD1hE4CllDNKmqT5wFN07eEu7QhDEuYioO+4gtjjhUDYeIA\n' +
'dCVtVO//q8rP8ukZEc8AEQEAAQAD/RHlttyNe3RnDr/AoKx6HXDLpUmGlm5VDDMm\n' + 'dCVtVO//q8rP8ukZEc8AEQEAAQAD/RHlttyNe3RnDr/AoKx6HXDLpUmGlm5VDDMm\n' +
'pgth14j2cSdCJYqIdHqOTvsiY31zY3jPQKzdOTgHnsI4X2qK9InbwXepSBkaOJzY\n' + 'pgth14j2cSdCJYqIdHqOTvsiY31zY3jPQKzdOTgHnsI4X2qK9InbwXepSBkaOJzY\n' +
'iNhifPSUs9qoNawDqbFJ8PMXd4QQGgM93w+tudKC650Zuq7M7eWSdQg0u9aoLY97\n' + 'iNhifPSUs9qoNawDqbFJ8PMXd4QQGgM93w+tudKC650Zuq7M7eWSdQg0u9aoLY97\n' +
'MpKx3DUFAgDA/RgoO8xYMgkKN1tuKWa61qesLdJRAZI/3cnvtsmmEBt9tdbcDoBz\n' + 'MpKx3DUFAgDA/RgoO8xYMgkKN1tuKWa61qesLdJRAZI/3cnvtsmmEBt9tdbcDoBz\n' +
'gOIAAvUFgipuP6dBWLyf2NRNRVVQdNTlAgD6xS7S87g3kTa3GLcEI2cveaP1WWNK\n' + 'gOIAAvUFgipuP6dBWLyf2NRNRVVQdNTlAgD6xS7S87g3kTa3GLcEI2cveaP1WWNK\n' +
'rKFnVWsjBKArKFzMQ5N6FMnFD4T96i3sYlACE5UjH90SpOgBKOpdKzSjAf9nghrw\n' + 'rKFnVWsjBKArKFzMQ5N6FMnFD4T96i3sYlACE5UjH90SpOgBKOpdKzSjAf9nghrw\n' +
'kbFbF708ZIpVEwxvp/JoSutYUQ4v01MImnCGqzDVuSef3eutLLu4ZG7kLekxNauV\n' + 'kbFbF708ZIpVEwxvp/JoSutYUQ4v01MImnCGqzDVuSef3eutLLu4ZG7kLekxNauV\n' +
'8tGFwxsdtv30RL/3nW+InwQYAQIACQUCUXqC2QIbDAAKCRA6HTM8yP08kRXjBACu\n' + '8tGFwxsdtv30RL/3nW+InwQYAQIACQUCUXqC2QIbDAAKCRA6HTM8yP08kRXjBACu\n' +
'RtEwjU+p6qqm3pmh7xz1CzhQN1F7VOj9dFUeECJJ1iv8J71w5UINH0otIceeBeWy\n' + 'RtEwjU+p6qqm3pmh7xz1CzhQN1F7VOj9dFUeECJJ1iv8J71w5UINH0otIceeBeWy\n' +
'NLA/QvK8+4/b9QW+S8aDZyeZpYg37gBwdTNGNT7TsEAxz9SUbx9uRja0wNmtb5xW\n' + 'NLA/QvK8+4/b9QW+S8aDZyeZpYg37gBwdTNGNT7TsEAxz9SUbx9uRja0wNmtb5xW\n' +
'mG+VE8CBXNkp8JTWx05AHwtK3baWlHWwpwnRlbU94Q==\n' + 'mG+VE8CBXNkp8JTWx05AHwtK3baWlHWwpwnRlbU94Q==\n' +
'=FSwA\n' + '=FSwA\n' +
'-----END PGP PRIVATE KEY BLOCK-----'; '-----END PGP PRIVATE KEY BLOCK-----';
var armored_msg = var armored_msg =
'-----BEGIN PGP MESSAGE-----\n' + '-----BEGIN PGP MESSAGE-----\n' +
'Version: GnuPG v2.0.19 (GNU/Linux)\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' +
'\n' + '\n' +
'hIwDFYET+7bfx/ABA/95Uc9942Tg8oqpO0vEu2eSKwPALM3a0DrVdAiFOIK/dJmZ\n' + 'hIwDFYET+7bfx/ABA/95Uc9942Tg8oqpO0vEu2eSKwPALM3a0DrVdAiFOIK/dJmZ\n' +
'YrtPRw3EEwHZjl6CO9RD+95iE27tPbsICw1K43gofSV/wWsPO6vvs3eftQYHSxxa\n' + 'YrtPRw3EEwHZjl6CO9RD+95iE27tPbsICw1K43gofSV/wWsPO6vvs3eftQYHSxxa\n' +
'IQbTPImiRaJ73Mf7iM3CNtQM4iUBsx1HnUGl+rtD0nz3fLm6i3CjwiNQWW42I9JH\n' + 'IQbTPImiRaJ73Mf7iM3CNtQM4iUBsx1HnUGl+rtD0nz3fLm6i3CjwiNQWW42I9JH\n' +
'AWv8EvvpxZ8X2ClFfSW3UVBoROHe9CAWHM/40nGutAZK8MIgmUI4xqkLFBbqqTyx\n' + 'AWv8EvvpxZ8X2ClFfSW3UVBoROHe9CAWHM/40nGutAZK8MIgmUI4xqkLFBbqqTyx\n' +
'/cDSC4Q+sv65UX4urbfc7uJuk1Cpj54=\n' + '/cDSC4Q+sv65UX4urbfc7uJuk1Cpj54=\n' +
'=iSaK\n' + '=iSaK\n' +
'-----END PGP MESSAGE-----'; '-----END PGP MESSAGE-----';
var key = new openpgp.packet.List();
key.read(openpgp.armor.decode(armored_key).data);
key = key[3];
var key = new openpgp.packet.List(); var msg = new openpgp.packet.List();
key.read(openpgp.armor.decode(armored_key).data); msg.read(openpgp.armor.decode(armored_msg).data);
key = key[3];
var msg = new openpgp.packet.List(); msg[0].decrypt(key);
msg.read(openpgp.armor.decode(armored_msg).data); msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
msg[0].decrypt(key); var text = msg[1].packets[0].packets[0].data;
msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
var text = msg[1].packets[0].packets[0].data;
expect(text).to.equal('Hello world!'); expect(text).to.equal('Hello world!');
done(); done();
}); });
it('Sym encrypted session key reading/writing', function(done) { it('Sym encrypted session key reading/writing', function(done) {
var passphrase = 'hello', var passphrase = 'hello',
algo = 'aes256'; algo = 'aes256';
var literal = new openpgp.packet.Literal(), var literal = new openpgp.packet.Literal(),
key_enc = new openpgp.packet.SymEncryptedSessionKey(), key_enc = new openpgp.packet.SymEncryptedSessionKey(),
enc = new openpgp.packet.SymEncryptedIntegrityProtected(), enc = new openpgp.packet.SymEncryptedIntegrityProtected(),
msg = new openpgp.packet.List(); msg = new openpgp.packet.List();
msg.push(key_enc); msg.push(key_enc);
msg.push(enc); msg.push(enc);
key_enc.sessionKeyAlgorithm = algo; key_enc.sessionKeyAlgorithm = algo;
key_enc.decrypt(passphrase); key_enc.decrypt(passphrase);
var key = key_enc.sessionKey; var key = key_enc.sessionKey;
literal.setText('Hello world!'); literal.setText('Hello world!');
enc.packets.push(literal); enc.packets.push(literal);
enc.encrypt(algo, key); enc.encrypt(algo, key);
var msg2 = new openpgp.packet.List(); var msg2 = new openpgp.packet.List();
msg2.read(msg.write()); msg2.read(msg.write());
msg2[0].decrypt(passphrase); msg2[0].decrypt(passphrase);
var key2 = msg2[0].sessionKey; var key2 = msg2[0].sessionKey;
msg2[1].decrypt(msg2[0].sessionKeyAlgorithm, key2); msg2[1].decrypt(msg2[0].sessionKeyAlgorithm, key2);
expect(msg2[1].packets[0].data).to.equal(literal.data); expect(msg2[1].packets[0].data).to.equal(literal.data);
done(); done();
}); });
it('Secret key encryption/decryption test', function(done) { it('Secret key encryption/decryption test', function(done) {
var armored_msg = var armored_msg =
'-----BEGIN PGP MESSAGE-----\n' + '-----BEGIN PGP MESSAGE-----\n' +
'Version: GnuPG v2.0.19 (GNU/Linux)\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' +
'\n' + '\n' +
'hIwD95D9aHS5fxEBA/98CwH54XZmwobOmHUcvWcDDQysBEC4uf7wASiGcRbejDaO\n' + 'hIwD95D9aHS5fxEBA/98CwH54XZmwobOmHUcvWcDDQysBEC4uf7wASiGcRbejDaO\n' +
'aJqcrK/3k8sBQMO7yOhvrCRqqpGDqnmx7IaaKLnZS7nYAZoHEsK9UyG0hDa8Cfbo\n' + 'aJqcrK/3k8sBQMO7yOhvrCRqqpGDqnmx7IaaKLnZS7nYAZoHEsK9UyG0hDa8Cfbo\n' +
'CP4xZVcgIvIfAW/in1LeT2td0QcQNbeewBmPea+vQEEvRgIP10tlE7MK8Ay48dJH\n' + 'CP4xZVcgIvIfAW/in1LeT2td0QcQNbeewBmPea+vQEEvRgIP10tlE7MK8Ay48dJH\n' +
'AagMgNYg7MBUjpuOCVrjM1pWja8uzbULfYhTq3IJ8H3QhbdT+k9khY9f0aJPEeYi\n' + 'AagMgNYg7MBUjpuOCVrjM1pWja8uzbULfYhTq3IJ8H3QhbdT+k9khY9f0aJPEeYi\n' +
'dVv6DK9uviMGc/DsVCw5K8lQRLlkcHc=\n' + 'dVv6DK9uviMGc/DsVCw5K8lQRLlkcHc=\n' +
'=pR+C\n' + '=pR+C\n' +
'-----END PGP MESSAGE-----'; '-----END PGP MESSAGE-----';
var key = new openpgp.packet.List(); var key = new openpgp.packet.List();
key.read(openpgp.armor.decode(armored_key).data); key.read(openpgp.armor.decode(armored_key).data);
key = key[3]; key = key[3];
key.decrypt('test'); key.decrypt('test');
var msg = new openpgp.packet.List(); var msg = new openpgp.packet.List();
msg.read(openpgp.armor.decode(armored_msg).data); msg.read(openpgp.armor.decode(armored_msg).data);
msg[0].decrypt(key); msg[0].decrypt(key);
msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey); msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
var text = msg[1].packets[0].packets[0].data; var text = msg[1].packets[0].packets[0].data;
expect(text).to.equal('Hello world!'); expect(text).to.equal('Hello world!');
done(); done();
}); });
it('Secret key reading with signature verification.', function(done) { it('Secret key reading with signature verification.', function(done) {
var key = new openpgp.packet.List(); var key = new openpgp.packet.List();
key.read(openpgp.armor.decode(armored_key).data); key.read(openpgp.armor.decode(armored_key).data);
var verified = key[2].verify(key[0], var verified = key[2].verify(key[0],
{ {
userid: key[1], userid: key[1],
key: key[0] key: key[0]
}); });
verified = verified && key[4].verify(key[0], verified = verified && key[4].verify(key[0],
{ {
key: key[0], key: key[0],
bind: key[3] bind: key[3]
}); });
expect(verified).to.be.true; expect(verified).to.be.true;
done(); done();
}); });
it('Reading a signed, encrypted message.', function(done) { it('Reading a signed, encrypted message.', function(done) {
var armored_msg = var armored_msg =
'-----BEGIN PGP MESSAGE-----\n' + '-----BEGIN PGP MESSAGE-----\n' +
'Version: GnuPG v2.0.19 (GNU/Linux)\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' +
'\n' + '\n' +
'hIwD95D9aHS5fxEBA/4/X4myvH+jB1HYNeZvdK+WsBNDMfLsBGOf205Rxr3vSob/\n' + 'hIwD95D9aHS5fxEBA/4/X4myvH+jB1HYNeZvdK+WsBNDMfLsBGOf205Rxr3vSob/\n' +
'A09boj8/9lFaipqu+AEdQKEjCB8sZ+OY0WiQPEPpuhG+mVqDqEiPFkdpcqNtS0VV\n' + 'A09boj8/9lFaipqu+AEdQKEjCB8sZ+OY0WiQPEPpuhG+mVqDqEiPFkdpcqNtS0VV\n' +
'pwqplHo6QnH2MHfxprZHYuwcEC9ynJCxJ6kSCD8Xs99h+PjxNNw7NhMjkF+N69LA\n' + 'pwqplHo6QnH2MHfxprZHYuwcEC9ynJCxJ6kSCD8Xs99h+PjxNNw7NhMjkF+N69LA\n' +
'NwGPtbLx2/r2nR4gO8gV92A2RQCOwPP7ZV+6fXgWIs+mhyCHFP3xUP5DaFCNM8mo\n' + 'NwGPtbLx2/r2nR4gO8gV92A2RQCOwPP7ZV+6fXgWIs+mhyCHFP3xUP5DaFCNM8mo\n' +
'PN97i659ucxF6IbOoK56FEaUbOPTD6xdyhWamxKfMsIb0UJgVUNhGaq+VlvOJxaB\n' + 'PN97i659ucxF6IbOoK56FEaUbOPTD6xdyhWamxKfMsIb0UJgVUNhGaq+VlvOJxaB\n' +
'iRcnY5UxsypKgtqfcKIseb21MIo4vcNdogyxBIDlAO472Zfxn0udzr6W2aQ77+NK\n' + 'iRcnY5UxsypKgtqfcKIseb21MIo4vcNdogyxBIDlAO472Zfxn0udzr6W2aQ77+NK\n' +
'FE1O0kCXS+DTFOYYVD7X8rXGSglQsdXJmHd89sdYFQkO7D7bOLdRJuXgdgH2czCs\n' + 'FE1O0kCXS+DTFOYYVD7X8rXGSglQsdXJmHd89sdYFQkO7D7bOLdRJuXgdgH2czCs\n' +
'UBGuHZzsGbTdyKvpVBuS3rnyHHBk6oCnsm1Nl7eLs64VkZUxjEUbq5pb4dlr1pw2\n' + 'UBGuHZzsGbTdyKvpVBuS3rnyHHBk6oCnsm1Nl7eLs64VkZUxjEUbq5pb4dlr1pw2\n' +
'ztpmpAnRcmM=\n' + 'ztpmpAnRcmM=\n' +
'=htrB\n' + '=htrB\n' +
'-----END PGP MESSAGE-----' '-----END PGP MESSAGE-----'
var key = new openpgp.packet.List(); var key = new openpgp.packet.List();
key.read(openpgp.armor.decode(armored_key).data); key.read(openpgp.armor.decode(armored_key).data);
key[3].decrypt('test') key[3].decrypt('test')
var msg = new openpgp.packet.List(); var msg = new openpgp.packet.List();
msg.read(openpgp.armor.decode(armored_msg).data); msg.read(openpgp.armor.decode(armored_msg).data);
msg[0].decrypt(key[3]); msg[0].decrypt(key[3]);
msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey); msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
var payload = msg[1].packets[0].packets var payload = msg[1].packets[0].packets
var verified = payload[2].verify(key[0], payload[1]); var verified = payload[2].verify(key[0], payload[1]);
expect(verified).to.be.true; expect(verified).to.be.true;
done(); done();
}); });
it('Writing and encryption of a secret key packet.', function(done) { it('Writing and encryption of a secret key packet.', function(done) {
var key = new openpgp.packet.List(); var key = new openpgp.packet.List();
key.push(new openpgp.packet.SecretKey); key.push(new openpgp.packet.SecretKey);
var rsa = new openpgp.crypto.publicKey.rsa(), var rsa = new openpgp.crypto.publicKey.rsa();
mpi = rsa.generate(512, "10001")
rsa.generate(512, "10001", function(err, mipGen) {
expect(err).to.not.exist;
var mpi = [mpi.n, mpi.ee, mpi.d, mpi.p, mpi.q, mpi.u]; var mpi = [mipGen.n, mipGen.ee, mipGen.d, mipGen.p, mipGen.q, mipGen.u];
mpi = mpi.map(function(k) { mpi = mpi.map(function(k) {
var mpi = new openpgp.MPI(); var mpi = new openpgp.MPI();
mpi.fromBigInteger(k); mpi.fromBigInteger(k);
return mpi; return mpi;
}); });
key[0].mpi = mpi; key[0].mpi = mpi;
key[0].encrypt('hello'); key[0].encrypt('hello');
var raw = key.write(); var raw = key.write();
var key2 = new openpgp.packet.List(); var key2 = new openpgp.packet.List();
key2.read(raw); key2.read(raw);
key2[0].decrypt('hello'); key2[0].decrypt('hello');
expect(key[0].mpi.toString()).to.equal(key2[0].mpi.toString()); expect(key[0].mpi.toString()).to.equal(key2[0].mpi.toString());
done(); done();
});
}); });
it('Writing and verification of a signature packet.', function(done) { it('Writing and verification of a signature packet.', function(done) {
var key = new openpgp.packet.SecretKey(); var key = new openpgp.packet.SecretKey();
var rsa = new openpgp.crypto.publicKey.rsa, var rsa = new openpgp.crypto.publicKey.rsa;
mpi = rsa.generate(512, "10001")
var mpi = [mpi.n, mpi.ee, mpi.d, mpi.p, mpi.q, mpi.u]; rsa.generate(512, "10001", function(err, mpiGen) {
expect(err).to.not.exist;
mpi = mpi.map(function(k) { var mpi = [mpiGen.n, mpiGen.ee, mpiGen.d, mpiGen.p, mpiGen.q, mpiGen.u];
var mpi = new openpgp.MPI();
mpi.fromBigInteger(k);
return mpi;
});
key.mpi = mpi; mpi = mpi.map(function(k) {
var mpi = new openpgp.MPI();
mpi.fromBigInteger(k);
return mpi;
});
var signed = new openpgp.packet.List(), key.mpi = mpi;
literal = new openpgp.packet.Literal(),
signature = new openpgp.packet.Signature();
literal.setText('Hello world'); var signed = new openpgp.packet.List(),
literal = new openpgp.packet.Literal(),
signature = new openpgp.packet.Signature();
signature.hashAlgorithm = 'sha256'; literal.setText('Hello world');
signature.publicKeyAlgorithm = 'rsa_sign';
signature.signatureType = 'binary';
signature.sign(key, literal); signature.hashAlgorithm = 'sha256';
signature.publicKeyAlgorithm = 'rsa_sign';
signature.signatureType = 'binary';
signed.push(literal); signature.sign(key, literal);
signed.push(signature);
var raw = signed.write(); signed.push(literal);
signed.push(signature);
var signed2 = new openpgp.packet.List(); var raw = signed.write();
signed2.read(raw);
var verified = signed2[1].verify(key, signed2[0]); var signed2 = new openpgp.packet.List();
signed2.read(raw);
expect(verified).to.be.true; var verified = signed2[1].verify(key, signed2[0]);
done();
expect(verified).to.be.true;
done();
});
}); });
}); });

View File

@ -636,13 +636,19 @@ describe("Signature", function() {
expect(result[0].valid).to.be.true; expect(result[0].valid).to.be.true;
}); });
it('Sign message with key without password', function() { it('Sign message with key without password', function(done) {
var key = openpgp.generateKeyPair({numBits: 512, userId: 'ABC', passphrase: null}).key; var opt = {numBits: 512, userId: 'ABC', passphrase: null};
openpgp.generateKeyPair(opt, function(err, gen) {
expect(err).to.not.exist;
var message = openpgp.message.fromText('hello world'); var key = gen.key;
message = message.sign([key]);
expect(message).to.exist; var message = openpgp.message.fromText('hello world');
message = message.sign([key]);
expect(message).to.exist;
done();
});
}); });
}); });

View File

@ -427,14 +427,6 @@ describe('High level API', function() {
}); });
}); });
it('Generate 1024-bit RSA/RSA key sync', function () {
var key = openpgp.generateKeyPair({numBits: 1024, userId: 'Test McTestington <test@example.com>', passphrase: 'hello world'});
expect(key).to.exist;
expect(key.publicKeyArmored).to.match(/^-----BEGIN PGP PUBLIC/);
expect(key.privateKeyArmored).to.match(/^-----BEGIN PGP PRIVATE/);
expect(key.key).to.be.an.instanceof(openpgp.key.Key);
});
}); });
describe('Decrypt secret key', function() { describe('Decrypt secret key', function() {