From cbe4a17ccb035683207bcc17cb1d593fbe2be311 Mon Sep 17 00:00:00 2001 From: Tankred Hase Date: Tue, 30 Sep 2014 15:38:02 +0200 Subject: [PATCH] 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" --- package.json | 2 +- src/crypto/crypto.js | 62 ++-- src/crypto/public_key/rsa.js | 55 ++-- src/key.js | 194 ++++++----- src/openpgp.js | 26 +- src/packet/secret_key.js | 20 +- src/worker/worker.js | 22 +- test/general/basic.js | 163 ++++----- test/general/key.js | 30 +- test/general/packet.js | 621 ++++++++++++++++++----------------- test/general/signature.js | 30 +- test/worker/api.js | 8 - 12 files changed, 650 insertions(+), 583 deletions(-) diff --git a/package.json b/package.json index 10bab78b..8c31da29 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "openpgp", "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/", "engines": { "node": ">=0.8" diff --git a/src/crypto/crypto.js b/src/crypto/crypto.js index 78d6454b..6ae3f64e 100644 --- a/src/crypto/crypto.js +++ b/src/crypto/crypto.js @@ -1,19 +1,19 @@ // GPG4Browsers - An OpenPGP implementation in javascript // Copyright (C) 2011 Recurity Labs GmbH -// +// // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 3.0 of the License, or (at your option) any later version. -// +// // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. -// +// // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // The GPG4Browsers crypto interface @@ -32,12 +32,12 @@ var random = require('./random.js'), module.exports = { /** - * Encrypts data using the specified public key multiprecision integers + * Encrypts data using the specified public key multiprecision integers * and the specified algorithm. * @param {module:enums.publicKey} algo Algorithm to be used (See {@link http://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1}) * @param {Array} publicMPIs Algorithm dependent multiprecision integers * @param {module:type/mpi} data Data to be encrypted as MPI - * @return {Array} if RSA an module:type/mpi; + * @return {Array} if RSA an module:type/mpi; * if elgamal encryption an array of two module:type/mpi is returned; otherwise null */ publicKeyEncrypt: function(algo, publicMPIs, data) { @@ -76,9 +76,9 @@ module.exports = { * Decrypts data using the specified public key multiprecision integers of the private key, * the specified secretMPIs of the private key and the specified algorithm. * @param {module:enums.publicKey} algo Algorithm to be used (See {@link http://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1}) - * @param {Array} publicMPIs Algorithm dependent multiprecision integers + * @param {Array} publicMPIs Algorithm dependent multiprecision integers * of the public key part of the private key - * @param {Array} secretMPIs Algorithm dependent multiprecision integers + * @param {Array} secretMPIs Algorithm dependent multiprecision integers * of the private key used * @param {module:type/mpi} data Data to be encrypted as MPI * @return {module:type/mpi} returns a big integer containing the decrypted data; otherwise null @@ -178,15 +178,19 @@ module.exports = { } }, - generateMpi: function(algo, bits) { - var result = (function() { - switch (algo) { - case 'rsa_encrypt': - case 'rsa_encrypt_sign': - case 'rsa_sign': - //remember "publicKey" refers to the crypto/public_key dir - var rsa = new publicKey.rsa(); - var keyObject = rsa.generate(bits, "10001"); + generateMpi: function(algo, bits, callback) { + switch (algo) { + case 'rsa_encrypt': + case 'rsa_encrypt_sign': + case 'rsa_sign': + //remember "publicKey" refers to the crypto/public_key dir + var rsa = new publicKey.rsa(); + rsa.generate(bits, "10001", function(err, keyObject) { + if (err) { + callback(err); + return; + } + var output = []; output.push(keyObject.n); output.push(keyObject.ee); @@ -194,17 +198,21 @@ module.exports = { output.push(keyObject.p); output.push(keyObject.q); output.push(keyObject.u); - return output; - default: - throw new Error('Unsupported algorithm for key generation.'); - } - })(); - return result.map(function(bn) { - var mpi = new type_mpi(); - mpi.fromBigInteger(bn); - return mpi; - }); + callback(null, mapResult(output)); + }); + break; + 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; + }); + } }, diff --git a/src/crypto/public_key/rsa.js b/src/crypto/public_key/rsa.js index eb5de534..f1222bd2 100644 --- a/src/crypto/public_key/rsa.js +++ b/src/crypto/public_key/rsa.js @@ -133,13 +133,15 @@ function RSA() { // 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 = { name: 'RSASSA-PKCS1-v1_5', modulusLength: B, // the specified keysize in bits @@ -151,52 +153,34 @@ function RSA() { var extractable = true; // make generated key extractable - window.crypto.subtle.generateKey(keyGenOpt, extractable, ['sign', 'verify']) - .then(onGenerated) - .then(onExported); + subtle.generateKey(keyGenOpt, extractable, ['sign', 'verify']) + .then(onGenerated, callback) + .then(onExported, callback); + + return; } function onGenerated(key) { // export the generated keys as JsonWebKey (JWK) // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 - var p1 = window.crypto.subtle.exportKey('jwk', key.privateKey); - var p2 = window.crypto.subtle.exportKey('jwk', key.publicKey); - - return window.Promise.all([p1, p2]); + return subtle.exportKey('jwk', key.privateKey); } - function onExported(exported) { - // 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; - + function onExported(jwk) { // map JWK parameters to local BigInteger type system 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.d = new BigInteger(util.hexstrdump(base64(d)), 16); - key.p = new BigInteger(util.hexstrdump(base64(p)), 16); - key.q = new BigInteger(util.hexstrdump(base64(q)), 16); + key.d = new BigInteger(util.hexstrdump(base64(jwk.d)), 16); + key.p = new BigInteger(util.hexstrdump(base64(jwk.p)), 16); + key.q = new BigInteger(util.hexstrdump(base64(jwk.q)), 16); key.u = key.p.modInverse(key.q); 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; } } - return key; + + callback(null, key); } this.encrypt = encrypt; diff --git a/src/key.js b/src/key.js index fbe1b6c7..2a730375 100644 --- a/src/key.js +++ b/src/key.js @@ -1,6 +1,6 @@ // GPG4Browsers - An OpenPGP implementation in javascript // Copyright (C) 2011 Recurity Labs GmbH -// +// // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either @@ -10,7 +10,7 @@ // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. -// +// // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -148,14 +148,14 @@ Key.prototype.toPacketlist = function() { if (this.subKeys) { for (i = 0; i < this.subKeys.length; i++) { packetlist.concat(this.subKeys[i].toPacketlist()); - } + } } return packetlist; }; -/** +/** * Returns all the private and public subkey packets - * @returns {Array<(module:packet/public_subkey|module:packet/secret_subkey)>} + * @returns {Array<(module:packet/public_subkey|module:packet/secret_subkey)>} */ Key.prototype.getSubkeyPackets = function() { var subKeys = []; @@ -167,17 +167,17 @@ Key.prototype.getSubkeyPackets = function() { return subKeys; }; -/** +/** * Returns all the private and public key and subkey packets - * @returns {Array<(module:packet/public_subkey|module:packet/secret_subkey|module:packet/secret_key|module:packet/public_key)>} + * @returns {Array<(module:packet/public_subkey|module:packet/secret_subkey|module:packet/secret_key|module:packet/public_key)>} */ Key.prototype.getAllKeyPackets = function() { return [this.primaryKey].concat(this.getSubkeyPackets()); }; -/** +/** * Returns key IDs of all key packets - * @returns {Array} + * @returns {Array} */ Key.prototype.getKeyIds = function() { var keyIds = []; @@ -197,7 +197,7 @@ Key.prototype.getKeyIds = function() { Key.prototype.getKeyPacket = function(keyIds) { var keys = this.getAllKeyPackets(); for (var i = 0; i < keys.length; i++) { - var keyId = keys[i].getKeyId(); + var keyId = keys[i].getKeyId(); for (var j = 0; j < keyIds.length; j++) { if (keyId.equals(keyIds[j])) { return keys[i]; @@ -284,7 +284,7 @@ Key.prototype.getSigningKeyPacket = function() { throw new Error('Need private key for signing'); } var primaryUser = this.getPrimaryUser(); - if (primaryUser && + if (primaryUser && isValidSigningKeyPacket(this.primaryKey, primaryUser.selfCertificate)) { return this.primaryKey; } @@ -342,7 +342,7 @@ Key.prototype.getEncryptionKeyPacket = function() { } // if no valid subkey for encryption, evaluate primary key var primaryUser = this.getPrimaryUser(); - if (primaryUser && + if (primaryUser && isValidEncryptionKeyPacket(this.primaryKey, primaryUser.selfCertificate)) { return this.primaryKey; } @@ -351,7 +351,7 @@ Key.prototype.getEncryptionKeyPacket = function() { /** * Decrypts all secret key and subkey packets - * @param {String} passphrase + * @param {String} passphrase * @return {Boolean} true if all key and subkey packets decrypted successfully */ Key.prototype.decrypt = function(passphrase) { @@ -370,14 +370,14 @@ Key.prototype.decrypt = function(passphrase) { /** * Decrypts specific key packets by key ID * @param {Array} keyIds - * @param {String} passphrase + * @param {String} passphrase * @return {Boolean} true if all key packets decrypted successfully */ Key.prototype.decryptKeyPacket = function(keyIds, passphrase) { if (this.isPrivate()) { var keys = this.getAllKeyPackets(); for (var i = 0; i < keys.length; i++) { - var keyId = keys[i].getKeyId(); + var keyId = keys[i].getKeyId(); for (var j = 0; j < keyIds.length; j++) { if (keyId.equals(keyIds[j])) { var success = keys[i].decrypt(passphrase); @@ -398,8 +398,8 @@ Key.prototype.decryptKeyPacket = function(keyIds, passphrase) { */ Key.prototype.verifyPrimaryKey = function() { // check revocation signature - if (this.revocationSignature && !this.revocationSignature.isExpired() && - (this.revocationSignature.verified || + if (this.revocationSignature && !this.revocationSignature.isExpired() && + (this.revocationSignature.verified || this.revocationSignature.verify(this.primaryKey, {key: this.primaryKey}))) { return enums.keyStatus.revoked; } @@ -641,8 +641,8 @@ User.prototype.isRevoked = function(certificate, primaryKey) { var that = this; return this.revocationCertifications.some(function(revCert) { return revCert.issuerKeyId.equals(certificate.issuerKeyId) && - !revCert.isExpired() && - (revCert.verified || + !revCert.isExpired() && + (revCert.verified || revCert.verify(primaryKey, {userid: that.userId || that.userAttribute, key: primaryKey})); }); } else { @@ -695,7 +695,7 @@ User.prototype.isValidSelfCertificate = function(primaryKey, selfCertificate) { * Verify User. Checks for existence of self signatures, revocation signatures * and validity of self signature * @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet - * @return {module:enums.keyStatus} status of user + * @return {module:enums.keyStatus} status of user */ User.prototype.verify = function(primaryKey) { if (!this.selfCertifications) { @@ -707,7 +707,7 @@ User.prototype.verify = function(primaryKey) { status = enums.keyStatus.revoked; continue; } - if (!(this.selfCertifications[i].verified || + if (!(this.selfCertifications[i].verified || this.selfCertifications[i].verify(primaryKey, {userid: this.userId || this.userAttribute, key: primaryKey}))) { status = enums.keyStatus.invalid; continue; @@ -792,8 +792,8 @@ SubKey.prototype.isValidSigningKey = function(primaryKey) { */ SubKey.prototype.verify = function(primaryKey) { // check subkey revocation signature - if (this.revocationSignature && !this.revocationSignature.isExpired() && - (this.revocationSignature.verified || + if (this.revocationSignature && !this.revocationSignature.isExpired() && + (this.revocationSignature.verified || this.revocationSignature.verify(primaryKey, {key:primaryKey, bind: this.subKey}))) { return enums.keyStatus.revoked; } @@ -888,12 +888,12 @@ function readArmored(armoredText) { result.keys.push(newKey); } catch (e) { result.err = result.err || []; - result.err.push(e); + result.err.push(e); } } } catch (e) { result.err = result.err || []; - result.err.push(e); + result.err.push(e); } return result; } @@ -910,7 +910,9 @@ function readArmored(armoredText) { * @return {module:key~Key} * @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; // RSA Encrypt-Only and RSA Sign-Only are deprecated and SHOULD NOT be generated if (options.keyType !== enums.publicKey.rsa_encrypt_sign) { @@ -921,74 +923,90 @@ function generate(options) { 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.generate(options.numBits); - if (options.passphrase) { - secretKeyPacket.encrypt(options.passphrase); + secretKeyPacket.generate(options.numBits, onSecretKeyGenerated); + + 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(); - userIdPacket.read(options.userId); + function onSecretSubkeyGenerated(err) { + if (err) { + callback(err); + return; + } - var dataToSign = {}; - dataToSign.userid = userIdPacket; - dataToSign.key = secretKeyPacket; - var 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 + if (options.passphrase) { + secretSubkeyPacket.encrypt(options.passphrase); + } + + dataToSign = {}; + dataToSign.key = secretKeyPacket; + dataToSign.bind = secretSubkeyPacket; + 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(); + } + + 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); } /** diff --git a/src/openpgp.js b/src/openpgp.js index 8f96f96d..c2ecb783 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -224,24 +224,28 @@ function verifyClearSignedMessage(publicKeys, msg, callback) { * @param {String} options.userId assumes already in form of "User Name " * @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 {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} * @static */ 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); return; } - return execute(function() { + key.generate(options, function(err, newKey) { var result = {}; - var newKey = key.generate(options); result.key = newKey; result.privateKeyArmored = newKey.armor(); result.publicKeyArmored = newKey.toPublic().armor(); - return result; - }, callback); + callback(null, result); + }); } // @@ -257,12 +261,20 @@ function useWorker(callback) { } 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; } +/** + * 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 */ diff --git a/src/packet/secret_key.js b/src/packet/secret_key.js index e2b1c0d6..21addf8f 100644 --- a/src/packet/secret_key.js +++ b/src/packet/secret_key.js @@ -1,6 +1,6 @@ // GPG4Browsers - An OpenPGP implementation in javascript // Copyright (C) 2011 Recurity Labs GmbH -// +// // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either @@ -10,7 +10,7 @@ // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. -// +// // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -270,9 +270,19 @@ SecretKey.prototype.decrypt = function (passphrase) { return true; }; -SecretKey.prototype.generate = function (bits) { - this.mpi = crypto.generateMpi(this.algorithm, bits); - this.isDecrypted = true; +SecretKey.prototype.generate = function (bits, callback) { + var self = this; + + crypto.generateMpi(self.algorithm, bits, function(err, mpi) { + if (err) { + callback(err); + return; + } + + self.mpi = mpi; + self.isDecrypted = true; + callback(); + }); }; /** diff --git a/src/worker/worker.js b/src/worker/worker.js index 336712d7..680eddf7 100644 --- a/src/worker/worker.js +++ b/src/worker/worker.js @@ -1,6 +1,6 @@ // GPG4Browsers - An OpenPGP implementation in javascript // Copyright (C) 2011 Recurity Labs GmbH -// +// // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either @@ -10,7 +10,7 @@ // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. -// +// // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -25,7 +25,7 @@ var MAX_SIZE_RANDOM_BUFFER = 60000; window.openpgp.crypto.random.randomBuffer.init(MAX_SIZE_RANDOM_BUFFER); onmessage = function (event) { - var data = null, + var data = null, err = null, msg = event.data, correct = false; @@ -101,7 +101,7 @@ onmessage = function (event) { } msg.publicKeys = msg.publicKeys.map(packetlistCloneToKey); var packetlist = window.openpgp.packet.List.fromStructuredClone(msg.message.packets); - msg.message = new window.openpgp.cleartext.CleartextMessage(msg.message.text, packetlist); + msg.message = new window.openpgp.cleartext.CleartextMessage(msg.message.text, packetlist); data = window.openpgp.verifyClearSignedMessage(msg.publicKeys, msg.message); } catch (e) { err = e.message; @@ -110,12 +110,20 @@ onmessage = function (event) { break; case 'generate-key-pair': try { - data = window.openpgp.generateKeyPair(msg.options); - data.key = data.key.toPacketlist(); + window.openpgp.generateKeyPair(msg.options, function(error, data) { + 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) { err = e.message; + response({event: 'method-return', data: data, err: err}); } - response({event: 'method-return', data: data, err: err}); break; case 'decrypt-key': try { diff --git a/test/general/basic.js b/test/general/basic.js index c954b42b..ffb26499 100644 --- a/test/general/basic.js +++ b/test/general/basic.js @@ -8,57 +8,61 @@ var chai = require('chai'), describe('Basic', function() { describe("Key generation/encryption/decryption", function() { - var testHelper = function(passphrase, userid, message) { - var key = openpgp.generateKeyPair({numBits: 512, userId: userid, passphrase: passphrase}); - expect(key).to.exist; - expect(key.key).to.exist; - expect(key.privateKeyArmored).to.exist; - expect(key.publicKeyArmored).to.exist; + var testHelper = function(passphrase, userid, message, done) { + 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; + 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 publicKeys = openpgp.key.readArmored(key.publicKeyArmored); + var info = '\npassphrase: ' + passphrase + '\n' + 'userid: ' + userid + '\n' + 'message: ' + message; - expect(privKeys).to.exist; - expect(privKeys.err).to.not.exist; - expect(privKeys.keys).to.have.length(1); + var privKeys = openpgp.key.readArmored(key.privateKeyArmored); + var publicKeys = openpgp.key.readArmored(key.publicKeyArmored); - var privKey = privKeys.keys[0]; - var pubKey = publicKeys.keys[0]; + expect(privKeys).to.exist; + expect(privKeys.err).to.not.exist; + expect(privKeys.keys).to.have.length(1); - expect(privKey).to.exist; - expect(pubKey).to.exist; + var privKey = privKeys.keys[0]; + 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(decrypted).to.exist; - expect(decrypted.signatures[0].valid).to.be.true; - expect(decrypted.text).to.equal(message); + expect(keyids).to.exist; + + var decrypted = openpgp.decryptAndVerifyMessage(privKey, [pubKey], msg); + expect(decrypted).to.exist; + expect(decrypted.signatures[0].valid).to.be.true; + expect(decrypted.text).to.equal(message); + + done(); + }); }; it('ASCII Text', function (done) { - testHelper('password', 'Test McTestington ', 'hello world'); - done(); + testHelper('password', 'Test McTestington ', 'hello world', done); }); it('Unicode Text', function (done) { - testHelper('●●●●', '♔♔♔♔ ', 'łäóć'); - done(); + testHelper('●●●●', '♔♔♔♔ ', 'łäóć', done); }); it('should fail to verify signature for wrong public key', function (done) { @@ -66,29 +70,35 @@ describe('Basic', function() { var passphrase = 'password'; 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 publicKeys = openpgp.key.readArmored(key.publicKeyArmored); + var privKeys = openpgp.key.readArmored(key.privateKeyArmored); + var publicKeys = openpgp.key.readArmored(key.publicKeyArmored); - var privKey = privKeys.keys[0]; - var pubKey = publicKeys.keys[0]; + var privKey = privKeys.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); - expect(msg).to.exist; + var msg = openpgp.message.readArmored(encrypted); + expect(msg).to.exist; - var anotherKey = openpgp.generateKeyPair({numBits: 512, userId: userid, passphrase: passphrase}); - var anotherPubKey = openpgp.key.readArmored(anotherKey.publicKeyArmored).keys[0]; + openpgp.generateKeyPair(opt, function(err, anotherKey) { + expect(err).to.not.exist; - var decrypted = openpgp.decryptAndVerifyMessage(privKey, [anotherPubKey], msg); - expect(decrypted).to.exist; - expect(decrypted.signatures[0].valid).to.be.null; - expect(decrypted.text).to.equal(message); - done(); + var anotherPubKey = openpgp.key.readArmored(anotherKey.publicKeyArmored).keys[0]; + + var decrypted = openpgp.decryptAndVerifyMessage(privKey, [anotherPubKey], msg); + expect(decrypted).to.exist; + expect(decrypted.signatures[0].valid).to.be.null; + expect(decrypted.text).to.equal(message); + done(); + }); + }); }); it('Performance test', function (done) { @@ -103,46 +113,49 @@ describe('Basic', function() { var userid = 'Test McTestington '; 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 publicKeys = openpgp.key.readArmored(key.publicKeyArmored); + var privKeys = openpgp.key.readArmored(key.privateKeyArmored); + var publicKeys = openpgp.key.readArmored(key.publicKeyArmored); - var privKey = privKeys.keys[0]; - var pubKey = publicKeys.keys[0]; + var privKey = privKeys.keys[0]; + var pubKey = publicKeys.keys[0]; - var success = privKey.decrypt(passphrase); + var success = privKey.decrypt(passphrase); - if (console.profile) { - console.profile("encrypt/sign/verify/decrypt"); - } + if (console.profile) { + console.profile("encrypt/sign/verify/decrypt"); + } - // sign and encrypt - var msg, encrypted; - msg = openpgp.message.fromBinary(message); - msg = msg.sign([privKey]); - msg = msg.encrypt([pubKey]); - encrypted = openpgp.armor.encode(openpgp.enums.armor.message, msg.packets.write()); + // sign and encrypt + var msg, encrypted; + msg = openpgp.message.fromBinary(message); + msg = msg.sign([privKey]); + msg = msg.encrypt([pubKey]); + encrypted = openpgp.armor.encode(openpgp.enums.armor.message, msg.packets.write()); - if (console.profileEnd) { - console.profileEnd(); - } + if (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.signatures[0].valid).to.be.true; - 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(); + done(); + }); }); }); diff --git a/test/general/key.js b/test/general/key.js index 6221ee35..f71b638d 100644 --- a/test/general/key.js +++ b/test/general/key.js @@ -137,7 +137,7 @@ describe('Key', function() { '=eoGb', '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); - var pub_sig_test = + var pub_sig_test = ['-----BEGIN PGP PUBLIC KEY BLOCK-----', 'Version: GnuPG v2.0.19 (GNU/Linux)', '', @@ -618,7 +618,7 @@ var pgp_desktop_priv = 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) { // key flags var keyFlags = openpgp.enums.keyFlags; @@ -633,10 +633,14 @@ var pgp_desktop_priv = var compr = openpgp.enums.compression; 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 - } - var key = openpgp.generateKeyPair({numBits: 512, userId: 'test', passphrase: 'hello'}); - testPref(key.key); - testPref(openpgp.key.readArmored(key.publicKeyArmored).keys[0]); + }; + var opt = {numBits: 512, userId: 'test', passphrase: 'hello'}; + openpgp.generateKeyPair(opt, function(err, key) { + expect(err).to.not.exist; + testPref(key.key); + testPref(openpgp.key.readArmored(key.publicKeyArmored).keys[0]); + done(); + }); }); 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); }); - it('Generated key is not unlocked by default', function() { - var key = openpgp.generateKeyPair({numBits: 512, userId: 'test', passphrase: '123'}); - 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.'); + it('Generated key is not unlocked by default', function(done) { + var opt = {numBits: 512, userId: 'test', passphrase: '123'}; + openpgp.generateKeyPair(opt, function(err, key) { + expect(err).to.not.exist; + 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(); + }); }); }); diff --git a/test/general/packet.js b/test/general/packet.js index ecac10ff..4609370b 100644 --- a/test/general/packet.js +++ b/test/general/packet.js @@ -6,445 +6,452 @@ var chai = require('chai'), expect = chai.expect; describe("Packet", function() { - var armored_key = - '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' + - 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + - '\n' + - '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\n' + - 'YRlci72GHhlyos8YHA==\n' + - '=KXkj\n' + - '-----END PGP PRIVATE KEY BLOCK-----'; + var armored_key = + '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' + + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + + '\n' + + 'lQH+BFF79J8BBADDhRUOMUSGdYM1Kq9J/vVS3qLfaZHweycAKm9SnpLGLJE+Qbki\n' + + 'JRXLAhxZ+HgVThR9VXs8wbPR2UXnDhMJGe+VcMA0jiwIOEAF0y9M3ZQsPFWguej2\n' + + '1ZycgOwxYHehbKdPqRK+nFgFbhvg6f6x2Gt+a0ZbvivGL1BqSSGsL+dchQARAQAB\n' + + '/gMDAijatUNeUFZSyfg16x343/1Jo6u07LVTdH6Bcbx4yBQjEHvlgb6m1eqEIbZ1\n' + + 'holVzt0fSKTzmlxltDaOwFLf7i42lqNoWyfaqFrOblJ5Ays7Q+6xiJTBROG9po+j\n' + + 'Z2AE+hkBIwKghB645OikchR4sn9Ej3ipea5v9+a7YimHlVmIiqgLDygQvXkzXVaf\n' + + 'Zi1P2wB7eU6If2xeeX5GSR8rWo+I7ujns0W8S9PxBHlH3n1oXUmFWsWLZCY/qpkD\n' + + 'I/FroBhXxBVRpQhQmdsWPUdcgmQTEj8jnP++lwSQexfgk2QboAW7ODUA8Cl9oy87\n' + + 'Uor5schwwdD3oRoLGcJZfR6Dyu9dCYdQSDWj+IQs95hJQfHNcfj7XFtTyOi7Kxx0\n' + + 'Jxio9De84QnxNAoNYuLtwkaRgkUVKVph2nYWJfAJunuMMosM2WdcidHJ5d6RIdxB\n' + + 'U6o3T+d8BPXuRQEZH9+FkDkb4ihakKO3+Zcon85e1ZUUtB1QYXRyaWNrIDxwYXRy\n' + + 'aWNrQGV4YW1wbGUuY29tPoi5BBMBAgAjBQJRe/SfAhsDBwsJCAcDAgEGFQgCCQoL\n' + + 'BBYCAwECHgECF4AACgkQObliSdM/GEJbjgP/ffei4lU6fXp8Qu0ubNHh4A6swkTO\n' + + 'b3suuBELE4A2/pK5YnW5yByFFSi4kq8bJp5O6p9ydXpOA38t3aQ8wrbo0yDvGekr\n' + + '1S1HWOLgCaY7rEDQubuCOHd2R81/VQOJyG3zgX4KFIgkVyV9BZXUpz4PXuhMORmv\n' + + '81uzej9r7BYkJ6GdAf4EUXv0nwEEAKbO02jtGEHet2fQfkAYyO+789sTxyfrUy5y\n' + + 'SAf5n3GgkuiHz8dFevhgqYyMK0OYEOCZqdd1lRBjL6Us7PxTljHc2jtGhoAgE4aZ\n' + + 'LKarI3j+5Oofcaq0+S0bhqiQ5hl6C4SkdYOEeJ0Hlq2008n0pJIlU4E5yIu0oNvb\n' + + '4+4owTpRABEBAAH+AwMCKNq1Q15QVlLJyeuGBEA+7nXS3aSy6mE4lR5f3Ml5NRqt\n' + + 'jm6Q+UUI69DzhLGX4jHRxna6NMP74S3CghOz9eChMndkfWLC/c11h1npzLci+AwJ\n' + + '45xMbw/OW5PLlaxdtkg/SnsHpFGCAuTUWY87kuWoG0HSVMn9Clm+67rdicOW6L5a\n' + + 'ChfyWcVZ+Hvwjx8YM0/j11If7oUkCZEstSUeJYOI10JQLhNLpDdkB89vXhAMaCuU\n' + + 'Ijhdq0vvJi6JruKQGPK+jajJ4MMannpQtKAvt8aifqpdovYy8w4yh2pGkadFvrsZ\n' + + 'mxpjqmmawab6zlOW5WrLxQVL1cQRdrIQ7jYtuLApGWkPfytSCBZ20pSyWnmkxd4X\n' + + 'OIms6BjqrP9LxBEXsPBwdUA5Iranr+UBIPDxQrTp5k0DJhXBCpJ1k3ZT+2dxiRS2\n' + + 'sk83w2VUBnXdYWZx0YlMqr3bDT6J5fO+8V8pbgY5BkHRCFMacFx45km/fvmInwQY\n' + + 'AQIACQUCUXv0nwIbDAAKCRA5uWJJ0z8YQqb3A/97njLl33OQYXVp9OTk/VgE6O+w\n' + + 'oSYa+6xMOzsk7tluLIRQtnIprga/e8vEZXGTomV2a77HBksg+YjlTh/l8oMuaoxG\n' + + 'QNkMpoRJKPip29RTW4gLdnoJVekZ/awkBN2S3NMArOZGca8U+M1IuV7OyVchSVSl\n' + + 'YRlci72GHhlyos8YHA==\n' + + '=KXkj\n' + + '-----END PGP PRIVATE KEY BLOCK-----'; it('Symmetrically encrypted packet', function(done) { - var message = new openpgp.packet.List(); + var message = new openpgp.packet.List(); - var literal = new openpgp.packet.Literal(); - literal.setText('Hello world'); - - var enc = new openpgp.packet.SymmetricallyEncrypted(); - message.push(enc); - enc.packets.push(literal); + var literal = new openpgp.packet.Literal(); + literal.setText('Hello world'); - var key = '12345678901234567890123456789012', - algo = 'aes256'; + var enc = new openpgp.packet.SymmetricallyEncrypted(); + message.push(enc); + enc.packets.push(literal); - enc.encrypt(algo, key); + var key = '12345678901234567890123456789012', + algo = 'aes256'; - var msg2 = new openpgp.packet.List(); - msg2.read(message.write()); + enc.encrypt(algo, key); - msg2[0].decrypt(algo, key); + var msg2 = new openpgp.packet.List(); + msg2.read(message.write()); + + msg2[0].decrypt(algo, key); expect(msg2[0].packets[0].data).to.equal(literal.data); done(); }); it('Sym. encrypted integrity protected packet', function(done) { - var key = '12345678901234567890123456789012', - algo = 'aes256'; + var key = '12345678901234567890123456789012', + algo = 'aes256'; - var literal = new openpgp.packet.Literal(), - enc = new openpgp.packet.SymEncryptedIntegrityProtected(), - msg = new openpgp.packet.List(); + var literal = new openpgp.packet.Literal(), + enc = new openpgp.packet.SymEncryptedIntegrityProtected(), + msg = new openpgp.packet.List(); - msg.push(enc); - literal.setText('Hello world!'); - enc.packets.push(literal); - enc.encrypt(algo, key); - - var msg2 = new openpgp.packet.List(); - msg2.read(msg.write()); + msg.push(enc); + literal.setText('Hello world!'); + enc.packets.push(literal); + enc.encrypt(algo, key); - msg2[0].decrypt(algo, key); + var msg2 = new openpgp.packet.List(); + msg2.read(msg.write()); + + msg2[0].decrypt(algo, key); expect(msg2[0].packets[0].data).to.equal(literal.data); done(); }); it('Sym encrypted session key with a compressed packet', function(done) { - var msg = - '-----BEGIN PGP MESSAGE-----\n' + - 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + - '\n' + - 'jA0ECQMCpo7I8WqsebTJ0koBmm6/oqdHXJU9aPe+Po+nk/k4/PZrLmlXwz2lhqBg\n' + - 'GAlY9rxVStLBrg0Hn+5gkhyHI9B85rM1BEYXQ8pP5CSFuTwbJ3O2s67dzQ==\n' + - '=VZ0/\n' + - '-----END PGP MESSAGE-----'; + var msg = + '-----BEGIN PGP MESSAGE-----\n' + + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + + '\n' + + 'jA0ECQMCpo7I8WqsebTJ0koBmm6/oqdHXJU9aPe+Po+nk/k4/PZrLmlXwz2lhqBg\n' + + 'GAlY9rxVStLBrg0Hn+5gkhyHI9B85rM1BEYXQ8pP5CSFuTwbJ3O2s67dzQ==\n' + + '=VZ0/\n' + + '-----END PGP MESSAGE-----'; - var msgbytes = openpgp.armor.decode(msg).data; + var msgbytes = openpgp.armor.decode(msg).data; - var parsed = new openpgp.packet.List(); - parsed.read(msgbytes); + var parsed = new openpgp.packet.List(); + parsed.read(msgbytes); - parsed[0].decrypt('test'); + parsed[0].decrypt('test'); - var key = parsed[0].sessionKey; - parsed[1].decrypt(parsed[0].sessionKeyAlgorithm, key); - var compressed = parsed[1].packets[0]; + var key = parsed[0].sessionKey; + parsed[1].decrypt(parsed[0].sessionKeyAlgorithm, key); + 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'); done(); }); it('Public key encrypted symmetric key packet', function(done) { - var rsa = new openpgp.crypto.publicKey.rsa(), - mpi = rsa.generate(512, "10001") + var rsa = new openpgp.crypto.publicKey.rsa(); - 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 = new openpgp.MPI(); - mpi.fromBigInteger(k); - return mpi; - }); + var mpi = [mpiGen.n, mpiGen.ee, mpiGen.d, mpiGen.p, mpiGen.q, mpiGen.u]; - var enc = new openpgp.packet.PublicKeyEncryptedSessionKey(), - msg = new openpgp.packet.List(), - msg2 = new openpgp.packet.List(); + mpi = mpi.map(function(k) { + var mpi = new openpgp.MPI(); + mpi.fromBigInteger(k); + return mpi; + }); - enc.sessionKey = '12345678901234567890123456789012'; - enc.publicKeyAlgorithm = 'rsa_encrypt'; - enc.sessionKeyAlgorithm = 'aes256'; - enc.publicKeyId.bytes = '12345678'; - enc.encrypt({ mpi: mpi }); + var enc = new openpgp.packet.PublicKeyEncryptedSessionKey(), + msg = new openpgp.packet.List(), + msg2 = new openpgp.packet.List(); - 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); - expect(msg2[0].sessionKeyAlgorithm).to.equal(enc.sessionKeyAlgorithm); - done(); + msg2[0].decrypt({ mpi: mpi }); + + 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) { - var armored_key = - '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' + - 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + - '\n' + - 'lQHYBFF33iMBBAC9YfOYahJlWrVj2J1TjQiZLunWljI4G9e6ARTyD99nfOkV3swh\n' + - '0WaOse4Utj7BfTqdYcoezhCaQpuExUupKWZqmduBcwSmEBfNu1XyKcxlDQuuk0Vk\n' + - 'viGC3kFRce/cJaKVFSRU8V5zPgt6KQNv/wNz7ydEisaSoNbk51vQt5oGfwARAQAB\n' + - 'AAP5AVL8xWMuKgLj9g7/wftMH+jO7vhAxje2W3Y+8r8TnOSn0536lQvzl/eQyeLC\n' + - 'VK2k3+7+trgO7I4KuXCXZqgAbEi3niDYXDaCJ+8gdR9qvPM2gi9NM71TGXZvGE0w\n' + - 'X8gIZfqLTQWKm9TIS/3tdrth4nwhiye0ASychOboIiN6VIECAMbCQ4/noxGV6yTK\n' + - 'VezsGSz+iCMxz2lV270/Ac2C5WPk+OlxXloxUXeEkGIr6Xkmhhpceed2KL41UC8Y\n' + - 'w5ttGIECAPPsahniKGyqp9CHy6W0B83yhhcIbmLlaVG2ftKyUEDxIggzOlXuVrue\n' + - 'z9XRd6wFqwDd1QMFW0uUyHPDCIFPnv8CAJaDFSZutuWdWMt15NZXjfgRgfJuDrtv\n' + - 'E7yFY/p0el8lCihOT8WoHbTn1PbCYMzNBc0IhHaZKAtA2pjkE+wzz9ClP7QbR2Vv\n' + - 'cmdlIDxnZW9yZ2VAZXhhbXBsZS5jb20+iLkEEwECACMFAlF33iMCGwMHCwkIBwMC\n' + - 'AQYVCAIJCgsEFgIDAQIeAQIXgAAKCRBcqs36fwJCXRbvA/9LPiK6WFKcFoNBnLEJ\n' + - 'mS/CNkL8yTpkslpCP6+TwJMc8uXqwYl9/PW2+CwmzZjs6JsvTzMcR/ZbfZJuSW6Y\n' + - 'EsLNejsSpgcY9aiewGtE+53e5oKYnlmVMTWOPywciIgMvXlzdGhxcwqJ8u0hT+ug\n' + - '9CjcAfuX9yw85LwXtdGwNh7J8Q==\n' + - '=lKiS\n' + - '-----END PGP PRIVATE KEY BLOCK-----'; + var armored_key = + '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' + + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + + '\n' + + 'lQHYBFF33iMBBAC9YfOYahJlWrVj2J1TjQiZLunWljI4G9e6ARTyD99nfOkV3swh\n' + + '0WaOse4Utj7BfTqdYcoezhCaQpuExUupKWZqmduBcwSmEBfNu1XyKcxlDQuuk0Vk\n' + + 'viGC3kFRce/cJaKVFSRU8V5zPgt6KQNv/wNz7ydEisaSoNbk51vQt5oGfwARAQAB\n' + + 'AAP5AVL8xWMuKgLj9g7/wftMH+jO7vhAxje2W3Y+8r8TnOSn0536lQvzl/eQyeLC\n' + + 'VK2k3+7+trgO7I4KuXCXZqgAbEi3niDYXDaCJ+8gdR9qvPM2gi9NM71TGXZvGE0w\n' + + 'X8gIZfqLTQWKm9TIS/3tdrth4nwhiye0ASychOboIiN6VIECAMbCQ4/noxGV6yTK\n' + + 'VezsGSz+iCMxz2lV270/Ac2C5WPk+OlxXloxUXeEkGIr6Xkmhhpceed2KL41UC8Y\n' + + 'w5ttGIECAPPsahniKGyqp9CHy6W0B83yhhcIbmLlaVG2ftKyUEDxIggzOlXuVrue\n' + + 'z9XRd6wFqwDd1QMFW0uUyHPDCIFPnv8CAJaDFSZutuWdWMt15NZXjfgRgfJuDrtv\n' + + 'E7yFY/p0el8lCihOT8WoHbTn1PbCYMzNBc0IhHaZKAtA2pjkE+wzz9ClP7QbR2Vv\n' + + 'cmdlIDxnZW9yZ2VAZXhhbXBsZS5jb20+iLkEEwECACMFAlF33iMCGwMHCwkIBwMC\n' + + 'AQYVCAIJCgsEFgIDAQIeAQIXgAAKCRBcqs36fwJCXRbvA/9LPiK6WFKcFoNBnLEJ\n' + + 'mS/CNkL8yTpkslpCP6+TwJMc8uXqwYl9/PW2+CwmzZjs6JsvTzMcR/ZbfZJuSW6Y\n' + + 'EsLNejsSpgcY9aiewGtE+53e5oKYnlmVMTWOPywciIgMvXlzdGhxcwqJ8u0hT+ug\n' + + '9CjcAfuX9yw85LwXtdGwNh7J8Q==\n' + + '=lKiS\n' + + '-----END PGP PRIVATE KEY BLOCK-----'; - var key = new openpgp.packet.List(); - key.read(openpgp.armor.decode(armored_key).data); - key = key[0]; + var key = new openpgp.packet.List(); + key.read(openpgp.armor.decode(armored_key).data); + key = key[0]; - var enc = new openpgp.packet.PublicKeyEncryptedSessionKey(), - secret = '12345678901234567890123456789012'; + var enc = new openpgp.packet.PublicKeyEncryptedSessionKey(), + secret = '12345678901234567890123456789012'; - enc.sessionKey = secret; - enc.publicKeyAlgorithm = 'rsa_encrypt'; - enc.sessionKeyAlgorithm = 'aes256'; - enc.publicKeyId.bytes = '12345678'; + enc.sessionKey = secret; + enc.publicKeyAlgorithm = 'rsa_encrypt'; + enc.sessionKeyAlgorithm = 'aes256'; + 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(); }); it('Public key encrypted packet (reading, GPG)', function(done) { - var armored_key = - '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' + - 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + - '\n' + - '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\n' + - '=FSwA\n' + - '-----END PGP PRIVATE KEY BLOCK-----'; + var armored_key = + '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' + + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + + '\n' + + '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\n' + + '=FSwA\n' + + '-----END PGP PRIVATE KEY BLOCK-----'; - var armored_msg = - '-----BEGIN PGP MESSAGE-----\n' + - 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + - '\n' + - 'hIwDFYET+7bfx/ABA/95Uc9942Tg8oqpO0vEu2eSKwPALM3a0DrVdAiFOIK/dJmZ\n' + - 'YrtPRw3EEwHZjl6CO9RD+95iE27tPbsICw1K43gofSV/wWsPO6vvs3eftQYHSxxa\n' + - 'IQbTPImiRaJ73Mf7iM3CNtQM4iUBsx1HnUGl+rtD0nz3fLm6i3CjwiNQWW42I9JH\n' + - 'AWv8EvvpxZ8X2ClFfSW3UVBoROHe9CAWHM/40nGutAZK8MIgmUI4xqkLFBbqqTyx\n' + - '/cDSC4Q+sv65UX4urbfc7uJuk1Cpj54=\n' + - '=iSaK\n' + - '-----END PGP MESSAGE-----'; + var armored_msg = + '-----BEGIN PGP MESSAGE-----\n' + + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + + '\n' + + 'hIwDFYET+7bfx/ABA/95Uc9942Tg8oqpO0vEu2eSKwPALM3a0DrVdAiFOIK/dJmZ\n' + + 'YrtPRw3EEwHZjl6CO9RD+95iE27tPbsICw1K43gofSV/wWsPO6vvs3eftQYHSxxa\n' + + 'IQbTPImiRaJ73Mf7iM3CNtQM4iUBsx1HnUGl+rtD0nz3fLm6i3CjwiNQWW42I9JH\n' + + 'AWv8EvvpxZ8X2ClFfSW3UVBoROHe9CAWHM/40nGutAZK8MIgmUI4xqkLFBbqqTyx\n' + + '/cDSC4Q+sv65UX4urbfc7uJuk1Cpj54=\n' + + '=iSaK\n' + + '-----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(); - key.read(openpgp.armor.decode(armored_key).data); - key = key[3]; + var msg = new openpgp.packet.List(); + msg.read(openpgp.armor.decode(armored_msg).data); - var msg = new openpgp.packet.List(); - msg.read(openpgp.armor.decode(armored_msg).data); + msg[0].decrypt(key); + msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey); - msg[0].decrypt(key); - 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!'); done(); }); it('Sym encrypted session key reading/writing', function(done) { - var passphrase = 'hello', - algo = 'aes256'; + var passphrase = 'hello', + algo = 'aes256'; - var literal = new openpgp.packet.Literal(), - key_enc = new openpgp.packet.SymEncryptedSessionKey(), - enc = new openpgp.packet.SymEncryptedIntegrityProtected(), - msg = new openpgp.packet.List(); + var literal = new openpgp.packet.Literal(), + key_enc = new openpgp.packet.SymEncryptedSessionKey(), + enc = new openpgp.packet.SymEncryptedIntegrityProtected(), + msg = new openpgp.packet.List(); - msg.push(key_enc); - msg.push(enc); + msg.push(key_enc); + msg.push(enc); - key_enc.sessionKeyAlgorithm = algo; - key_enc.decrypt(passphrase); + key_enc.sessionKeyAlgorithm = algo; + key_enc.decrypt(passphrase); - var key = key_enc.sessionKey; + var key = key_enc.sessionKey; - literal.setText('Hello world!'); - enc.packets.push(literal); - enc.encrypt(algo, key); + literal.setText('Hello world!'); + enc.packets.push(literal); + enc.encrypt(algo, key); - var msg2 = new openpgp.packet.List(); - msg2.read(msg.write()); + var msg2 = new openpgp.packet.List(); + msg2.read(msg.write()); - msg2[0].decrypt(passphrase); - var key2 = msg2[0].sessionKey; - msg2[1].decrypt(msg2[0].sessionKeyAlgorithm, key2); + msg2[0].decrypt(passphrase); + var key2 = msg2[0].sessionKey; + msg2[1].decrypt(msg2[0].sessionKeyAlgorithm, key2); expect(msg2[1].packets[0].data).to.equal(literal.data); done(); }); it('Secret key encryption/decryption test', function(done) { - var armored_msg = - '-----BEGIN PGP MESSAGE-----\n' + - 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + - '\n' + - 'hIwD95D9aHS5fxEBA/98CwH54XZmwobOmHUcvWcDDQysBEC4uf7wASiGcRbejDaO\n' + - 'aJqcrK/3k8sBQMO7yOhvrCRqqpGDqnmx7IaaKLnZS7nYAZoHEsK9UyG0hDa8Cfbo\n' + - 'CP4xZVcgIvIfAW/in1LeT2td0QcQNbeewBmPea+vQEEvRgIP10tlE7MK8Ay48dJH\n' + - 'AagMgNYg7MBUjpuOCVrjM1pWja8uzbULfYhTq3IJ8H3QhbdT+k9khY9f0aJPEeYi\n' + - 'dVv6DK9uviMGc/DsVCw5K8lQRLlkcHc=\n' + - '=pR+C\n' + - '-----END PGP MESSAGE-----'; + var armored_msg = + '-----BEGIN PGP MESSAGE-----\n' + + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + + '\n' + + 'hIwD95D9aHS5fxEBA/98CwH54XZmwobOmHUcvWcDDQysBEC4uf7wASiGcRbejDaO\n' + + 'aJqcrK/3k8sBQMO7yOhvrCRqqpGDqnmx7IaaKLnZS7nYAZoHEsK9UyG0hDa8Cfbo\n' + + 'CP4xZVcgIvIfAW/in1LeT2td0QcQNbeewBmPea+vQEEvRgIP10tlE7MK8Ay48dJH\n' + + 'AagMgNYg7MBUjpuOCVrjM1pWja8uzbULfYhTq3IJ8H3QhbdT+k9khY9f0aJPEeYi\n' + + 'dVv6DK9uviMGc/DsVCw5K8lQRLlkcHc=\n' + + '=pR+C\n' + + '-----END PGP MESSAGE-----'; - var key = new openpgp.packet.List(); - key.read(openpgp.armor.decode(armored_key).data); - key = key[3]; - key.decrypt('test'); + var key = new openpgp.packet.List(); + key.read(openpgp.armor.decode(armored_key).data); + key = key[3]; + key.decrypt('test'); - var msg = new openpgp.packet.List(); - msg.read(openpgp.armor.decode(armored_msg).data); + var msg = new openpgp.packet.List(); + msg.read(openpgp.armor.decode(armored_msg).data); - msg[0].decrypt(key); - msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey); + msg[0].decrypt(key); + 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!'); done(); }); it('Secret key reading with signature verification.', function(done) { - var key = new openpgp.packet.List(); - key.read(openpgp.armor.decode(armored_key).data); + var key = new openpgp.packet.List(); + key.read(openpgp.armor.decode(armored_key).data); - var verified = key[2].verify(key[0], - { - userid: key[1], - key: key[0] - }); + var verified = key[2].verify(key[0], + { + userid: key[1], + key: key[0] + }); - verified = verified && key[4].verify(key[0], - { - key: key[0], - bind: key[3] - }); + verified = verified && key[4].verify(key[0], + { + key: key[0], + bind: key[3] + }); expect(verified).to.be.true; done(); }); it('Reading a signed, encrypted message.', function(done) { - var armored_msg = - '-----BEGIN PGP MESSAGE-----\n' + - 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + - '\n' + - 'hIwD95D9aHS5fxEBA/4/X4myvH+jB1HYNeZvdK+WsBNDMfLsBGOf205Rxr3vSob/\n' + - 'A09boj8/9lFaipqu+AEdQKEjCB8sZ+OY0WiQPEPpuhG+mVqDqEiPFkdpcqNtS0VV\n' + - 'pwqplHo6QnH2MHfxprZHYuwcEC9ynJCxJ6kSCD8Xs99h+PjxNNw7NhMjkF+N69LA\n' + - 'NwGPtbLx2/r2nR4gO8gV92A2RQCOwPP7ZV+6fXgWIs+mhyCHFP3xUP5DaFCNM8mo\n' + - 'PN97i659ucxF6IbOoK56FEaUbOPTD6xdyhWamxKfMsIb0UJgVUNhGaq+VlvOJxaB\n' + - 'iRcnY5UxsypKgtqfcKIseb21MIo4vcNdogyxBIDlAO472Zfxn0udzr6W2aQ77+NK\n' + - 'FE1O0kCXS+DTFOYYVD7X8rXGSglQsdXJmHd89sdYFQkO7D7bOLdRJuXgdgH2czCs\n' + - 'UBGuHZzsGbTdyKvpVBuS3rnyHHBk6oCnsm1Nl7eLs64VkZUxjEUbq5pb4dlr1pw2\n' + - 'ztpmpAnRcmM=\n' + - '=htrB\n' + - '-----END PGP MESSAGE-----' + var armored_msg = + '-----BEGIN PGP MESSAGE-----\n' + + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + + '\n' + + 'hIwD95D9aHS5fxEBA/4/X4myvH+jB1HYNeZvdK+WsBNDMfLsBGOf205Rxr3vSob/\n' + + 'A09boj8/9lFaipqu+AEdQKEjCB8sZ+OY0WiQPEPpuhG+mVqDqEiPFkdpcqNtS0VV\n' + + 'pwqplHo6QnH2MHfxprZHYuwcEC9ynJCxJ6kSCD8Xs99h+PjxNNw7NhMjkF+N69LA\n' + + 'NwGPtbLx2/r2nR4gO8gV92A2RQCOwPP7ZV+6fXgWIs+mhyCHFP3xUP5DaFCNM8mo\n' + + 'PN97i659ucxF6IbOoK56FEaUbOPTD6xdyhWamxKfMsIb0UJgVUNhGaq+VlvOJxaB\n' + + 'iRcnY5UxsypKgtqfcKIseb21MIo4vcNdogyxBIDlAO472Zfxn0udzr6W2aQ77+NK\n' + + 'FE1O0kCXS+DTFOYYVD7X8rXGSglQsdXJmHd89sdYFQkO7D7bOLdRJuXgdgH2czCs\n' + + 'UBGuHZzsGbTdyKvpVBuS3rnyHHBk6oCnsm1Nl7eLs64VkZUxjEUbq5pb4dlr1pw2\n' + + 'ztpmpAnRcmM=\n' + + '=htrB\n' + + '-----END PGP MESSAGE-----' - var key = new openpgp.packet.List(); - key.read(openpgp.armor.decode(armored_key).data); - key[3].decrypt('test') + var key = new openpgp.packet.List(); + key.read(openpgp.armor.decode(armored_key).data); + key[3].decrypt('test') - var msg = new openpgp.packet.List(); - msg.read(openpgp.armor.decode(armored_msg).data); + var msg = new openpgp.packet.List(); + msg.read(openpgp.armor.decode(armored_msg).data); - msg[0].decrypt(key[3]); - msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey); + msg[0].decrypt(key[3]); + 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; done(); }); it('Writing and encryption of a secret key packet.', function(done) { - var key = new openpgp.packet.List(); - key.push(new openpgp.packet.SecretKey); + var key = new openpgp.packet.List(); + key.push(new openpgp.packet.SecretKey); - var rsa = new openpgp.crypto.publicKey.rsa(), - mpi = rsa.generate(512, "10001") + var rsa = new openpgp.crypto.publicKey.rsa(); + 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) { - var mpi = new openpgp.MPI(); - mpi.fromBigInteger(k); - return mpi; - }); + mpi = mpi.map(function(k) { + var mpi = new openpgp.MPI(); + mpi.fromBigInteger(k); + 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(); - key2.read(raw); - key2[0].decrypt('hello'); - - expect(key[0].mpi.toString()).to.equal(key2[0].mpi.toString()); - done(); + var key2 = new openpgp.packet.List(); + key2.read(raw); + key2[0].decrypt('hello'); + + expect(key[0].mpi.toString()).to.equal(key2[0].mpi.toString()); + 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, - mpi = rsa.generate(512, "10001") + var rsa = new openpgp.crypto.publicKey.rsa; - 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 = new openpgp.MPI(); - mpi.fromBigInteger(k); - return mpi; - }); + var mpi = [mpiGen.n, mpiGen.ee, mpiGen.d, mpiGen.p, mpiGen.q, mpiGen.u]; - key.mpi = mpi; + mpi = mpi.map(function(k) { + var mpi = new openpgp.MPI(); + mpi.fromBigInteger(k); + return mpi; + }); - var signed = new openpgp.packet.List(), - literal = new openpgp.packet.Literal(), - signature = new openpgp.packet.Signature(); + key.mpi = mpi; - literal.setText('Hello world'); + var signed = new openpgp.packet.List(), + literal = new openpgp.packet.Literal(), + signature = new openpgp.packet.Signature(); - signature.hashAlgorithm = 'sha256'; - signature.publicKeyAlgorithm = 'rsa_sign'; - signature.signatureType = 'binary'; + literal.setText('Hello world'); - signature.sign(key, literal); + signature.hashAlgorithm = 'sha256'; + signature.publicKeyAlgorithm = 'rsa_sign'; + signature.signatureType = 'binary'; - signed.push(literal); - signed.push(signature); + signature.sign(key, literal); - var raw = signed.write(); + signed.push(literal); + signed.push(signature); - var signed2 = new openpgp.packet.List(); - signed2.read(raw); + var raw = signed.write(); - var verified = signed2[1].verify(key, signed2[0]); + var signed2 = new openpgp.packet.List(); + signed2.read(raw); - expect(verified).to.be.true; - done(); + var verified = signed2[1].verify(key, signed2[0]); + + expect(verified).to.be.true; + done(); + }); }); }); diff --git a/test/general/signature.js b/test/general/signature.js index e4b7ebeb..7e05bcdd 100644 --- a/test/general/signature.js +++ b/test/general/signature.js @@ -312,7 +312,7 @@ describe("Signature", function() { }); it('Verify V4 signature. Hash: SHA1. PK: RSA. Signature Type: 0x00 (binary document)', function(done) { - var signedArmor = + var signedArmor = [ '-----BEGIN PGP MESSAGE-----', 'Version: GnuPG v2.0.19 (GNU/Linux)', '', @@ -335,7 +335,7 @@ describe("Signature", function() { }); it('Verify V3 signature. Hash: MD5. PK: RSA. Signature Type: 0x01 (text document)', function(done) { - var signedArmor = + var signedArmor = [ '-----BEGIN PGP MESSAGE-----', 'Version: GnuPG v2.0.19 (GNU/Linux)', '', @@ -358,7 +358,7 @@ describe("Signature", function() { }); it('Verify signature of signed and encrypted message from GPG2 with openpgp.decryptAndVerifyMessage', function(done) { - var msg_armor = + var msg_armor = [ '-----BEGIN PGP MESSAGE-----', 'Version: GnuPG v2.0.19 (GNU/Linux)', '', @@ -393,7 +393,7 @@ describe("Signature", function() { }); it('Verify signature of signed and encrypted message from PGP 10.3.0 with openpgp.decryptAndVerifyMessage', function(done) { - var msg_armor = + var msg_armor = [ '-----BEGIN PGP MESSAGE-----', 'Version: Encryption Desktop 10.3.0 (Build 9307)', 'Charset: utf-8', @@ -429,7 +429,7 @@ describe("Signature", function() { }); it('Verify signed message with two one pass signatures', function(done) { - var msg_armor = + var msg_armor = [ '-----BEGIN PGP MESSAGE-----', 'Version: GnuPG v2.0.19 (GNU/Linux)', '', @@ -470,7 +470,7 @@ describe("Signature", function() { }); it('Verify cleartext signed message with two signatures with openpgp.verifyClearSignedMessage', function(done) { - var msg_armor = + var msg_armor = [ '-----BEGIN PGP SIGNED MESSAGE-----', 'Hash: SHA256', '', @@ -523,7 +523,7 @@ describe("Signature", function() { var clearSignedArmor = openpgp.signClearMessage([privKey], plaintext); var csMsg = openpgp.cleartext.readArmored(clearSignedArmor); - + var cleartextSig = openpgp.verifyClearSignedMessage([pubKey], csMsg); expect(cleartextSig).to.exist; @@ -636,13 +636,19 @@ describe("Signature", function() { expect(result[0].valid).to.be.true; }); - it('Sign message with key without password', function() { - var key = openpgp.generateKeyPair({numBits: 512, userId: 'ABC', passphrase: null}).key; + it('Sign message with key without password', function(done) { + 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'); - message = message.sign([key]); + var key = gen.key; - expect(message).to.exist; + var message = openpgp.message.fromText('hello world'); + message = message.sign([key]); + + expect(message).to.exist; + done(); + }); }); }); diff --git a/test/worker/api.js b/test/worker/api.js index 43efaea3..cba322f5 100644 --- a/test/worker/api.js +++ b/test/worker/api.js @@ -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 ', 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() {