Merge pull request #259 from openpgpjs/promises
Refactor public api to use ES6 Promises
This commit is contained in:
commit
2362cce642
39
.jshintrc
Normal file
39
.jshintrc
Normal file
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"indent": 2,
|
||||
"strict": true,
|
||||
"globalstrict": true,
|
||||
"node": true,
|
||||
"browser": true,
|
||||
"nonew": true,
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
"immed": true,
|
||||
"newcap": true,
|
||||
"regexp": true,
|
||||
"evil": true,
|
||||
"eqnull": true,
|
||||
"expr": true,
|
||||
"trailing": true,
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
|
||||
"predef": [
|
||||
"console",
|
||||
"Promise",
|
||||
"importScripts",
|
||||
"process",
|
||||
"Event",
|
||||
"self",
|
||||
"describe",
|
||||
"it",
|
||||
"sinon",
|
||||
"mocha",
|
||||
"before",
|
||||
"beforeEach",
|
||||
"after",
|
||||
"afterEach"
|
||||
],
|
||||
|
||||
"globals": {
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ module.exports = function(grunt) {
|
|||
'test/lib/unittests-bundle.js': [ './test/unittests.js' ]
|
||||
},
|
||||
options: {
|
||||
external: [ 'openpgp', 'crypto', 'node-localstorage' ]
|
||||
external: [ 'openpgp', 'crypto', 'node-localstorage']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
28
README.md
28
README.md
|
@ -18,34 +18,46 @@ For use in browser, install via bower:
|
|||
|
||||
bower install --save openpgp
|
||||
|
||||
Or Fetch a minified build under [releases](https://github.com/openpgpjs/openpgpjs/releases).
|
||||
Or Fetch a minified build under [releases](https://github.com/openpgpjs/openpgpjs/releases).
|
||||
|
||||
The library can be loaded via AMD/require.js or accessed globally via `window.openpgp`.
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
OpenPGP.js only supports browsers that implement `window.crypto.getRandomValues`. Also, if the browsers support [native WebCrypto](http://www.w3.org/TR/WebCryptoAPI/) via the `window.crypto.subtle` api, this will be used. Though this can be deactivated by setting `config.useWebCrypto = false`. In this case the library will fall back to Web Worker operations if the `initWorker(workerPath)` is set.
|
||||
|
||||
OpenPGP.js uses ES6 promises which are available in [most modern browsers](http://caniuse.com/#feat=promises). If you need to support browsers that do not support Promises, fear not! There is a [polyfill](https://github.com/jakearchibald/es6-promise), which is included in the build step. So no action required on the developer's part for promises!
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
#### Encryption
|
||||
|
||||
|
||||
var openpgp = require('openpgp');
|
||||
var key = '-----BEGIN PGP PUBLIC KEY BLOCK ... END PGP PUBLIC KEY BLOCK-----';
|
||||
var publicKey = openpgp.key.readArmored(key);
|
||||
var pgpMessage = openpgp.encryptMessage(publicKey.keys, 'Hello, World!');
|
||||
openpgp.encryptMessage(publicKey.keys, 'Hello, World!').then(function(pgpMessage) {
|
||||
// success
|
||||
}).catch(function(error) {
|
||||
// failure
|
||||
});
|
||||
|
||||
#### Decryption
|
||||
|
||||
|
||||
var openpgp = require('openpgp');
|
||||
var key = '-----BEGIN PGP PRIVATE KEY BLOCK ... END PGP PRIVATE KEY BLOCK-----';
|
||||
var privateKey = openpgp.key.readArmored(key).keys[0];
|
||||
privateKey.decrypt('passphrase');
|
||||
var pgpMessage = '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----';
|
||||
pgpMessage = openpgp.message.readArmored(pgpMessage);
|
||||
var plaintext = openpgp.decryptMessage(privateKey, pgpMessage);
|
||||
openpgp.decryptMessage(privateKey, pgpMessage).then(function(plaintext) {
|
||||
// success
|
||||
}).catch(function(error) {
|
||||
// failure
|
||||
});
|
||||
|
||||
|
||||
|
||||
OpenPGP.js currently only fully supports browsers that implement `window.crypto.getRandomValues`. If you can help us support more browsers and runtimes, please chip in!
|
||||
|
||||
### Security recommendations
|
||||
|
||||
It should be noted that js crypto apps deployed via regular web hosting (a.k.a. [**host-based security**](https://www.schneier.com/blog/archives/2012/08/cryptocat.html)) provide users with less security than installable apps with auditable static versions. Installable apps can be deployed as a [Firefox](https://developer.mozilla.org/en-US/Marketplace/Publishing/Packaged_apps) or [Chrome](http://developer.chrome.com/apps/about_apps.html) packaged app. These apps are basically signed zip files and their runtimes typically enforce a strict [Content Security Policy (CSP)](http://www.html5rocks.com/en/tutorials/security/content-security-policy/) to protect users against [XSS](http://en.wikipedia.org/wiki/Cross-site_scripting). This [blogpost](http://tonyarcieri.com/whats-wrong-with-webcrypto) explains the trust model of the web quite well.
|
||||
|
|
|
@ -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",
|
||||
"homepage": "http://openpgpjs.org/",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
|
@ -46,10 +46,11 @@
|
|||
"phantomjs": "~1.9.2-5"
|
||||
},
|
||||
"dependencies": {
|
||||
"es6-promise": "^1.0.0",
|
||||
"node-localstorage": "~0.3.4"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/openpgpjs/openpgpjs"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +1,16 @@
|
|||
// 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
|
||||
|
@ -23,6 +23,8 @@
|
|||
* @module cleartext
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var config = require('./config'),
|
||||
packet = require('./packet'),
|
||||
enums = require('./enums.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<module:type/mpi>} publicMPIs Algorithm dependent multiprecision integers
|
||||
* @param {module:type/mpi} data Data to be encrypted as MPI
|
||||
* @return {Array<module:type/mpi>} if RSA an module:type/mpi;
|
||||
* @return {Array<module:type/mpi>} 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<module:type/mpi>} publicMPIs Algorithm dependent multiprecision integers
|
||||
* @param {Array<module:type/mpi>} publicMPIs Algorithm dependent multiprecision integers
|
||||
* of the public key part of the private key
|
||||
* @param {Array<module:type/mpi>} secretMPIs Algorithm dependent multiprecision integers
|
||||
* @param {Array<module:type/mpi>} 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
|
||||
|
@ -179,14 +179,13 @@ 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");
|
||||
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();
|
||||
return rsa.generate(bits, "10001").then(function(keyObject) {
|
||||
var output = [];
|
||||
output.push(keyObject.n);
|
||||
output.push(keyObject.ee);
|
||||
|
@ -194,17 +193,19 @@ 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 mapResult(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;
|
||||
});
|
||||
function mapResult(result) {
|
||||
return result.map(function(bn) {
|
||||
var mpi = new type_mpi();
|
||||
mpi.fromBigInteger(bn);
|
||||
return mpi;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
// 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
|
||||
|
@ -134,40 +134,97 @@ function RSA() {
|
|||
// Generate a new random private key B bits long, using public expt E
|
||||
|
||||
function generate(B, E) {
|
||||
var key = new keyObject();
|
||||
var rng = new SecureRandom();
|
||||
var qs = B >> 1;
|
||||
key.e = parseInt(E, 16);
|
||||
key.ee = new BigInteger(E, 16);
|
||||
for (;;) {
|
||||
for (;;) {
|
||||
key.p = new BigInteger(B - qs, 1, rng);
|
||||
if (key.p.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) === 0 && key.p.isProbablePrime(10))
|
||||
break;
|
||||
}
|
||||
for (;;) {
|
||||
key.q = new BigInteger(qs, 1, rng);
|
||||
if (key.q.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) === 0 && key.q.isProbablePrime(10))
|
||||
break;
|
||||
}
|
||||
if (key.p.compareTo(key.q) <= 0) {
|
||||
var t = key.p;
|
||||
key.p = key.q;
|
||||
key.q = t;
|
||||
}
|
||||
var p1 = key.p.subtract(BigInteger.ONE);
|
||||
var q1 = key.q.subtract(BigInteger.ONE);
|
||||
var phi = p1.multiply(q1);
|
||||
if (phi.gcd(key.ee).compareTo(BigInteger.ONE) === 0) {
|
||||
key.n = key.p.multiply(key.q);
|
||||
key.d = key.ee.modInverse(phi);
|
||||
key.dmp1 = key.d.mod(p1);
|
||||
key.dmq1 = key.d.mod(q1);
|
||||
key.u = key.p.modInverse(key.q);
|
||||
break;
|
||||
}
|
||||
var webCrypto = util.getWebCrypto();
|
||||
var promise;
|
||||
|
||||
//
|
||||
// Native RSA keygen using Web Crypto
|
||||
//
|
||||
|
||||
if (webCrypto) {
|
||||
var Euint32 = new Uint32Array([parseInt(E, 16)]); // get integer of exponent
|
||||
var Euint8 = new Uint8Array(Euint32.buffer); // get bytes of exponent
|
||||
var keyGenOpt = {
|
||||
name: 'RSASSA-PKCS1-v1_5',
|
||||
modulusLength: B, // the specified keysize in bits
|
||||
publicExponent: Euint8.subarray(0, 3), // take three bytes (max 65537)
|
||||
hash: {
|
||||
name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify'
|
||||
}
|
||||
};
|
||||
promise = webCrypto.generateKey(keyGenOpt, true, ['sign', 'verify']);
|
||||
return promise.then(exportKey).then(decodeKey);
|
||||
}
|
||||
return key;
|
||||
|
||||
function exportKey(key) {
|
||||
// export the generated keys as JsonWebKey (JWK)
|
||||
// https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33
|
||||
return webCrypto.exportKey('jwk', key.privateKey);
|
||||
}
|
||||
|
||||
function decodeKey(jwk) {
|
||||
// map JWK parameters to local BigInteger type system
|
||||
var key = new keyObject();
|
||||
key.n = toBigInteger(jwk.n);
|
||||
key.ee = new BigInteger(E, 16);
|
||||
key.d = toBigInteger(jwk.d);
|
||||
key.p = toBigInteger(jwk.p);
|
||||
key.q = toBigInteger(jwk.q);
|
||||
key.u = key.p.modInverse(key.q);
|
||||
|
||||
function toBigInteger(base64url) {
|
||||
var base64 = base64url.replace(/\-/g, '+').replace(/_/g, '/');
|
||||
var hex = util.hexstrdump(atob(base64));
|
||||
return new BigInteger(hex, 16);
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
//
|
||||
// JS code
|
||||
//
|
||||
|
||||
promise = new Promise(function(resolve) {
|
||||
var key = new keyObject();
|
||||
var rng = new SecureRandom();
|
||||
var qs = B >> 1;
|
||||
key.e = parseInt(E, 16);
|
||||
key.ee = new BigInteger(E, 16);
|
||||
|
||||
for (;;) {
|
||||
for (;;) {
|
||||
key.p = new BigInteger(B - qs, 1, rng);
|
||||
if (key.p.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) === 0 && key.p.isProbablePrime(10))
|
||||
break;
|
||||
}
|
||||
for (;;) {
|
||||
key.q = new BigInteger(qs, 1, rng);
|
||||
if (key.q.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) === 0 && key.q.isProbablePrime(10))
|
||||
break;
|
||||
}
|
||||
if (key.p.compareTo(key.q) <= 0) {
|
||||
var t = key.p;
|
||||
key.p = key.q;
|
||||
key.q = t;
|
||||
}
|
||||
var p1 = key.p.subtract(BigInteger.ONE);
|
||||
var q1 = key.q.subtract(BigInteger.ONE);
|
||||
var phi = p1.multiply(q1);
|
||||
if (phi.gcd(key.ee).compareTo(BigInteger.ONE) === 0) {
|
||||
key.n = key.p.multiply(key.q);
|
||||
key.d = key.ee.modInverse(phi);
|
||||
key.dmp1 = key.d.mod(p1);
|
||||
key.dmq1 = key.d.mod(q1);
|
||||
key.u = key.p.modInverse(key.q);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
resolve(key);
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
this.encrypt = encrypt;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* @module enums
|
||||
*/
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = require('./openpgp.js');
|
||||
/**
|
||||
|
|
187
src/key.js
187
src/key.js
|
@ -1,16 +1,16 @@
|
|||
// 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
|
||||
|
@ -23,6 +23,8 @@
|
|||
* @module key
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var packet = require('./packet'),
|
||||
enums = require('./enums.js'),
|
||||
armor = require('./encoding/armor.js'),
|
||||
|
@ -148,14 +150,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 +169,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<module:type/keyid>}
|
||||
* @returns {Array<module:type/keyid>}
|
||||
*/
|
||||
Key.prototype.getKeyIds = function() {
|
||||
var keyIds = [];
|
||||
|
@ -197,7 +199,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 +286,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 +344,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 +353,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 +372,14 @@ Key.prototype.decrypt = function(passphrase) {
|
|||
/**
|
||||
* Decrypts specific key packets by key ID
|
||||
* @param {Array<module:type/keyid>} 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 +400,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 +643,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 +697,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 +709,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 +794,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 +890,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;
|
||||
}
|
||||
|
@ -911,6 +913,8 @@ function readArmored(armoredText) {
|
|||
* @static
|
||||
*/
|
||||
function generate(options) {
|
||||
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 +925,85 @@ function generate(options) {
|
|||
options.unlocked = true;
|
||||
}
|
||||
|
||||
var packetlist = new packet.List();
|
||||
// generate
|
||||
var genSecretKey = generateSecretKey();
|
||||
var genSecretSubkey = generateSecretSubkey();
|
||||
return Promise.all([genSecretKey, genSecretSubkey]).then(wrapKeyObject);
|
||||
|
||||
var secretKeyPacket = new packet.SecretKey();
|
||||
secretKeyPacket.algorithm = enums.read(enums.publicKey, options.keyType);
|
||||
secretKeyPacket.generate(options.numBits);
|
||||
if (options.passphrase) {
|
||||
secretKeyPacket.encrypt(options.passphrase);
|
||||
function generateSecretKey() {
|
||||
secretKeyPacket = new packet.SecretKey();
|
||||
secretKeyPacket.algorithm = enums.read(enums.publicKey, options.keyType);
|
||||
return secretKeyPacket.generate(options.numBits);
|
||||
}
|
||||
|
||||
var userIdPacket = new packet.Userid();
|
||||
userIdPacket.read(options.userId);
|
||||
|
||||
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
|
||||
}
|
||||
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);
|
||||
function generateSecretSubkey() {
|
||||
secretSubkeyPacket = new packet.SecretSubkey();
|
||||
secretSubkeyPacket.algorithm = enums.read(enums.publicKey, options.keyType);
|
||||
return secretSubkeyPacket.generate(options.numBits);
|
||||
}
|
||||
|
||||
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);
|
||||
function wrapKeyObject() {
|
||||
// set passphrase protection
|
||||
if (options.passphrase) {
|
||||
secretKeyPacket.encrypt(options.passphrase);
|
||||
secretSubkeyPacket.encrypt(options.passphrase);
|
||||
}
|
||||
|
||||
packetlist.push(secretKeyPacket);
|
||||
packetlist.push(userIdPacket);
|
||||
packetlist.push(signaturePacket);
|
||||
packetlist.push(secretSubkeyPacket);
|
||||
packetlist.push(subkeySignaturePacket);
|
||||
packetlist = new packet.List();
|
||||
|
||||
if (!options.unlocked) {
|
||||
secretKeyPacket.clearPrivateMPIs();
|
||||
secretSubkeyPacket.clearPrivateMPIs();
|
||||
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);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
return new Key(packetlist);
|
||||
}
|
||||
|
||||
return new Key(packetlist);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
// 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
|
||||
|
@ -24,6 +24,8 @@
|
|||
* @module message
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var packet = require('./packet'),
|
||||
enums = require('./enums.js'),
|
||||
armor = require('./encoding/armor.js'),
|
||||
|
@ -83,7 +85,7 @@ Message.prototype.getSigningKeyIds = function() {
|
|||
|
||||
/**
|
||||
* Decrypt the message
|
||||
* @param {module:key~Key} privateKey private key with decrypted secret data
|
||||
* @param {module:key~Key} privateKey private key with decrypted secret data
|
||||
* @return {Array<module:message~Message>} new message with decrypted content
|
||||
*/
|
||||
Message.prototype.decrypt = function(privateKey) {
|
||||
|
@ -186,7 +188,7 @@ Message.prototype.sign = function(privateKeys) {
|
|||
|
||||
var literalDataPacket = this.packets.findPacket(enums.packet.literal);
|
||||
if (!literalDataPacket) throw new Error('No literal data packet to sign.');
|
||||
|
||||
|
||||
var literalFormat = enums.write(enums.literal, literalDataPacket.format);
|
||||
var signatureType = literalFormat == enums.literal.binary ?
|
||||
enums.signature.binary : enums.signature.text;
|
||||
|
@ -206,7 +208,7 @@ Message.prototype.sign = function(privateKeys) {
|
|||
}
|
||||
|
||||
packetlist.push(literalDataPacket);
|
||||
|
||||
|
||||
for (i = privateKeys.length - 1; i >= 0; i--) {
|
||||
var signaturePacket = new packet.Signature();
|
||||
signaturePacket.signatureType = signatureType;
|
||||
|
|
144
src/openpgp.js
144
src/openpgp.js
|
@ -31,15 +31,21 @@
|
|||
* @module openpgp
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var armor = require('./encoding/armor.js'),
|
||||
packet = require('./packet'),
|
||||
enums = require('./enums.js'),
|
||||
config = require('./config'),
|
||||
message = require('./message.js'),
|
||||
cleartext = require('./cleartext.js'),
|
||||
key = require('./key.js'),
|
||||
util = require('./util'),
|
||||
AsyncProxy = require('./worker/async_proxy.js');
|
||||
|
||||
if (typeof Promise === 'undefined') {
|
||||
// load ES6 Promises polyfill
|
||||
require('es6-promise').polyfill();
|
||||
}
|
||||
|
||||
var asyncProxy; // instance of the asyncproxy
|
||||
|
||||
/**
|
||||
|
@ -54,18 +60,16 @@ function initWorker(path) {
|
|||
* Encrypts message text with keys
|
||||
* @param {(Array<module:key~Key>|module:key~Key)} keys array of keys or single key, used to encrypt the message
|
||||
* @param {String} text message as native JavaScript string
|
||||
* @param {function} callback (optional) callback(error, result) for async style
|
||||
* @return {String} encrypted ASCII armored message
|
||||
* @static
|
||||
*/
|
||||
function encryptMessage(keys, text, callback) {
|
||||
function encryptMessage(keys, text) {
|
||||
if (!keys.length) {
|
||||
keys = [keys];
|
||||
}
|
||||
|
||||
if (useWorker(callback)) {
|
||||
asyncProxy.encryptMessage(keys, text, callback);
|
||||
return;
|
||||
if (useWorker()) {
|
||||
return asyncProxy.encryptMessage(keys, text);
|
||||
}
|
||||
|
||||
return execute(function() {
|
||||
|
@ -74,7 +78,8 @@ function encryptMessage(keys, text, callback) {
|
|||
msg = msg.encrypt(keys);
|
||||
armored = armor.encode(enums.armor.message, msg.packets.write());
|
||||
return armored;
|
||||
}, callback);
|
||||
|
||||
}, 'Error encrypting message!');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,18 +87,16 @@ function encryptMessage(keys, text, callback) {
|
|||
* @param {(Array<module:key~Key>|module:key~Key)} publicKeys array of keys or single key, used to encrypt the message
|
||||
* @param {module:key~Key} privateKey private key with decrypted secret key data for signing
|
||||
* @param {String} text message as native JavaScript string
|
||||
* @param {function} callback (optional) callback(error, result) for async style
|
||||
* @return {String} encrypted ASCII armored message
|
||||
* @static
|
||||
*/
|
||||
function signAndEncryptMessage(publicKeys, privateKey, text, callback) {
|
||||
function signAndEncryptMessage(publicKeys, privateKey, text) {
|
||||
if (!publicKeys.length) {
|
||||
publicKeys = [publicKeys];
|
||||
}
|
||||
|
||||
if (useWorker(callback)) {
|
||||
asyncProxy.signAndEncryptMessage(publicKeys, privateKey, text, callback);
|
||||
return;
|
||||
if (useWorker()) {
|
||||
return asyncProxy.signAndEncryptMessage(publicKeys, privateKey, text);
|
||||
}
|
||||
|
||||
return execute(function() {
|
||||
|
@ -103,28 +106,28 @@ function signAndEncryptMessage(publicKeys, privateKey, text, callback) {
|
|||
msg = msg.encrypt(publicKeys);
|
||||
armored = armor.encode(enums.armor.message, msg.packets.write());
|
||||
return armored;
|
||||
}, callback);
|
||||
|
||||
}, 'Error signing and encrypting message!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts message
|
||||
* @param {module:key~Key} privateKey private key with decrypted secret key data
|
||||
* @param {module:message~Message} msg the message object with the encrypted data
|
||||
* @param {function} callback (optional) callback(error, result) for async style
|
||||
* @return {(String|null)} decrypted message as as native JavaScript string
|
||||
* or null if no literal data found
|
||||
* @static
|
||||
*/
|
||||
function decryptMessage(privateKey, msg, callback) {
|
||||
if (useWorker(callback)) {
|
||||
asyncProxy.decryptMessage(privateKey, msg, callback);
|
||||
return;
|
||||
function decryptMessage(privateKey, msg) {
|
||||
if (useWorker()) {
|
||||
return asyncProxy.decryptMessage(privateKey, msg);
|
||||
}
|
||||
|
||||
return execute(function() {
|
||||
msg = msg.decrypt(privateKey);
|
||||
return msg.getText();
|
||||
}, callback);
|
||||
|
||||
}, 'Error decrypting message!');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,20 +135,18 @@ function decryptMessage(privateKey, msg, callback) {
|
|||
* @param {module:key~Key} privateKey private key with decrypted secret key data
|
||||
* @param {(Array<module:key~Key>|module:key~Key)} publicKeys array of keys or single key, to verify signatures
|
||||
* @param {module:message~Message} msg the message object with signed and encrypted data
|
||||
* @param {function} callback (optional) callback(error, result) for async style
|
||||
* @return {{text: String, signatures: Array<{keyid: module:type/keyid, valid: Boolean}>}}
|
||||
* decrypted message as as native JavaScript string
|
||||
* with verified signatures or null if no literal data found
|
||||
* @static
|
||||
*/
|
||||
function decryptAndVerifyMessage(privateKey, publicKeys, msg, callback) {
|
||||
function decryptAndVerifyMessage(privateKey, publicKeys, msg) {
|
||||
if (!publicKeys.length) {
|
||||
publicKeys = [publicKeys];
|
||||
}
|
||||
|
||||
if (useWorker(callback)) {
|
||||
asyncProxy.decryptAndVerifyMessage(privateKey, publicKeys, msg, callback);
|
||||
return;
|
||||
if (useWorker()) {
|
||||
return asyncProxy.decryptAndVerifyMessage(privateKey, publicKeys, msg);
|
||||
}
|
||||
|
||||
return execute(function() {
|
||||
|
@ -157,51 +158,49 @@ function decryptAndVerifyMessage(privateKey, publicKeys, msg, callback) {
|
|||
return result;
|
||||
}
|
||||
return null;
|
||||
}, callback);
|
||||
|
||||
}, 'Error decrypting and verifying message!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs a cleartext message
|
||||
* @param {(Array<module:key~Key>|module:key~Key)} privateKeys array of keys or single key with decrypted secret key data to sign cleartext
|
||||
* @param {String} text cleartext
|
||||
* @param {function} callback (optional) callback(error, result) for async style
|
||||
* @return {String} ASCII armored message
|
||||
* @static
|
||||
*/
|
||||
function signClearMessage(privateKeys, text, callback) {
|
||||
function signClearMessage(privateKeys, text) {
|
||||
if (!privateKeys.length) {
|
||||
privateKeys = [privateKeys];
|
||||
}
|
||||
|
||||
if (useWorker(callback)) {
|
||||
asyncProxy.signClearMessage(privateKeys, text, callback);
|
||||
return;
|
||||
if (useWorker()) {
|
||||
return asyncProxy.signClearMessage(privateKeys, text);
|
||||
}
|
||||
|
||||
return execute(function() {
|
||||
var cleartextMessage = new cleartext.CleartextMessage(text);
|
||||
cleartextMessage.sign(privateKeys);
|
||||
return cleartextMessage.armor();
|
||||
}, callback);
|
||||
|
||||
}, 'Error signing cleartext message!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies signatures of cleartext signed message
|
||||
* @param {(Array<module:key~Key>|module:key~Key)} publicKeys array of keys or single key, to verify signatures
|
||||
* @param {module:cleartext~CleartextMessage} msg cleartext message object with signatures
|
||||
* @param {function} callback (optional) callback(error, result) for async style
|
||||
* @return {{text: String, signatures: Array<{keyid: module:type/keyid, valid: Boolean}>}}
|
||||
* cleartext with status of verified signatures
|
||||
* @static
|
||||
*/
|
||||
function verifyClearSignedMessage(publicKeys, msg, callback) {
|
||||
function verifyClearSignedMessage(publicKeys, msg) {
|
||||
if (!publicKeys.length) {
|
||||
publicKeys = [publicKeys];
|
||||
}
|
||||
|
||||
if (useWorker(callback)) {
|
||||
asyncProxy.verifyClearSignedMessage(publicKeys, msg, callback);
|
||||
return;
|
||||
if (useWorker()) {
|
||||
return asyncProxy.verifyClearSignedMessage(publicKeys, msg);
|
||||
}
|
||||
|
||||
return execute(function() {
|
||||
|
@ -212,7 +211,8 @@ function verifyClearSignedMessage(publicKeys, msg, callback) {
|
|||
result.text = msg.getText();
|
||||
result.signatures = msg.verify(publicKeys);
|
||||
return result;
|
||||
}, callback);
|
||||
|
||||
}, 'Error verifying cleartext signed message!');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -224,24 +224,23 @@ function verifyClearSignedMessage(publicKeys, msg, callback) {
|
|||
* @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 {Boolean} [options.unlocked=false] The secret part of the generated key is unlocked
|
||||
* @param {function} callback (optional) callback(error, result) for async style
|
||||
* @return {Object} {key: module:key~Key, privateKeyArmored: String, publicKeyArmored: String}
|
||||
* @static
|
||||
*/
|
||||
function generateKeyPair(options, callback) {
|
||||
if (useWorker(callback)) {
|
||||
asyncProxy.generateKeyPair(options, callback);
|
||||
return;
|
||||
function generateKeyPair(options) {
|
||||
// use web worker if web crypto apis are not supported
|
||||
if (!util.getWebCrypto() && useWorker()) {
|
||||
return asyncProxy.generateKeyPair(options);
|
||||
}
|
||||
|
||||
return execute(function() {
|
||||
return key.generate(options).then(function(newKey) {
|
||||
var result = {};
|
||||
var newKey = key.generate(options);
|
||||
result.key = newKey;
|
||||
result.privateKeyArmored = newKey.armor();
|
||||
result.publicKeyArmored = newKey.toPublic().armor();
|
||||
return result;
|
||||
}, callback);
|
||||
|
||||
}, 'Error generating keypair!');
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -251,41 +250,50 @@ function generateKeyPair(options, callback) {
|
|||
/**
|
||||
* Are we in a browser and do we support worker?
|
||||
*/
|
||||
function useWorker(callback) {
|
||||
if (typeof window === 'undefined' || !window.Worker || typeof callback !== 'function') {
|
||||
function useWorker() {
|
||||
if (typeof window === 'undefined' || !window.Worker) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command pattern that handles async calls gracefully
|
||||
* Command pattern that wraps synchronous code into a promise
|
||||
* @param {function} cmd The synchronous function with a return value
|
||||
* to be wrapped in a promise
|
||||
* @param {String} errMsg A human readable error Message
|
||||
* @return {Promise} The promise wrapped around cmd
|
||||
*/
|
||||
function execute(cmd, callback) {
|
||||
var result;
|
||||
function execute(cmd, errMsg) {
|
||||
// wrap the sync cmd in a promise
|
||||
var promise = new Promise(function(resolve) {
|
||||
var result = cmd();
|
||||
resolve(result);
|
||||
});
|
||||
|
||||
try {
|
||||
result = cmd();
|
||||
} catch (err) {
|
||||
if (callback) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
// handler error globally
|
||||
promise.catch(onError.bind(null, errMsg));
|
||||
|
||||
throw err;
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback(null, result);
|
||||
return;
|
||||
}
|
||||
|
||||
return result;
|
||||
/**
|
||||
* Global error handler that logs the stack trace and
|
||||
* rethrows a high lvl error message
|
||||
* @param {String} message A human readable high level error Message
|
||||
* @param {Error} error The internal error that caused the failure
|
||||
*/
|
||||
function onError(message, error) {
|
||||
// log the stack trace
|
||||
console.error(error.stack);
|
||||
// rethrow new high level error for api users
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
exports.initWorker = initWorker;
|
||||
|
@ -295,4 +303,4 @@ exports.decryptMessage = decryptMessage;
|
|||
exports.decryptAndVerifyMessage = decryptAndVerifyMessage;
|
||||
exports.signClearMessage = signClearMessage;
|
||||
exports.verifyClearSignedMessage = verifyClearSignedMessage;
|
||||
exports.generateKeyPair = generateKeyPair;
|
||||
exports.generateKeyPair = generateKeyPair;
|
|
@ -1,16 +1,16 @@
|
|||
// 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
|
||||
|
@ -271,8 +271,12 @@ SecretKey.prototype.decrypt = function (passphrase) {
|
|||
};
|
||||
|
||||
SecretKey.prototype.generate = function (bits) {
|
||||
this.mpi = crypto.generateMpi(this.algorithm, bits);
|
||||
this.isDecrypted = true;
|
||||
var self = this;
|
||||
|
||||
return crypto.generateMpi(self.algorithm, bits).then(function(mpi) {
|
||||
self.mpi = mpi;
|
||||
self.isDecrypted = true;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
34
src/util.js
34
src/util.js
|
@ -1,16 +1,16 @@
|
|||
// 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
|
||||
|
@ -21,6 +21,8 @@
|
|||
* @module util
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var config = require('./config');
|
||||
|
||||
module.exports = {
|
||||
|
@ -193,7 +195,7 @@ module.exports = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Convert a Uint8Array to a string. This currently functions
|
||||
* Convert a Uint8Array to a string. This currently functions
|
||||
* the same as bin2str.
|
||||
* @function module:util.Uint8Array2str
|
||||
* @param {Uint8Array} bin An array of (binary) integers to convert
|
||||
|
@ -228,7 +230,7 @@ module.exports = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Helper function to print a debug message. Debug
|
||||
* Helper function to print a debug message. Debug
|
||||
* messages are only printed if
|
||||
* @link module:config/config.debug is set to true.
|
||||
* @param {String} str String of the debug message
|
||||
|
@ -240,7 +242,7 @@ module.exports = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Helper function to print a debug message. Debug
|
||||
* Helper function to print a debug message. Debug
|
||||
* messages are only printed if
|
||||
* @link module:config/config.debug is set to true.
|
||||
* Different than print_debug because will call hexstrdump iff necessary.
|
||||
|
@ -265,9 +267,9 @@ module.exports = {
|
|||
/**
|
||||
* Shifting a string to n bits right
|
||||
* @param {String} value The string to shift
|
||||
* @param {Integer} bitcount Amount of bits to shift (MUST be smaller
|
||||
* @param {Integer} bitcount Amount of bits to shift (MUST be smaller
|
||||
* than 9)
|
||||
* @return {String} Resulting string.
|
||||
* @return {String} Resulting string.
|
||||
*/
|
||||
shiftRight: function (value, bitcount) {
|
||||
var temp = util.str2bin(value);
|
||||
|
@ -305,5 +307,21 @@ module.exports = {
|
|||
return "SHA224";
|
||||
}
|
||||
return "unknown";
|
||||
},
|
||||
|
||||
/**
|
||||
* Get native Web Cryptography api. The default configuration is to use
|
||||
* the api when available. But it can also be deactivated with config.useWebCrypto
|
||||
* @return {Object} The SubtleCrypto api or 'undefined'
|
||||
*/
|
||||
getWebCrypto: function() {
|
||||
if (config.useWebCrypto === false) {
|
||||
// make web crypto optional
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined' && window.crypto && window.crypto.subtle) {
|
||||
return window.crypto.subtle;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -24,11 +24,12 @@
|
|||
* @module async_proxy
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var crypto = require('../crypto'),
|
||||
packet = require('../packet'),
|
||||
key = require('../key.js'),
|
||||
type_keyid = require('../type/keyid.js'),
|
||||
enums = require('../enums.js');
|
||||
type_keyid = require('../type/keyid.js');
|
||||
|
||||
var INITIAL_RANDOM_SEED = 50000, // random bytes seeded to worker
|
||||
RANDOM_SEED_REQUEST = 20000; // random bytes seeded after worker request
|
||||
|
@ -49,6 +50,24 @@ function AsyncProxy(path) {
|
|||
this.tasks = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Command pattern that wraps synchronous code into a promise
|
||||
* @param {Object} self The current this
|
||||
* @param {function} cmd The synchronous function with a return value
|
||||
* to be wrapped in a promise
|
||||
* @return {Promise} The promise wrapped around cmd
|
||||
*/
|
||||
AsyncProxy.prototype.execute = function(cmd) {
|
||||
var self = this;
|
||||
|
||||
var promise = new Promise(function(resolve, reject) {
|
||||
cmd();
|
||||
self.tasks.push({ resolve:resolve, reject:reject });
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* Message handling
|
||||
*/
|
||||
|
@ -56,7 +75,13 @@ AsyncProxy.prototype.onMessage = function(event) {
|
|||
var msg = event.data;
|
||||
switch (msg.event) {
|
||||
case 'method-return':
|
||||
this.tasks.shift()(msg.err ? new Error(msg.err) : null, msg.data);
|
||||
if (msg.err) {
|
||||
// fail
|
||||
this.tasks.shift().reject(new Error(msg.err));
|
||||
} else {
|
||||
// success
|
||||
this.tasks.shift().resolve(msg.data);
|
||||
}
|
||||
break;
|
||||
case 'request-seed':
|
||||
this.seedRandom(RANDOM_SEED_REQUEST);
|
||||
|
@ -98,21 +123,23 @@ AsyncProxy.prototype.terminate = function() {
|
|||
* Encrypts message text with keys
|
||||
* @param {(Array<module:key~Key>|module:key~Key)} keys array of keys or single key, used to encrypt the message
|
||||
* @param {String} text message as native JavaScript string
|
||||
* @param {Function} callback receives encrypted ASCII armored message
|
||||
*/
|
||||
AsyncProxy.prototype.encryptMessage = function(keys, text, callback) {
|
||||
if (!keys.length) {
|
||||
keys = [keys];
|
||||
}
|
||||
keys = keys.map(function(key) {
|
||||
return key.toPacketlist();
|
||||
AsyncProxy.prototype.encryptMessage = function(keys, text) {
|
||||
var self = this;
|
||||
|
||||
return self.execute(function() {
|
||||
if (!keys.length) {
|
||||
keys = [keys];
|
||||
}
|
||||
keys = keys.map(function(key) {
|
||||
return key.toPacketlist();
|
||||
});
|
||||
self.worker.postMessage({
|
||||
event: 'encrypt-message',
|
||||
keys: keys,
|
||||
text: text
|
||||
});
|
||||
});
|
||||
this.worker.postMessage({
|
||||
event: 'encrypt-message',
|
||||
keys: keys,
|
||||
text: text
|
||||
});
|
||||
this.tasks.push(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -120,40 +147,43 @@ AsyncProxy.prototype.encryptMessage = function(keys, text, callback) {
|
|||
* @param {(Array<module:key~Key>|module:key~Key)} publicKeys array of keys or single key, used to encrypt the message
|
||||
* @param {module:key~Key} privateKey private key with decrypted secret key data for signing
|
||||
* @param {String} text message as native JavaScript string
|
||||
* @param {Function} callback receives encrypted ASCII armored message
|
||||
*/
|
||||
AsyncProxy.prototype.signAndEncryptMessage = function(publicKeys, privateKey, text, callback) {
|
||||
if (!publicKeys.length) {
|
||||
publicKeys = [publicKeys];
|
||||
}
|
||||
publicKeys = publicKeys.map(function(key) {
|
||||
return key.toPacketlist();
|
||||
AsyncProxy.prototype.signAndEncryptMessage = function(publicKeys, privateKey, text) {
|
||||
var self = this;
|
||||
|
||||
return self.execute(function() {
|
||||
if (!publicKeys.length) {
|
||||
publicKeys = [publicKeys];
|
||||
}
|
||||
publicKeys = publicKeys.map(function(key) {
|
||||
return key.toPacketlist();
|
||||
});
|
||||
privateKey = privateKey.toPacketlist();
|
||||
self.worker.postMessage({
|
||||
event: 'sign-and-encrypt-message',
|
||||
publicKeys: publicKeys,
|
||||
privateKey: privateKey,
|
||||
text: text
|
||||
});
|
||||
});
|
||||
privateKey = privateKey.toPacketlist();
|
||||
this.worker.postMessage({
|
||||
event: 'sign-and-encrypt-message',
|
||||
publicKeys: publicKeys,
|
||||
privateKey: privateKey,
|
||||
text: text
|
||||
});
|
||||
this.tasks.push(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypts message
|
||||
* @param {module:key~Key} privateKey private key with decrypted secret key data
|
||||
* @param {module:message~Message} message the message object with the encrypted data
|
||||
* @param {Function} callback receives decrypted message as as native JavaScript string
|
||||
* or null if no literal data found
|
||||
*/
|
||||
AsyncProxy.prototype.decryptMessage = function(privateKey, message, callback) {
|
||||
privateKey = privateKey.toPacketlist();
|
||||
this.worker.postMessage({
|
||||
event: 'decrypt-message',
|
||||
privateKey: privateKey,
|
||||
message: message
|
||||
AsyncProxy.prototype.decryptMessage = function(privateKey, message) {
|
||||
var self = this;
|
||||
|
||||
return self.execute(function() {
|
||||
privateKey = privateKey.toPacketlist();
|
||||
self.worker.postMessage({
|
||||
event: 'decrypt-message',
|
||||
privateKey: privateKey,
|
||||
message: message
|
||||
});
|
||||
});
|
||||
this.tasks.push(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -161,82 +191,91 @@ AsyncProxy.prototype.decryptMessage = function(privateKey, message, callback) {
|
|||
* @param {module:key~Key} privateKey private key with decrypted secret key data
|
||||
* @param {(Array<module:key~Key>|module:key~Key)} publicKeys array of keys or single key to verify signatures
|
||||
* @param {module:message~Message} message the message object with signed and encrypted data
|
||||
* @param {Function} callback receives decrypted message as as native JavaScript string
|
||||
* with verified signatures or null if no literal data found
|
||||
*/
|
||||
AsyncProxy.prototype.decryptAndVerifyMessage = function(privateKey, publicKeys, message, callback) {
|
||||
privateKey = privateKey.toPacketlist();
|
||||
if (!publicKeys.length) {
|
||||
publicKeys = [publicKeys];
|
||||
}
|
||||
publicKeys = publicKeys.map(function(key) {
|
||||
return key.toPacketlist();
|
||||
});
|
||||
this.worker.postMessage({
|
||||
event: 'decrypt-and-verify-message',
|
||||
privateKey: privateKey,
|
||||
publicKeys: publicKeys,
|
||||
message: message
|
||||
});
|
||||
this.tasks.push(function(err, data) {
|
||||
if (data) {
|
||||
AsyncProxy.prototype.decryptAndVerifyMessage = function(privateKey, publicKeys, message) {
|
||||
var self = this;
|
||||
|
||||
var promise = new Promise(function(resolve, reject) {
|
||||
privateKey = privateKey.toPacketlist();
|
||||
if (!publicKeys.length) {
|
||||
publicKeys = [publicKeys];
|
||||
}
|
||||
publicKeys = publicKeys.map(function(key) {
|
||||
return key.toPacketlist();
|
||||
});
|
||||
self.worker.postMessage({
|
||||
event: 'decrypt-and-verify-message',
|
||||
privateKey: privateKey,
|
||||
publicKeys: publicKeys,
|
||||
message: message
|
||||
});
|
||||
|
||||
self.tasks.push({ resolve:function(data) {
|
||||
data.signatures = data.signatures.map(function(sig) {
|
||||
sig.keyid = type_keyid.fromClone(sig.keyid);
|
||||
return sig;
|
||||
});
|
||||
}
|
||||
callback(err, data);
|
||||
resolve(data);
|
||||
}, reject:reject });
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* Signs a cleartext message
|
||||
* @param {(Array<module:key~Key>|module:key~Key)} privateKeys array of keys or single key, with decrypted secret key data to sign cleartext
|
||||
* @param {String} text cleartext
|
||||
* @param {Function} callback receives ASCII armored message
|
||||
*/
|
||||
AsyncProxy.prototype.signClearMessage = function(privateKeys, text, callback) {
|
||||
if (!privateKeys.length) {
|
||||
privateKeys = [privateKeys];
|
||||
}
|
||||
privateKeys = privateKeys.map(function(key) {
|
||||
return key.toPacketlist();
|
||||
AsyncProxy.prototype.signClearMessage = function(privateKeys, text) {
|
||||
var self = this;
|
||||
|
||||
return self.execute(function() {
|
||||
if (!privateKeys.length) {
|
||||
privateKeys = [privateKeys];
|
||||
}
|
||||
privateKeys = privateKeys.map(function(key) {
|
||||
return key.toPacketlist();
|
||||
});
|
||||
self.worker.postMessage({
|
||||
event: 'sign-clear-message',
|
||||
privateKeys: privateKeys,
|
||||
text: text
|
||||
});
|
||||
});
|
||||
this.worker.postMessage({
|
||||
event: 'sign-clear-message',
|
||||
privateKeys: privateKeys,
|
||||
text: text
|
||||
});
|
||||
this.tasks.push(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Verifies signatures of cleartext signed message
|
||||
* @param {(Array<module:key~Key>|module:key~Key)} publicKeys array of keys or single key, to verify signatures
|
||||
* @param {module:cleartext~CleartextMessage} message cleartext message object with signatures
|
||||
* @param {Function} callback receives cleartext with status of verified signatures
|
||||
*/
|
||||
AsyncProxy.prototype.verifyClearSignedMessage = function(publicKeys, message, callback) {
|
||||
if (!publicKeys.length) {
|
||||
publicKeys = [publicKeys];
|
||||
}
|
||||
publicKeys = publicKeys.map(function(key) {
|
||||
return key.toPacketlist();
|
||||
});
|
||||
this.worker.postMessage({
|
||||
event: 'verify-clear-signed-message',
|
||||
publicKeys: publicKeys,
|
||||
message: message
|
||||
});
|
||||
this.tasks.push(function(err, data) {
|
||||
if (data) {
|
||||
AsyncProxy.prototype.verifyClearSignedMessage = function(publicKeys, message) {
|
||||
var self = this;
|
||||
|
||||
var promise = new Promise(function(resolve, reject) {
|
||||
if (!publicKeys.length) {
|
||||
publicKeys = [publicKeys];
|
||||
}
|
||||
publicKeys = publicKeys.map(function(key) {
|
||||
return key.toPacketlist();
|
||||
});
|
||||
self.worker.postMessage({
|
||||
event: 'verify-clear-signed-message',
|
||||
publicKeys: publicKeys,
|
||||
message: message
|
||||
});
|
||||
|
||||
self.tasks.push({ resolve:function(data) {
|
||||
data.signatures = data.signatures.map(function(sig) {
|
||||
sig.keyid = type_keyid.fromClone(sig.keyid);
|
||||
return sig;
|
||||
});
|
||||
}
|
||||
callback(err, data);
|
||||
resolve(data);
|
||||
}, reject:reject });
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -247,42 +286,50 @@ AsyncProxy.prototype.verifyClearSignedMessage = function(publicKeys, message, ca
|
|||
* @param {Integer} numBits number of bits for the key creation. (should be 1024+, generally)
|
||||
* @param {String} userId assumes already in form of "User Name <username@email.com>"
|
||||
* @param {String} passphrase The passphrase used to encrypt the resulting private key
|
||||
* @param {Function} callback receives object with key and public and private armored texts
|
||||
*/
|
||||
AsyncProxy.prototype.generateKeyPair = function(options, callback) {
|
||||
this.worker.postMessage({
|
||||
event: 'generate-key-pair',
|
||||
options: options
|
||||
});
|
||||
this.tasks.push(function(err, data) {
|
||||
if (data) {
|
||||
AsyncProxy.prototype.generateKeyPair = function(options) {
|
||||
var self = this;
|
||||
|
||||
var promise = new Promise(function(resolve, reject) {
|
||||
self.worker.postMessage({
|
||||
event: 'generate-key-pair',
|
||||
options: options
|
||||
});
|
||||
|
||||
self.tasks.push({ resolve:function(data) {
|
||||
var packetlist = packet.List.fromStructuredClone(data.key);
|
||||
data.key = new key.Key(packetlist);
|
||||
}
|
||||
callback(err, data);
|
||||
resolve(data);
|
||||
}, reject:reject });
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypts secret part of all secret key packets of key.
|
||||
* @param {module:key~Key} privateKey private key with encrypted secret key data
|
||||
* @param {String} password password to unlock the key
|
||||
* @param {Function} callback receives decrypted key
|
||||
*/
|
||||
AsyncProxy.prototype.decryptKey = function(privateKey, password, callback) {
|
||||
privateKey = privateKey.toPacketlist();
|
||||
this.worker.postMessage({
|
||||
event: 'decrypt-key',
|
||||
privateKey: privateKey,
|
||||
password: password
|
||||
});
|
||||
this.tasks.push(function(err, data) {
|
||||
if (data) {
|
||||
AsyncProxy.prototype.decryptKey = function(privateKey, password) {
|
||||
var self = this;
|
||||
|
||||
var promise = new Promise(function(resolve, reject) {
|
||||
privateKey = privateKey.toPacketlist();
|
||||
self.worker.postMessage({
|
||||
event: 'decrypt-key',
|
||||
privateKey: privateKey,
|
||||
password: password
|
||||
});
|
||||
|
||||
self.tasks.push({ resolve:function(data) {
|
||||
var packetlist = packet.List.fromStructuredClone(data);
|
||||
data = new key.Key(packetlist);
|
||||
}
|
||||
callback(err, data);
|
||||
resolve(data);
|
||||
}, reject:reject });
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -290,23 +337,27 @@ AsyncProxy.prototype.decryptKey = function(privateKey, password, callback) {
|
|||
* @param {module:key~Key} privateKey private key with encrypted secret key data
|
||||
* @param {Array<module:type/keyid>} keyIds
|
||||
* @param {String} password password to unlock the key
|
||||
* @param {Function} callback receives decrypted key
|
||||
*/
|
||||
AsyncProxy.prototype.decryptKeyPacket = function(privateKey, keyIds, password, callback) {
|
||||
privateKey = privateKey.toPacketlist();
|
||||
this.worker.postMessage({
|
||||
event: 'decrypt-key-packet',
|
||||
privateKey: privateKey,
|
||||
keyIds: keyIds,
|
||||
password: password
|
||||
});
|
||||
this.tasks.push(function(err, data) {
|
||||
if (data) {
|
||||
AsyncProxy.prototype.decryptKeyPacket = function(privateKey, keyIds, password) {
|
||||
var self = this;
|
||||
|
||||
var promise = new Promise(function(resolve, reject) {
|
||||
privateKey = privateKey.toPacketlist();
|
||||
self.worker.postMessage({
|
||||
event: 'decrypt-key-packet',
|
||||
privateKey: privateKey,
|
||||
keyIds: keyIds,
|
||||
password: password
|
||||
});
|
||||
|
||||
self.tasks.push({ resolve:function(data) {
|
||||
var packetlist = packet.List.fromStructuredClone(data);
|
||||
data = new key.Key(packetlist);
|
||||
}
|
||||
callback(err, data);
|
||||
resolve(data);
|
||||
}, reject:reject });
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
module.exports = AsyncProxy;
|
||||
|
|
|
@ -1,22 +1,44 @@
|
|||
// 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
|
||||
|
||||
window = {}; // to make UMD bundles work
|
||||
|
||||
// Mozilla bind polyfill because phantomjs is stupid
|
||||
if (!Function.prototype.bind) {
|
||||
Function.prototype.bind = function(oThis) {
|
||||
if (typeof this !== "function") {
|
||||
// closest thing possible to the ECMAScript 5 internal IsCallable function
|
||||
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
|
||||
}
|
||||
|
||||
var aArgs = Array.prototype.slice.call(arguments, 1),
|
||||
fToBind = this,
|
||||
FNOP = function() {},
|
||||
fBound = function() {
|
||||
return fToBind.apply(this instanceof FNOP && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
|
||||
};
|
||||
|
||||
FNOP.prototype = this.prototype;
|
||||
fBound.prototype = new FNOP();
|
||||
|
||||
return fBound;
|
||||
};
|
||||
}
|
||||
|
||||
importScripts('openpgp.js');
|
||||
|
||||
var MIN_SIZE_RANDOM_BUFFER = 40000;
|
||||
|
@ -24,11 +46,12 @@ var MAX_SIZE_RANDOM_BUFFER = 60000;
|
|||
|
||||
window.openpgp.crypto.random.randomBuffer.init(MAX_SIZE_RANDOM_BUFFER);
|
||||
|
||||
onmessage = function (event) {
|
||||
var data = null,
|
||||
self.onmessage = function (event) {
|
||||
var data = null,
|
||||
err = null,
|
||||
msg = event.data,
|
||||
correct = false;
|
||||
|
||||
switch (msg.event) {
|
||||
case 'seed-random':
|
||||
if (!(msg.buf instanceof Uint8Array)) {
|
||||
|
@ -37,85 +60,78 @@ onmessage = function (event) {
|
|||
window.openpgp.crypto.random.randomBuffer.set(msg.buf);
|
||||
break;
|
||||
case 'encrypt-message':
|
||||
try {
|
||||
if (!msg.keys.length) {
|
||||
msg.keys = [msg.keys];
|
||||
}
|
||||
msg.keys = msg.keys.map(packetlistCloneToKey);
|
||||
data = window.openpgp.encryptMessage(msg.keys, msg.text);
|
||||
} catch (e) {
|
||||
err = e.message;
|
||||
if (!msg.keys.length) {
|
||||
msg.keys = [msg.keys];
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
msg.keys = msg.keys.map(packetlistCloneToKey);
|
||||
window.openpgp.encryptMessage(msg.keys, msg.text).then(function(data) {
|
||||
response({event: 'method-return', data: data});
|
||||
}).catch(function(e) {
|
||||
response({event: 'method-return', err: e.message});
|
||||
});
|
||||
break;
|
||||
case 'sign-and-encrypt-message':
|
||||
try {
|
||||
if (!msg.publicKeys.length) {
|
||||
msg.publicKeys = [msg.publicKeys];
|
||||
}
|
||||
msg.publicKeys = msg.publicKeys.map(packetlistCloneToKey);
|
||||
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
||||
data = window.openpgp.signAndEncryptMessage(msg.publicKeys, msg.privateKey, msg.text);
|
||||
} catch (e) {
|
||||
err = e.message;
|
||||
if (!msg.publicKeys.length) {
|
||||
msg.publicKeys = [msg.publicKeys];
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
msg.publicKeys = msg.publicKeys.map(packetlistCloneToKey);
|
||||
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
||||
window.openpgp.signAndEncryptMessage(msg.publicKeys, msg.privateKey, msg.text).then(function(data) {
|
||||
response({event: 'method-return', data: data});
|
||||
}).catch(function(e) {
|
||||
response({event: 'method-return', err: e.message});
|
||||
});
|
||||
break;
|
||||
case 'decrypt-message':
|
||||
try {
|
||||
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
||||
msg.message = packetlistCloneToMessage(msg.message.packets);
|
||||
data = window.openpgp.decryptMessage(msg.privateKey, msg.message);
|
||||
} catch (e) {
|
||||
err = e.message;
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
||||
msg.message = packetlistCloneToMessage(msg.message.packets);
|
||||
window.openpgp.decryptMessage(msg.privateKey, msg.message).then(function(data) {
|
||||
response({event: 'method-return', data: data});
|
||||
}).catch(function(e) {
|
||||
response({event: 'method-return', err: e.message});
|
||||
});
|
||||
break;
|
||||
case 'decrypt-and-verify-message':
|
||||
try {
|
||||
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
||||
if (!msg.publicKeys.length) {
|
||||
msg.publicKeys = [msg.publicKeys];
|
||||
}
|
||||
msg.publicKeys = msg.publicKeys.map(packetlistCloneToKey);
|
||||
msg.message = packetlistCloneToMessage(msg.message.packets);
|
||||
data = window.openpgp.decryptAndVerifyMessage(msg.privateKey, msg.publicKeys, msg.message);
|
||||
} catch (e) {
|
||||
err = e.message;
|
||||
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
||||
if (!msg.publicKeys.length) {
|
||||
msg.publicKeys = [msg.publicKeys];
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
msg.publicKeys = msg.publicKeys.map(packetlistCloneToKey);
|
||||
msg.message = packetlistCloneToMessage(msg.message.packets);
|
||||
window.openpgp.decryptAndVerifyMessage(msg.privateKey, msg.publicKeys, msg.message).then(function(data) {
|
||||
response({event: 'method-return', data: data});
|
||||
}).catch(function(e) {
|
||||
response({event: 'method-return', err: e.message});
|
||||
});
|
||||
break;
|
||||
case 'sign-clear-message':
|
||||
try {
|
||||
msg.privateKeys = msg.privateKeys.map(packetlistCloneToKey);
|
||||
data = window.openpgp.signClearMessage(msg.privateKeys, msg.text);
|
||||
} catch (e) {
|
||||
err = e.message;
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
msg.privateKeys = msg.privateKeys.map(packetlistCloneToKey);
|
||||
window.openpgp.signClearMessage(msg.privateKeys, msg.text).then(function(data) {
|
||||
response({event: 'method-return', data: data});
|
||||
}).catch(function(e) {
|
||||
response({event: 'method-return', err: e.message});
|
||||
});
|
||||
break;
|
||||
case 'verify-clear-signed-message':
|
||||
try {
|
||||
if (!msg.publicKeys.length) {
|
||||
msg.publicKeys = [msg.publicKeys];
|
||||
}
|
||||
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);
|
||||
data = window.openpgp.verifyClearSignedMessage(msg.publicKeys, msg.message);
|
||||
} catch (e) {
|
||||
err = e.message;
|
||||
if (!msg.publicKeys.length) {
|
||||
msg.publicKeys = [msg.publicKeys];
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
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);
|
||||
window.openpgp.verifyClearSignedMessage(msg.publicKeys, msg.message).then(function(data) {
|
||||
response({event: 'method-return', data: data});
|
||||
}).catch(function(e) {
|
||||
response({event: 'method-return', err: e.message});
|
||||
});
|
||||
break;
|
||||
case 'generate-key-pair':
|
||||
try {
|
||||
data = window.openpgp.generateKeyPair(msg.options);
|
||||
window.openpgp.generateKeyPair(msg.options).then(function(data) {
|
||||
data.key = data.key.toPacketlist();
|
||||
} catch (e) {
|
||||
err = e.message;
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
response({event: 'method-return', data: data});
|
||||
}).catch(function(e) {
|
||||
response({event: 'method-return', err: e.message});
|
||||
});
|
||||
break;
|
||||
case 'decrypt-key':
|
||||
try {
|
||||
|
|
|
@ -8,94 +8,114 @@ 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};
|
||||
var privKey;
|
||||
var pubKey;
|
||||
|
||||
var info = '\npassphrase: ' + passphrase + '\n' + 'userid: ' + userid + '\n' + 'message: ' + message;
|
||||
openpgp.generateKeyPair(opt).then(function(key) {
|
||||
|
||||
var privKeys = openpgp.key.readArmored(key.privateKeyArmored);
|
||||
var publicKeys = openpgp.key.readArmored(key.publicKeyArmored);
|
||||
expect(key).to.exist;
|
||||
expect(key.key).to.exist;
|
||||
expect(key.privateKeyArmored).to.exist;
|
||||
expect(key.publicKeyArmored).to.exist;
|
||||
|
||||
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;
|
||||
privKey = privKeys.keys[0];
|
||||
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);
|
||||
expect(success).to.be.true;
|
||||
|
||||
var encrypted = openpgp.signAndEncryptMessage([pubKey], privKey, message);
|
||||
return openpgp.signAndEncryptMessage([pubKey], privKey, message);
|
||||
|
||||
expect(encrypted).to.exist;
|
||||
}).then(function(encrypted) {
|
||||
|
||||
var msg = openpgp.message.readArmored(encrypted);
|
||||
expect(encrypted).to.exist;
|
||||
var msg = openpgp.message.readArmored(encrypted);
|
||||
expect(msg).to.exist;
|
||||
var keyids = msg.getEncryptionKeyIds();
|
||||
expect(keyids).to.exist;
|
||||
|
||||
expect(msg).to.exist;
|
||||
return openpgp.decryptAndVerifyMessage(privKey, [pubKey], msg);
|
||||
|
||||
var keyids = msg.getEncryptionKeyIds();
|
||||
}).then(function(decrypted) {
|
||||
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 <test@example.com>', 'hello world');
|
||||
done();
|
||||
testHelper('password', 'Test McTestington <test@example.com>', 'hello world', done);
|
||||
});
|
||||
it('Unicode Text', function (done) {
|
||||
testHelper('●●●●', '♔♔♔♔ <test@example.com>', 'łäóć');
|
||||
done();
|
||||
testHelper('●●●●', '♔♔♔♔ <test@example.com>', 'łäóć', done);
|
||||
});
|
||||
|
||||
it('should fail to verify signature for wrong public key', function (done) {
|
||||
var userid = 'Test McTestington <test@example.com>';
|
||||
var passphrase = 'password';
|
||||
var message = 'hello world';
|
||||
var privKey;
|
||||
var pubKey;
|
||||
var msg;
|
||||
|
||||
var key = openpgp.generateKeyPair({numBits: 512, userId: userid, passphrase: passphrase});
|
||||
var opt = {numBits: 512, userId: userid, passphrase: passphrase};
|
||||
openpgp.generateKeyPair(opt).then(function(key) {
|
||||
|
||||
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];
|
||||
privKey = privKeys.keys[0];
|
||||
pubKey = publicKeys.keys[0];
|
||||
|
||||
var success = privKey.decrypt(passphrase);
|
||||
var success = privKey.decrypt(passphrase);
|
||||
expect(success).to.be.true;
|
||||
|
||||
var encrypted = openpgp.signAndEncryptMessage([pubKey], privKey, message);
|
||||
return openpgp.signAndEncryptMessage([pubKey], privKey, message);
|
||||
|
||||
var msg = openpgp.message.readArmored(encrypted);
|
||||
expect(msg).to.exist;
|
||||
}).then(function(encrypted) {
|
||||
|
||||
var anotherKey = openpgp.generateKeyPair({numBits: 512, userId: userid, passphrase: passphrase});
|
||||
var anotherPubKey = openpgp.key.readArmored(anotherKey.publicKeyArmored).keys[0];
|
||||
msg = openpgp.message.readArmored(encrypted);
|
||||
expect(msg).to.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();
|
||||
return openpgp.generateKeyPair(opt);
|
||||
|
||||
}).then(function(anotherKey) {
|
||||
|
||||
var anotherPubKey = openpgp.key.readArmored(anotherKey.publicKeyArmored).keys[0];
|
||||
|
||||
return openpgp.decryptAndVerifyMessage(privKey, [anotherPubKey], msg);
|
||||
|
||||
}).then(function(decrypted) {
|
||||
|
||||
expect(decrypted).to.exist;
|
||||
expect(decrypted.signatures[0].valid).to.be.null;
|
||||
expect(decrypted.text).to.equal(message);
|
||||
done();
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
it('Performance test', function (done) {
|
||||
// init test data
|
||||
function randomString(length, chars) {
|
||||
var result = '';
|
||||
for (var i = length; i > 0; --i) result += chars[Math.round(Math.random() * (chars.length - 1))];
|
||||
for (var i = length; i > 0; --i) {
|
||||
result += chars[Math.round(Math.random() * (chars.length - 1))];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
var message = randomString(1024*1024*3, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
|
||||
|
@ -103,46 +123,49 @@ describe('Basic', function() {
|
|||
var userid = 'Test McTestington <test@example.com>';
|
||||
var passphrase = 'password';
|
||||
|
||||
var key = openpgp.generateKeyPair({numBits: 512, userId: userid, passphrase: passphrase});
|
||||
var opt = {numBits: 512, userId: userid, passphrase: passphrase};
|
||||
openpgp.generateKeyPair(opt).then(function(key) {
|
||||
|
||||
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);
|
||||
expect(success).to.be.true;
|
||||
|
||||
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;
|
||||
return openpgp.decryptAndVerifyMessage(privKey, [pubKey], msg);
|
||||
|
||||
var decrypted = openpgp.decryptAndVerifyMessage(privKey, [pubKey], msg);
|
||||
}).then(function(decrypted) {
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -227,30 +250,33 @@ describe('Basic', function() {
|
|||
|
||||
expect(pubKey).to.exist;
|
||||
|
||||
var encrypted = openpgp.encryptMessage([pubKey], plaintext);
|
||||
openpgp.encryptMessage([pubKey], plaintext).then(function(encrypted) {
|
||||
|
||||
expect(encrypted).to.exist;
|
||||
expect(encrypted).to.exist;
|
||||
|
||||
message = openpgp.message.readArmored(encrypted);
|
||||
message = openpgp.message.readArmored(encrypted);
|
||||
|
||||
expect(message).to.exist;
|
||||
expect(message).to.exist;
|
||||
|
||||
var privKeys = openpgp.key.readArmored(priv_key);
|
||||
var privKeys = openpgp.key.readArmored(priv_key);
|
||||
|
||||
expect(privKeys).to.exist;
|
||||
expect(privKeys.err).to.not.exist;
|
||||
expect(privKeys.keys).to.have.length(1);
|
||||
expect(privKeys).to.exist;
|
||||
expect(privKeys.err).to.not.exist;
|
||||
expect(privKeys.keys).to.have.length(1);
|
||||
|
||||
privKey = privKeys.keys[0];
|
||||
privKey = privKeys.keys[0];
|
||||
|
||||
expect(privKey).to.exist;
|
||||
expect(privKey).to.exist;
|
||||
|
||||
// get key IDs the message is encrypted for
|
||||
keyids = message.getEncryptionKeyIds();
|
||||
// get key IDs the message is encrypted for
|
||||
keyids = message.getEncryptionKeyIds();
|
||||
|
||||
expect(keyids).to.exist;
|
||||
expect(keyids).to.have.length(1);
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
expect(keyids).to.exist;
|
||||
expect(keyids).to.have.length(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('Decrypting key packet with wrong password returns false', function (done) {
|
||||
|
@ -261,15 +287,11 @@ describe('Basic', function() {
|
|||
done();
|
||||
});
|
||||
|
||||
var decrypted, error;
|
||||
|
||||
it('Calling decryptMessage with not decrypted key packet leads to exception', function (done) {
|
||||
function exceptionTest() {
|
||||
decrypted = openpgp.decryptMessage(privKey, message);
|
||||
}
|
||||
|
||||
expect(exceptionTest).to.throw(Error);
|
||||
done();
|
||||
openpgp.decryptMessage(privKey, message).catch(function(error) {
|
||||
expect(error).to.exist;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Decrypting key packet with correct password returns true', function (done) {
|
||||
|
@ -280,16 +302,23 @@ describe('Basic', function() {
|
|||
});
|
||||
|
||||
it('Encrypt plain text and afterwards decrypt leads to same result', function (done) {
|
||||
decrypted = openpgp.decryptMessage(privKey, message);
|
||||
expect(decrypted).to.exist;
|
||||
expect(decrypted).to.equal(plaintext);
|
||||
done();
|
||||
openpgp.decryptMessage(privKey, message).then(function(decrypted) {
|
||||
expect(decrypted).to.exist;
|
||||
expect(decrypted).to.equal(plaintext);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Decrypt message 2x', function() {
|
||||
decrypted = openpgp.decryptMessage(privKey, message);
|
||||
var decrypted2 = openpgp.decryptMessage(privKey, message);
|
||||
expect(decrypted).to.equal(decrypted2);
|
||||
it('Decrypt message 2x', function(done) {
|
||||
var decrypted1;
|
||||
|
||||
openpgp.decryptMessage(privKey, message).then(function(decrypted) {
|
||||
decrypted1 = decrypted;
|
||||
return openpgp.decryptMessage(privKey, message);
|
||||
}).then(function(decrypted2) {
|
||||
expect(decrypted1).to.equal(decrypted2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -347,15 +376,17 @@ describe('Basic', function() {
|
|||
'-----END PGP PRIVATE KEY BLOCK-----'].join('\n');
|
||||
|
||||
it('Decrypt message', function (done) {
|
||||
var privKey, message, decrypted;
|
||||
var privKey, message;
|
||||
|
||||
privKey = openpgp.key.readArmored(priv_key).keys[0];
|
||||
privKey.decrypt('1234');
|
||||
message = openpgp.message.readArmored(pgp_msg);
|
||||
decrypted = openpgp.decryptMessage(privKey, message);
|
||||
|
||||
expect(decrypted).to.equal('hello 3des\n');
|
||||
done();
|
||||
openpgp.decryptMessage(privKey, message).then(function(decrypted) {
|
||||
expect(decrypted).to.equal('hello 3des\n');
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -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,13 @@ 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).then(function(key) {
|
||||
testPref(key.key);
|
||||
testPref(openpgp.key.readArmored(key.publicKeyArmored).keys[0]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('User attribute packet read & write', function() {
|
||||
|
@ -653,11 +656,14 @@ 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).then(function(key) {
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -6,445 +6,444 @@ 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' +
|
||||
'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\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").then(function(mpiGen) {
|
||||
|
||||
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];
|
||||
mpi = mpi.map(function(k) {
|
||||
var mpi = new openpgp.MPI();
|
||||
mpi.fromBigInteger(k);
|
||||
return mpi;
|
||||
});
|
||||
|
||||
var enc = new openpgp.packet.PublicKeyEncryptedSessionKey(),
|
||||
msg = new openpgp.packet.List(),
|
||||
msg2 = new openpgp.packet.List();
|
||||
var enc = new openpgp.packet.PublicKeyEncryptedSessionKey(),
|
||||
msg = new openpgp.packet.List(),
|
||||
msg2 = new openpgp.packet.List();
|
||||
|
||||
enc.sessionKey = '12345678901234567890123456789012';
|
||||
enc.publicKeyAlgorithm = 'rsa_encrypt';
|
||||
enc.sessionKeyAlgorithm = 'aes256';
|
||||
enc.publicKeyId.bytes = '12345678';
|
||||
enc.encrypt({ mpi: mpi });
|
||||
enc.sessionKey = '12345678901234567890123456789012';
|
||||
enc.publicKeyAlgorithm = 'rsa_encrypt';
|
||||
enc.sessionKeyAlgorithm = 'aes256';
|
||||
enc.publicKeyId.bytes = '12345678';
|
||||
enc.encrypt({ mpi: mpi });
|
||||
|
||||
msg.push(enc);
|
||||
msg.push(enc);
|
||||
|
||||
msg2.read(msg.write());
|
||||
msg2.read(msg.write());
|
||||
|
||||
msg2[0].decrypt({ mpi: mpi });
|
||||
msg2[0].decrypt({ mpi: mpi });
|
||||
|
||||
expect(msg2[0].sessionKey).to.equal(enc.sessionKey);
|
||||
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) {
|
||||
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' +
|
||||
'lQHYBFF6gtkBBADKUOWZK6/V75MNwBS+hLYicoS0Sojbo3qWXXpS7eM+uhiDm4bP\n' +
|
||||
'DNjdNVA0R+TCjvhWbc3W6cvdHYTmHRMhTIOefncZRt3OwF7AvVk53fKKPiNNv5C9\n' +
|
||||
'IK8bcDhAknSOg1TXRSpXLHtYy36A6iDgffNSjoCOVaeKpuRDMA37PvJWFQARAQAB\n' +
|
||||
'AAP+KxHbOwcrnPPuXppCYEew3Xb7LMWESpvMFFgsmxx1COzFnLjek1P1E+yOWT7n\n' +
|
||||
'4opcsEuaazLk+TrYSMOuR6O6DgGg5c+ctVPU+NGNNCiiTkOzuD+8ow8NgsoINOxi\n' +
|
||||
'481qLK0NYpc5sEg394J3fRuzpfEi6DTS/RzCN7YDiGFccNECAM71NuaAzH5LrZ+B\n' +
|
||||
'4Okwy9CQQbgoYrdaia24CjEaUODaROnyNsvOb0ydEebVAbGzrsBr6LrisTidyZsG\n' +
|
||||
't2T+L7ECAPpCFzZIwwk6giZ10HmXEhXZLXYmdhQD/1fwegpTrEciMA6MCcdkcCyO\n' +
|
||||
'2/J+S+NXM62ykMGDhg2cjhU1rj/uaaUCAJfCjkwpxMsDKHYDFDXyjJFy2vEmA3s8\n' +
|
||||
'cnmAUDF1caPyEcPEZmYJRE+KdroOD6IGhzp7oA34Ef3D6HOCovH9YaCgbbQbSm9o\n' +
|
||||
'bm55IDxqb2hubnlAZXhhbXBsZS5jb20+iLkEEwECACMFAlF6gtkCGwMHCwkIBwMC\n' +
|
||||
'AQYVCAIJCgsEFgIDAQIeAQIXgAAKCRA6HTM8yP08keZgA/4vL273zrqnmOrqmo/K\n' +
|
||||
'UxQgD0vMhM58d25UjGYI6LAZkAls/k4FvFt5GUHVWJR3HBRuuNlB7UndH/uYlU7j\n' +
|
||||
'm/bQLiP4uvFQuRGuG76f0O5t/KyeUdzrpNiJpe8tYDAnoPxUzENYsIv0fm2ZISo1\n' +
|
||||
'QnnXX2WuVZGMZH1YhQoakZxbnp0B2ARReoLZAQQAvQvPp2MLu9vnRvZ3Py559kQf\n' +
|
||||
'0Z5AnEXVokALTn5A2m51dLekQ9T3Rhz8p9I6C/XjVQwBkp1USOaDUz+L7lsbNdY4\n' +
|
||||
'YbUi3eIA5RImVXeTIrD1hE4CllDNKmqT5wFN07eEu7QhDEuYioO+4gtjjhUDYeIA\n' +
|
||||
'dCVtVO//q8rP8ukZEc8AEQEAAQAD/RHlttyNe3RnDr/AoKx6HXDLpUmGlm5VDDMm\n' +
|
||||
'pgth14j2cSdCJYqIdHqOTvsiY31zY3jPQKzdOTgHnsI4X2qK9InbwXepSBkaOJzY\n' +
|
||||
'iNhifPSUs9qoNawDqbFJ8PMXd4QQGgM93w+tudKC650Zuq7M7eWSdQg0u9aoLY97\n' +
|
||||
'MpKx3DUFAgDA/RgoO8xYMgkKN1tuKWa61qesLdJRAZI/3cnvtsmmEBt9tdbcDoBz\n' +
|
||||
'gOIAAvUFgipuP6dBWLyf2NRNRVVQdNTlAgD6xS7S87g3kTa3GLcEI2cveaP1WWNK\n' +
|
||||
'rKFnVWsjBKArKFzMQ5N6FMnFD4T96i3sYlACE5UjH90SpOgBKOpdKzSjAf9nghrw\n' +
|
||||
'kbFbF708ZIpVEwxvp/JoSutYUQ4v01MImnCGqzDVuSef3eutLLu4ZG7kLekxNauV\n' +
|
||||
'8tGFwxsdtv30RL/3nW+InwQYAQIACQUCUXqC2QIbDAAKCRA6HTM8yP08kRXjBACu\n' +
|
||||
'RtEwjU+p6qqm3pmh7xz1CzhQN1F7VOj9dFUeECJJ1iv8J71w5UINH0otIceeBeWy\n' +
|
||||
'NLA/QvK8+4/b9QW+S8aDZyeZpYg37gBwdTNGNT7TsEAxz9SUbx9uRja0wNmtb5xW\n' +
|
||||
'mG+VE8CBXNkp8JTWx05AHwtK3baWlHWwpwnRlbU94Q==\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").then(function(mipGen) {
|
||||
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;
|
||||
});
|
||||
|
||||
var mpi = [mpi.n, mpi.ee, mpi.d, mpi.p, mpi.q, mpi.u];
|
||||
key[0].mpi = mpi;
|
||||
|
||||
mpi = mpi.map(function(k) {
|
||||
var mpi = new openpgp.MPI();
|
||||
mpi.fromBigInteger(k);
|
||||
return mpi;
|
||||
});
|
||||
key[0].encrypt('hello');
|
||||
|
||||
key[0].mpi = mpi;
|
||||
var raw = key.write();
|
||||
|
||||
key[0].encrypt('hello');
|
||||
var key2 = new openpgp.packet.List();
|
||||
key2.read(raw);
|
||||
key2[0].decrypt('hello');
|
||||
|
||||
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();
|
||||
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").then(function(mpiGen) {
|
||||
var mpi = [mpiGen.n, mpiGen.ee, mpiGen.d, mpiGen.p, mpiGen.q, mpiGen.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.mpi = mpi;
|
||||
|
||||
key.mpi = mpi;
|
||||
var signed = new openpgp.packet.List(),
|
||||
literal = new openpgp.packet.Literal(),
|
||||
signature = new openpgp.packet.Signature();
|
||||
|
||||
var signed = new openpgp.packet.List(),
|
||||
literal = new openpgp.packet.Literal(),
|
||||
signature = new openpgp.packet.Signature();
|
||||
literal.setText('Hello world');
|
||||
|
||||
literal.setText('Hello world');
|
||||
signature.hashAlgorithm = 'sha256';
|
||||
signature.publicKeyAlgorithm = 'rsa_sign';
|
||||
signature.signatureType = 'binary';
|
||||
|
||||
signature.hashAlgorithm = 'sha256';
|
||||
signature.publicKeyAlgorithm = 'rsa_sign';
|
||||
signature.signatureType = 'binary';
|
||||
signature.sign(key, literal);
|
||||
|
||||
signature.sign(key, literal);
|
||||
signed.push(literal);
|
||||
signed.push(signature);
|
||||
|
||||
signed.push(literal);
|
||||
signed.push(signature);
|
||||
var raw = signed.write();
|
||||
|
||||
var raw = signed.write();
|
||||
var signed2 = new openpgp.packet.List();
|
||||
signed2.read(raw);
|
||||
|
||||
var signed2 = new openpgp.packet.List();
|
||||
signed2.read(raw);
|
||||
var verified = signed2[1].verify(key, signed2[0]);
|
||||
|
||||
var verified = signed2[1].verify(key, signed2[0]);
|
||||
|
||||
expect(verified).to.be.true;
|
||||
done();
|
||||
expect(verified).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -262,10 +262,11 @@ describe("Signature", function() {
|
|||
var pub_key = openpgp.key.readArmored(pub_key_arm1).keys[0];
|
||||
var msg = openpgp.message.readArmored(msg_arm1);
|
||||
priv_key.decrypt("abcd");
|
||||
var decrypted = openpgp.decryptAndVerifyMessage(priv_key, [pub_key], msg);
|
||||
expect(decrypted).to.exist;
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
done();
|
||||
openpgp.decryptAndVerifyMessage(priv_key, [pub_key], msg).then(function(decrypted) {
|
||||
expect(decrypted).to.exist;
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Testing GnuPG stripped-key extensions', function(done) {
|
||||
|
@ -312,7 +313,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 +336,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 +359,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)',
|
||||
'',
|
||||
|
@ -383,17 +384,17 @@ describe("Signature", function() {
|
|||
var keyids = esMsg.getEncryptionKeyIds();
|
||||
privKey.decryptKeyPacket(keyids, 'hello world');
|
||||
|
||||
var decrypted = openpgp.decryptAndVerifyMessage(privKey, [pubKey], esMsg);
|
||||
|
||||
expect(decrypted).to.exist;
|
||||
expect(decrypted.text).to.equal(plaintext);
|
||||
expect(decrypted.signatures).to.have.length(1);
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
done();
|
||||
openpgp.decryptAndVerifyMessage(privKey, [pubKey], esMsg).then(function(decrypted) {
|
||||
expect(decrypted).to.exist;
|
||||
expect(decrypted.text).to.equal(plaintext);
|
||||
expect(decrypted.signatures).to.have.length(1);
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
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',
|
||||
|
@ -419,17 +420,18 @@ describe("Signature", function() {
|
|||
var keyids = esMsg.getEncryptionKeyIds();
|
||||
privKey.decryptKeyPacket(keyids, 'hello world');
|
||||
|
||||
var decrypted = openpgp.decryptAndVerifyMessage(privKey, [pubKey], esMsg);
|
||||
openpgp.decryptAndVerifyMessage(privKey, [pubKey], esMsg).then(function(decrypted) {
|
||||
expect(decrypted).to.exist;
|
||||
expect(decrypted.text).to.equal(plaintext);
|
||||
expect(decrypted.signatures).to.have.length(1);
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
done();
|
||||
});
|
||||
|
||||
expect(decrypted).to.exist;
|
||||
expect(decrypted.text).to.equal(plaintext);
|
||||
expect(decrypted.signatures).to.have.length(1);
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
done();
|
||||
});
|
||||
|
||||
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 +472,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',
|
||||
'',
|
||||
|
@ -504,14 +506,14 @@ describe("Signature", function() {
|
|||
expect(pubKey2.getKeyPacket(keyids)).to.exist;
|
||||
expect(pubKey3.getKeyPacket(keyids)).to.exist;
|
||||
|
||||
var cleartextSig = openpgp.verifyClearSignedMessage([pubKey2, pubKey3], csMsg);
|
||||
|
||||
expect(cleartextSig).to.exist;
|
||||
expect(cleartextSig.text).to.equal(plaintext);
|
||||
expect(cleartextSig.signatures).to.have.length(2);
|
||||
expect(cleartextSig.signatures[0].valid).to.be.true;
|
||||
expect(cleartextSig.signatures[1].valid).to.be.true;
|
||||
done();
|
||||
openpgp.verifyClearSignedMessage([pubKey2, pubKey3], csMsg).then(function(cleartextSig) {
|
||||
expect(cleartextSig).to.exist;
|
||||
expect(cleartextSig.text).to.equal(plaintext);
|
||||
expect(cleartextSig.signatures).to.have.length(2);
|
||||
expect(cleartextSig.signatures[0].valid).to.be.true;
|
||||
expect(cleartextSig.signatures[1].valid).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Sign text with openpgp.signClearMessage and verify with openpgp.verifyClearSignedMessage leads to same cleartext and valid signatures', function(done) {
|
||||
|
@ -520,17 +522,19 @@ describe("Signature", function() {
|
|||
var privKey = openpgp.key.readArmored(priv_key_arm2).keys[0];
|
||||
privKey.getSigningKeyPacket().decrypt('hello world');
|
||||
|
||||
var clearSignedArmor = openpgp.signClearMessage([privKey], plaintext);
|
||||
openpgp.signClearMessage([privKey], plaintext).then(function(clearSignedArmor) {
|
||||
|
||||
var csMsg = openpgp.cleartext.readArmored(clearSignedArmor);
|
||||
|
||||
var cleartextSig = openpgp.verifyClearSignedMessage([pubKey], csMsg);
|
||||
var csMsg = openpgp.cleartext.readArmored(clearSignedArmor);
|
||||
return openpgp.verifyClearSignedMessage([pubKey], csMsg);
|
||||
|
||||
}).then(function(cleartextSig) {
|
||||
expect(cleartextSig).to.exist;
|
||||
expect(cleartextSig.text).to.equal(plaintext.replace(/\r/g,''));
|
||||
expect(cleartextSig.signatures).to.have.length(1);
|
||||
expect(cleartextSig.signatures[0].valid).to.be.true;
|
||||
done();
|
||||
});
|
||||
|
||||
expect(cleartextSig).to.exist;
|
||||
expect(cleartextSig.text).to.equal(plaintext.replace(/\r/g,''));
|
||||
expect(cleartextSig.signatures).to.have.length(1);
|
||||
expect(cleartextSig.signatures[0].valid).to.be.true;
|
||||
done();
|
||||
});
|
||||
|
||||
it('Verify primary key revocation signature', function(done) {
|
||||
|
@ -636,13 +640,17 @@ 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).then(function(gen) {
|
||||
var key = gen.key;
|
||||
|
||||
var message = openpgp.message.fromText('hello world');
|
||||
message = message.sign([key]);
|
||||
var message = openpgp.message.fromText('hello world');
|
||||
message = message.sign([key]);
|
||||
|
||||
expect(message).to.exist;
|
||||
expect(message).to.exist;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -9,12 +9,13 @@
|
|||
<body>
|
||||
<div id="mocha"></div>
|
||||
|
||||
<!--<script src="lib/jquery.min.js"></script>-->
|
||||
<!-- libs -->
|
||||
<script src="../dist/openpgp.js"></script>
|
||||
<script src="lib/chai.js"></script>
|
||||
<script src="lib/mocha.js"></script>
|
||||
<script>
|
||||
mocha.setup('bdd');
|
||||
mocha.timeout(20000);
|
||||
</script>
|
||||
<script src="lib/unittests-bundle.js"></script>
|
||||
<script>
|
||||
|
|
|
@ -184,8 +184,7 @@ describe('High level API', function() {
|
|||
describe('Encryption', function() {
|
||||
|
||||
it('RSA: encryptMessage async', function (done) {
|
||||
openpgp.encryptMessage([pubKeyRSA], plaintext, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
openpgp.encryptMessage([pubKeyRSA], plaintext).then(function(data) {
|
||||
expect(data).to.exist;
|
||||
expect(data).to.match(/^-----BEGIN PGP MESSAGE/);
|
||||
var msg = openpgp.message.readArmored(data);
|
||||
|
@ -195,8 +194,7 @@ describe('High level API', function() {
|
|||
});
|
||||
|
||||
it('RSA: encryptMessage one key async', function (done) {
|
||||
openpgp.encryptMessage(pubKeyRSA, plaintext, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
openpgp.encryptMessage(pubKeyRSA, plaintext).then(function(data) {
|
||||
expect(data).to.exist;
|
||||
expect(data).to.match(/^-----BEGIN PGP MESSAGE/);
|
||||
var msg = openpgp.message.readArmored(data);
|
||||
|
@ -205,25 +203,8 @@ describe('High level API', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('RSA: encryptMessage sync', function () {
|
||||
var msg = openpgp.encryptMessage([pubKeyRSA], plaintext);
|
||||
expect(msg).to.exist;
|
||||
expect(msg).to.match(/^-----BEGIN PGP MESSAGE/);
|
||||
msg = openpgp.message.readArmored(msg);
|
||||
expect(msg).to.be.an.instanceof(openpgp.message.Message);
|
||||
});
|
||||
|
||||
it('RSA: encryptMessage one key sync', function () {
|
||||
var msg = openpgp.encryptMessage(pubKeyRSA, plaintext);
|
||||
expect(msg).to.exist;
|
||||
expect(msg).to.match(/^-----BEGIN PGP MESSAGE/);
|
||||
msg = openpgp.message.readArmored(msg);
|
||||
expect(msg).to.be.an.instanceof(openpgp.message.Message);
|
||||
});
|
||||
|
||||
it('ELG: encryptMessage async', function (done) {
|
||||
openpgp.encryptMessage([pubKeyDE], plaintext, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
openpgp.encryptMessage([pubKeyDE], plaintext).then(function(data) {
|
||||
expect(data).to.exist;
|
||||
expect(data).to.match(/^-----BEGIN PGP MESSAGE/);
|
||||
var msg = openpgp.message.readArmored(data);
|
||||
|
@ -232,14 +213,6 @@ describe('High level API', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('ELG: encryptMessage sync', function () {
|
||||
var msg = openpgp.encryptMessage([pubKeyDE], plaintext);
|
||||
expect(msg).to.exist;
|
||||
expect(msg).to.match(/^-----BEGIN PGP MESSAGE/);
|
||||
msg = openpgp.message.readArmored(msg);
|
||||
expect(msg).to.be.an.instanceof(openpgp.message.Message);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Decryption', function() {
|
||||
|
@ -254,35 +227,21 @@ describe('High level API', function() {
|
|||
});
|
||||
|
||||
it('RSA: decryptMessage async', function (done) {
|
||||
openpgp.decryptMessage(privKeyRSA, msgRSA, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
openpgp.decryptMessage(privKeyRSA, msgRSA).then(function(data) {
|
||||
expect(data).to.exist;
|
||||
expect(data).to.equal(plaintext);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('RSA: decryptMessage sync', function () {
|
||||
var text = openpgp.decryptMessage(privKeyRSA, msgRSA);
|
||||
expect(text).to.exist;
|
||||
expect(text).to.equal(plaintext);
|
||||
});
|
||||
|
||||
it('ELG: decryptMessage async', function (done) {
|
||||
openpgp.decryptMessage(privKeyDE, msgDE, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
openpgp.decryptMessage(privKeyDE, msgDE).then(function(data) {
|
||||
expect(data).to.exist;
|
||||
expect(data).to.equal(plaintext);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('ELG: decryptMessage sync', function () {
|
||||
var text = openpgp.decryptMessage(privKeyDE, msgDE);
|
||||
expect(text).to.exist;
|
||||
expect(text).to.equal(plaintext);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function verifySignature(data, privKey) {
|
||||
|
@ -304,8 +263,7 @@ describe('High level API', function() {
|
|||
});
|
||||
|
||||
it('RSA: decryptAndVerifyMessage async', function (done) {
|
||||
openpgp.decryptAndVerifyMessage(privKeyRSA, [pubKeyRSA], msgRSA, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
openpgp.decryptAndVerifyMessage(privKeyRSA, [pubKeyRSA], msgRSA).then(function(data) {
|
||||
expect(data).to.exist;
|
||||
verifySignature(data, privKeyRSA);
|
||||
done();
|
||||
|
@ -313,8 +271,7 @@ describe('High level API', function() {
|
|||
});
|
||||
|
||||
it('ELG: decryptAndVerifyMessage async', function (done) {
|
||||
openpgp.decryptAndVerifyMessage(privKeyDE, [pubKeyDE], msgDE, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
openpgp.decryptAndVerifyMessage(privKeyDE, [pubKeyDE], msgDE).then(function(data) {
|
||||
expect(data).to.exist;
|
||||
verifySignature(data, privKeyDE);
|
||||
done();
|
||||
|
@ -330,13 +287,13 @@ describe('High level API', function() {
|
|||
});
|
||||
|
||||
it('RSA: signAndEncryptMessage async', function (done) {
|
||||
openpgp.signAndEncryptMessage([pubKeyRSA], privKeyRSA, plaintext, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
openpgp.signAndEncryptMessage([pubKeyRSA], privKeyRSA, plaintext).then(function(data) {
|
||||
expect(data).to.exist;
|
||||
expect(data).to.match(/^-----BEGIN PGP MESSAGE/);
|
||||
var msg = openpgp.message.readArmored(data);
|
||||
expect(msg).to.be.an.instanceof(openpgp.message.Message);
|
||||
var decrypted = openpgp.decryptAndVerifyMessage(privKeyRSA, [pubKeyRSA], msg);
|
||||
return openpgp.decryptAndVerifyMessage(privKeyRSA, [pubKeyRSA], msg);
|
||||
}).then(function(decrypted) {
|
||||
verifySignature(decrypted, privKeyRSA);
|
||||
done();
|
||||
});
|
||||
|
@ -352,8 +309,7 @@ describe('High level API', function() {
|
|||
});
|
||||
|
||||
it('RSA: signClearMessage async', function (done) {
|
||||
openpgp.signClearMessage([privKeyRSA], plaintext, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
openpgp.signClearMessage([privKeyRSA], plaintext).then(function(data) {
|
||||
expect(data).to.exist;
|
||||
expect(data).to.match(/-----BEGIN PGP SIGNED MESSAGE-----/);
|
||||
var msg = openpgp.message.readArmored(data);
|
||||
|
@ -363,8 +319,7 @@ describe('High level API', function() {
|
|||
});
|
||||
|
||||
it('DSA: signClearMessage async', function (done) {
|
||||
openpgp.signClearMessage([privKeyDE], plaintext, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
openpgp.signClearMessage([privKeyDE], plaintext).then(function(data) {
|
||||
expect(data).to.exist;
|
||||
expect(data).to.match(/-----BEGIN PGP SIGNED MESSAGE-----/);
|
||||
var msg = openpgp.message.readArmored(data);
|
||||
|
@ -374,10 +329,10 @@ describe('High level API', function() {
|
|||
});
|
||||
|
||||
it('RSA: verifyClearSignedMessage async', function (done) {
|
||||
var signed = openpgp.signClearMessage([privKeyRSA], plaintext);
|
||||
signed = openpgp.cleartext.readArmored(signed);
|
||||
openpgp.verifyClearSignedMessage([pubKeyRSA], signed, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
openpgp.signClearMessage([privKeyRSA], plaintext).then(function(signed) {
|
||||
signed = openpgp.cleartext.readArmored(signed);
|
||||
return openpgp.verifyClearSignedMessage([pubKeyRSA], signed);
|
||||
}).then(function(data) {
|
||||
expect(data).to.exist;
|
||||
verifySignature(data, privKeyRSA);
|
||||
done();
|
||||
|
@ -391,10 +346,8 @@ describe('High level API', function() {
|
|||
before(initKeys);
|
||||
|
||||
it('Signing with not decrypted key gives error', function (done) {
|
||||
openpgp.signClearMessage([privKeyRSA], plaintext, function(err, data) {
|
||||
expect(data).to.not.exist;
|
||||
openpgp.signClearMessage([privKeyRSA], plaintext).catch(function(err) {
|
||||
expect(err).to.exist;
|
||||
expect(err.message).to.equal('Private key is not decrypted.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -404,10 +357,8 @@ describe('High level API', function() {
|
|||
wProxy.worker = new Worker('../dist/openpgp.worker.js');
|
||||
wProxy.worker.onmessage = wProxy.onMessage.bind(wProxy);
|
||||
wProxy.seedRandom(10);
|
||||
wProxy.encryptMessage([pubKeyRSA], plaintext, function(err, data) {
|
||||
expect(data).to.not.exist;
|
||||
wProxy.encryptMessage([pubKeyRSA], plaintext).catch(function(err) {
|
||||
expect(err).to.exist;
|
||||
expect(err).to.eql(new Error('Random number buffer depleted'));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -417,8 +368,8 @@ describe('High level API', function() {
|
|||
describe('Key generation', function() {
|
||||
|
||||
it('Generate 1024-bit RSA/RSA key async', function (done) {
|
||||
openpgp.generateKeyPair({numBits: 1024, userId: 'Test McTestington <test@example.com>', passphrase: 'hello world'}, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
var opt = {numBits: 1024, userId: 'Test McTestington <test@example.com>', passphrase: 'hello world'};
|
||||
openpgp.generateKeyPair(opt).then(function(data) {
|
||||
expect(data).to.exist;
|
||||
expect(data.publicKeyArmored).to.match(/^-----BEGIN PGP PUBLIC/);
|
||||
expect(data.privateKeyArmored).to.match(/^-----BEGIN PGP PRIVATE/);
|
||||
|
@ -427,14 +378,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() {
|
||||
|
@ -450,13 +393,13 @@ describe('High level API', function() {
|
|||
it('Decrypt key', function (done) {
|
||||
expect(privKeyRSA.primaryKey.isDecrypted).to.be.false;
|
||||
expect(privKeyRSA.subKeys[0].subKey.isDecrypted).to.be.false;
|
||||
proxy.decryptKey(privKeyRSA, 'hello world', function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
proxy.decryptKey(privKeyRSA, 'hello world').then(function(data) {
|
||||
expect(data).to.exist;
|
||||
expect(data).to.be.an.instanceof(openpgp.key.Key);
|
||||
expect(data.primaryKey.isDecrypted).to.be.true;
|
||||
expect(data.subKeys[0].subKey.isDecrypted).to.be.true;
|
||||
var text = openpgp.decryptMessage(data, msg);
|
||||
return openpgp.decryptMessage(data, msg);
|
||||
}).then(function(text) {
|
||||
expect(text).to.equal(plaintext);
|
||||
done();
|
||||
});
|
||||
|
@ -466,20 +409,20 @@ describe('High level API', function() {
|
|||
expect(privKeyRSA.primaryKey.isDecrypted).to.be.false;
|
||||
expect(privKeyRSA.subKeys[0].subKey.isDecrypted).to.be.false;
|
||||
var keyid = privKeyRSA.subKeys[0].subKey.getKeyId();
|
||||
proxy.decryptKeyPacket(privKeyRSA, [keyid], 'hello world', function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
proxy.decryptKeyPacket(privKeyRSA, [keyid], 'hello world').then(function(data) {
|
||||
expect(data).to.exist;
|
||||
expect(data).to.be.an.instanceof(openpgp.key.Key);
|
||||
expect(data.primaryKey.isDecrypted).to.be.false;
|
||||
expect(data.subKeys[0].subKey.isDecrypted).to.be.true;
|
||||
var text = openpgp.decryptMessage(data, msg);
|
||||
return openpgp.decryptMessage(data, msg);
|
||||
}).then(function(text) {
|
||||
expect(text).to.equal(plaintext);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Error on wrong password decryptKey', function (done) {
|
||||
proxy.decryptKey(privKeyRSA, 'what?', function(err, data) {
|
||||
proxy.decryptKey(privKeyRSA, 'what?').catch(function(err) {
|
||||
expect(err).to.eql(new Error('Wrong password'));
|
||||
done();
|
||||
});
|
||||
|
@ -487,7 +430,7 @@ describe('High level API', function() {
|
|||
|
||||
it('Error on wrong password decryptKeyPacket', function (done) {
|
||||
var keyid = privKeyRSA.subKeys[0].subKey.getKeyId();
|
||||
proxy.decryptKeyPacket(privKeyRSA, [keyid], 'what?', function(err, data) {
|
||||
proxy.decryptKeyPacket(privKeyRSA, [keyid], 'what?').catch(function(err) {
|
||||
expect(err).to.eql(new Error('Wrong password'));
|
||||
done();
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user