commit
e939d1e314
|
@ -23,6 +23,11 @@ module.exports = function(grunt) {
|
|||
external: [ 'crypto', 'node-localstorage' ]
|
||||
}
|
||||
},
|
||||
worker: {
|
||||
files: {
|
||||
'dist/openpgp.worker.js': [ './src/worker/worker.js' ]
|
||||
}
|
||||
},
|
||||
unittests: {
|
||||
files: {
|
||||
'test/lib/unittests-bundle.js': []
|
||||
|
|
|
@ -60,30 +60,41 @@ module.exports = {
|
|||
* @return {Integer} A secure random number
|
||||
*/
|
||||
getSecureRandom: function(from, to) {
|
||||
var buf = new Uint32Array(1);
|
||||
this.getRandomValues(buf);
|
||||
var randUint = this.getSecureRandomUint();
|
||||
var bits = ((to - from)).toString(2).length;
|
||||
while ((buf[0] & (Math.pow(2, bits) - 1)) > (to - from))
|
||||
this.getRandomValues(buf);
|
||||
return from + (Math.abs(buf[0] & (Math.pow(2, bits) - 1)));
|
||||
while ((randUint & (Math.pow(2, bits) - 1)) > (to - from)) {
|
||||
randUint = this.getSecureRandomUint();
|
||||
}
|
||||
return from + (Math.abs(randUint & (Math.pow(2, bits) - 1)));
|
||||
},
|
||||
|
||||
getSecureRandomOctet: function() {
|
||||
var buf = new Uint32Array(1);
|
||||
var buf = new Uint8Array(1);
|
||||
this.getRandomValues(buf);
|
||||
return buf[0] & 0xFF;
|
||||
return buf[0];
|
||||
},
|
||||
|
||||
getSecureRandomUint: function() {
|
||||
var buf = new Uint8Array(4);
|
||||
var dv = new DataView(buf.buffer);
|
||||
this.getRandomValues(buf);
|
||||
return dv.getUint32(0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper routine which calls platform specific crypto random generator
|
||||
* @param {Uint32Array} buf
|
||||
* @param {Uint8Array} buf
|
||||
*/
|
||||
getRandomValues: function(buf) {
|
||||
if (nodeCrypto === null) {
|
||||
if (typeof window !== 'undefined' && window.crypto) {
|
||||
window.crypto.getRandomValues(buf);
|
||||
} else if (nodeCrypto) {
|
||||
var bytes = nodeCrypto.randomBytes(buf.length);
|
||||
buf.set(bytes);
|
||||
} else if (this.randomBuffer.buffer) {
|
||||
this.randomBuffer.get(buf);
|
||||
} else {
|
||||
var bytes = nodeCrypto.randomBytes(4);
|
||||
buf[0] = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
|
||||
throw new Error('No secure random number generator available.');
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -122,6 +133,57 @@ module.exports = {
|
|||
r = this.getRandomBigInteger(range.bitLength());
|
||||
}
|
||||
return min.add(r);
|
||||
}
|
||||
},
|
||||
|
||||
randomBuffer: new RandomBuffer()
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Buffer for secure random numbers
|
||||
*/
|
||||
function RandomBuffer() {
|
||||
this.buffer = null;
|
||||
this.size = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize buffer
|
||||
* @param {Integer} size size of buffer
|
||||
*/
|
||||
RandomBuffer.prototype.init = function(size) {
|
||||
this.buffer = new Uint32Array(size);
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Concat array of secure random numbers to buffer
|
||||
* @param {Uint32Array} buf
|
||||
*/
|
||||
RandomBuffer.prototype.set = function(buf) {
|
||||
if (!this.buffer) {
|
||||
throw new Error('RandomBuffer is not initialized');
|
||||
}
|
||||
var freeSpace = this.buffer.length - this.size;
|
||||
if (buf.length > freeSpace) {
|
||||
buf = buf.subarray(0, freeSpace);
|
||||
}
|
||||
this.buffer.set(buf, this.size);
|
||||
this.size += buf.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Take numbers out of buffer and copy to array
|
||||
* @param {Uint32Array} buf the destination array
|
||||
*/
|
||||
RandomBuffer.prototype.get = function(buf) {
|
||||
if (!this.buffer) {
|
||||
throw new Error('RandomBuffer is not initialized');
|
||||
}
|
||||
if (this.size < buf.length) {
|
||||
throw new Error('Random number buffer depleted.')
|
||||
}
|
||||
for (var i = 0; i < buf.length; i++) {
|
||||
buf[i] = this.buffer[--this.size];
|
||||
}
|
||||
};
|
||||
|
|
|
@ -65,3 +65,8 @@ module.exports.crypto = require('./crypto');
|
|||
* @name module:openpgp.Keyring
|
||||
*/
|
||||
module.exports.Keyring = require('./keyring');
|
||||
/**
|
||||
* @see module:worker/async_proxy
|
||||
* @name module:openpgp.AsyncProxy
|
||||
*/
|
||||
module.exports.AsyncProxy = require('./worker/async_proxy.js');
|
||||
|
|
|
@ -168,6 +168,8 @@ Message.prototype.encrypt = function(keys) {
|
|||
//TODO get preferred algo from signature
|
||||
symEncryptedPacket.encrypt(enums.read(enums.symmetric, config.encryption_cipher), sessionKey);
|
||||
packetlist.push(symEncryptedPacket);
|
||||
// remove packets after encryption
|
||||
symEncryptedPacket.packets = new packet.List();
|
||||
return new Message(packetlist);
|
||||
};
|
||||
|
||||
|
|
|
@ -46,6 +46,25 @@ module.exports = {
|
|||
*/
|
||||
newPacketFromTag: function (tag) {
|
||||
return new this[packetClassFromTagName(tag)]();
|
||||
},
|
||||
/**
|
||||
* Allocate a new packet from structured packet clone
|
||||
* See {@link http://www.w3.org/html/wg/drafts/html/master/infrastructure.html#safe-passing-of-structured-data}
|
||||
* @param {Object} packetClone packet clone
|
||||
* @returns {Object} new packet object with data from packet clone
|
||||
*/
|
||||
fromStructuredClone: function(packetClone) {
|
||||
var tagName = enums.read(enums.packet, packetClone.tag)
|
||||
var packet = this.newPacketFromTag(tagName);
|
||||
for (var attr in packetClone) {
|
||||
if (packetClone.hasOwnProperty(attr)) {
|
||||
packet[attr] = packetClone[attr];
|
||||
}
|
||||
}
|
||||
if (packet.postCloneTypeFix) {
|
||||
packet.postCloneTypeFix();
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -57,10 +76,3 @@ module.exports = {
|
|||
function packetClassFromTagName(tag) {
|
||||
return tag.substr(0, 1).toUpperCase() + tag.substr(1);
|
||||
}
|
||||
|
||||
for (var i in enums.packet) {
|
||||
var packetClass = module.exports[packetClassFromTagName(i)];
|
||||
|
||||
if (packetClass !== undefined)
|
||||
packetClass.prototype.tag = enums.packet[i];
|
||||
}
|
||||
|
|
|
@ -37,6 +37,11 @@ var enums = require('../enums.js'),
|
|||
* @constructor
|
||||
*/
|
||||
function Compressed() {
|
||||
/**
|
||||
* Packet type
|
||||
* @type {module:enums.packet}
|
||||
*/
|
||||
this.tag = enums.packet.compressed;
|
||||
/**
|
||||
* List of packets
|
||||
* @type {module:packet/packetlist}
|
||||
|
|
|
@ -34,6 +34,7 @@ var util = require('../util.js'),
|
|||
* @constructor
|
||||
*/
|
||||
function Literal() {
|
||||
this.tag = enums.packet.literal;
|
||||
this.format = 'utf8'; // default format for literal data packets
|
||||
this.data = ''; // literal data representation as native JavaScript string or bytes
|
||||
this.date = new Date();
|
||||
|
|
|
@ -25,15 +25,19 @@
|
|||
* the Marker packet.<br/>
|
||||
* <br/>
|
||||
* Such a packet MUST be ignored when received.
|
||||
* @requires enums
|
||||
* @module packet/marker
|
||||
*/
|
||||
|
||||
module.exports = Marker;
|
||||
|
||||
var enums = require('../enums.js');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function Marker() {
|
||||
this.tag = enums.packet.marker;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,6 +37,7 @@ var enums = require('../enums.js'),
|
|||
* @constructor
|
||||
*/
|
||||
function OnePassSignature() {
|
||||
this.tag = enums.packet.onePassSignature; // The packet type
|
||||
this.version = null; // A one-octet version number. The current version is 3.
|
||||
this.type = null; // A one-octet signature type. Signature types are described in {@link http://tools.ietf.org/html/rfc4880#section-5.2.1|RFC4880 Section 5.2.1}.
|
||||
this.hashAlgorithm = null; // A one-octet number describing the hash algorithm used. (See {@link http://tools.ietf.org/html/rfc4880#section-9.4|RFC4880 9.4})
|
||||
|
@ -94,3 +95,10 @@ OnePassSignature.prototype.write = function () {
|
|||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fix custom types after cloning
|
||||
*/
|
||||
OnePassSignature.prototype.postCloneTypeFix = function() {
|
||||
this.signingKeyId = type_keyid.fromClone(this.signingKeyId);
|
||||
};
|
||||
|
|
|
@ -175,3 +175,22 @@ Packetlist.prototype.concat = function (packetlist) {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Allocate a new packetlist from structured packetlist clone
|
||||
* See {@link http://www.w3.org/html/wg/drafts/html/master/infrastructure.html#safe-passing-of-structured-data}
|
||||
* @param {Object} packetClone packetlist clone
|
||||
* @returns {Object} new packetlist object with data from packetlist clone
|
||||
*/
|
||||
module.exports.fromStructuredClone = function(packetlistClone) {
|
||||
var packetlist = new Packetlist();
|
||||
for (var i = 0; i < packetlistClone.length; i++) {
|
||||
packetlist.push(packets.fromStructuredClone(packetlistClone[i]));
|
||||
if (packetlist[i].packets.length !== 0) {
|
||||
packetlist[i].packets = this.fromStructuredClone(packetlist[i].packets);
|
||||
} else {
|
||||
packetlist[i].packets = new Packetlist();
|
||||
}
|
||||
}
|
||||
return packetlist;
|
||||
};
|
|
@ -42,6 +42,7 @@ var util = require('../util.js'),
|
|||
* @constructor
|
||||
*/
|
||||
function PublicKey() {
|
||||
this.tag = enums.packet.publicKey;
|
||||
this.version = 4;
|
||||
/** Key creation date.
|
||||
* @type {Date} */
|
||||
|
@ -183,3 +184,20 @@ PublicKey.prototype.getFingerprint = function () {
|
|||
return crypto.hash.md5(toHash);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns bit size of key
|
||||
* @return {int} Number of bits
|
||||
*/
|
||||
PublicKey.prototype.getBitSize = function () {
|
||||
return this.mpi[0].byteLength() * 8;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fix custom types after cloning
|
||||
*/
|
||||
PublicKey.prototype.postCloneTypeFix = function() {
|
||||
for (var i = 0; i < this.mpi.length; i++) {
|
||||
this.mpi[i] = type_mpi.fromClone(this.mpi[i]);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -49,6 +49,7 @@ var type_keyid = require('../type/keyid.js'),
|
|||
* @constructor
|
||||
*/
|
||||
function PublicKeyEncryptedSessionKey() {
|
||||
this.tag = enums.packet.publicKeyEncryptedSessionKey;
|
||||
this.version = 3;
|
||||
|
||||
this.publicKeyId = new type_keyid();
|
||||
|
@ -182,3 +183,13 @@ PublicKeyEncryptedSessionKey.prototype.decrypt = function (key) {
|
|||
enums.read(enums.symmetric, decoded.charCodeAt(0));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Fix custom types after cloning
|
||||
*/
|
||||
PublicKeyEncryptedSessionKey.prototype.postCloneTypeFix = function() {
|
||||
this.publicKeyId = type_keyid.fromClone(this.publicKeyId);
|
||||
for (var i = 0; i < this.encrypted.length; i++) {
|
||||
this.encrypted[i] = type_mpi.fromClone(this.encrypted[i]);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
|
||||
/**
|
||||
* @requires packet/public_key
|
||||
* @requires enums
|
||||
* @module packet/public_subkey
|
||||
*/
|
||||
|
||||
module.exports = PublicSubkey;
|
||||
|
||||
var publicKey = require('./public_key.js');
|
||||
var publicKey = require('./public_key.js'),
|
||||
enums = require('../enums.js');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
|
@ -30,7 +32,8 @@ var publicKey = require('./public_key.js');
|
|||
*/
|
||||
function PublicSubkey() {
|
||||
publicKey.call(this);
|
||||
};
|
||||
this.tag = enums.packet.publicSubkey;
|
||||
}
|
||||
|
||||
PublicSubkey.prototype = new publicKey();
|
||||
PublicSubkey.prototype.constructor = PublicSubkey;
|
||||
|
|
|
@ -46,6 +46,7 @@ var publicKey = require('./public_key.js'),
|
|||
*/
|
||||
function SecretKey() {
|
||||
publicKey.call(this);
|
||||
this.tag = enums.packet.secretKey;
|
||||
// encrypted secret-key data
|
||||
this.encrypted = null;
|
||||
// indicator if secret-key data is available in decrypted form
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
|
||||
/**
|
||||
* @requires packet/secret_key
|
||||
* @requires enums
|
||||
* @module packet/secret_subkey
|
||||
*/
|
||||
|
||||
module.exports = SecretSubkey;
|
||||
|
||||
var secretKey = require('./secret_key.js');
|
||||
var secretKey = require('./secret_key.js'),
|
||||
enums = require('../enums.js');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
|
@ -30,6 +32,7 @@ var secretKey = require('./secret_key.js');
|
|||
*/
|
||||
function SecretSubkey() {
|
||||
secretKey.call(this);
|
||||
this.tag = enums.packet.secretSubkey;
|
||||
}
|
||||
|
||||
SecretSubkey.prototype = new secretKey();
|
||||
|
|
|
@ -44,7 +44,7 @@ var util = require('../util.js'),
|
|||
* @constructor
|
||||
*/
|
||||
function Signature() {
|
||||
|
||||
this.tag = enums.packet.signature;
|
||||
this.version = 4;
|
||||
this.signatureType = null;
|
||||
this.hashAlgorithm = null;
|
||||
|
@ -52,7 +52,6 @@ function Signature() {
|
|||
|
||||
this.signatureData = null;
|
||||
this.signedHashValue = null;
|
||||
this.mpi = null;
|
||||
|
||||
this.created = new Date();
|
||||
this.signatureExpirationTime = null;
|
||||
|
@ -638,3 +637,10 @@ Signature.prototype.isExpired = function () {
|
|||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fix custom types after cloning
|
||||
*/
|
||||
Signature.prototype.postCloneTypeFix = function() {
|
||||
this.issuerKeyId = type_keyid.fromClone(this.issuerKeyId);
|
||||
};
|
||||
|
|
|
@ -27,18 +27,21 @@
|
|||
* packet.
|
||||
* @requires crypto
|
||||
* @requires util
|
||||
* @requires enums
|
||||
* @module packet/sym_encrypted_integrity_protected
|
||||
*/
|
||||
|
||||
module.exports = SymEncryptedIntegrityProtected;
|
||||
|
||||
var util = require('../util.js'),
|
||||
crypto = require('../crypto');
|
||||
crypto = require('../crypto'),
|
||||
enums = require('../enums.js');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function SymEncryptedIntegrityProtected() {
|
||||
this.tag = enums.packet.symEncryptedIntegrityProtected;
|
||||
/** The encrypted payload. */
|
||||
this.encrypted = null; // string
|
||||
/**
|
||||
|
|
|
@ -45,7 +45,7 @@ module.exports = SymEncryptedSessionKey;
|
|||
* @constructor
|
||||
*/
|
||||
function SymEncryptedSessionKey() {
|
||||
this.tag = 3;
|
||||
this.tag = enums.packet.symEncryptedSessionKey;
|
||||
this.sessionKeyEncryptionAlgorithm = null;
|
||||
this.sessionKeyAlgorithm = 'aes256';
|
||||
this.encrypted = null;
|
||||
|
@ -140,3 +140,10 @@ SymEncryptedSessionKey.prototype.encrypt = function(passphrase) {
|
|||
crypto.getPrefixRandom(this.sessionKeyEncryptionAlgorithm),
|
||||
this.sessionKeyEncryptionAlgorithm, key, private_key, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Fix custom types after cloning
|
||||
*/
|
||||
SymEncryptedSessionKey.prototype.postCloneTypeFix = function() {
|
||||
this.s2k = type_s2k.fromClone(this.s2k);
|
||||
};
|
||||
|
|
|
@ -24,17 +24,20 @@
|
|||
* theory other Symmetrically Encrypted Data packets or sequences of packets
|
||||
* that form whole OpenPGP messages).
|
||||
* @requires crypto
|
||||
* @requires enums
|
||||
* @module packet/symmetrically_encrypted
|
||||
*/
|
||||
|
||||
module.exports = SymmetricallyEncrypted;
|
||||
|
||||
var crypto = require('../crypto');
|
||||
var crypto = require('../crypto'),
|
||||
enums = require('../enums.js');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function SymmetricallyEncrypted() {
|
||||
this.tag = enums.packet.symmetricallyEncrypted;
|
||||
this.encrypted = null;
|
||||
/** Decrypted packets contained within.
|
||||
* @type {module:packet/packetlist} */
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
/**
|
||||
* @requires enums
|
||||
* @module packet/trust
|
||||
*/
|
||||
|
||||
module.exports = Trust;
|
||||
|
||||
var enums = require('../enums.js');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function Trust() {
|
||||
};
|
||||
this.tag = enums.packet.trust;
|
||||
}
|
||||
|
|
|
@ -32,11 +32,13 @@
|
|||
* User Attribute packet as a User ID packet with opaque contents, but
|
||||
* an implementation may use any method desired.
|
||||
* module packet/user_attribute
|
||||
* @requires enums
|
||||
* @module packet/user_attribute
|
||||
*/
|
||||
|
||||
var util = require('../util.js'),
|
||||
packet = require('./packet.js');
|
||||
packet = require('./packet.js'),
|
||||
enums = require('../enums.js');
|
||||
|
||||
module.exports = UserAttribute;
|
||||
|
||||
|
@ -44,6 +46,7 @@ module.exports = UserAttribute;
|
|||
* @constructor
|
||||
*/
|
||||
function UserAttribute() {
|
||||
this.tag = enums.packet.userAttribute;
|
||||
this.attributes = [];
|
||||
}
|
||||
|
||||
|
|
|
@ -24,17 +24,20 @@
|
|||
* restrictions on its content. The packet length in the header
|
||||
* specifies the length of the User ID.
|
||||
* @requires util
|
||||
* @requires enums
|
||||
* @module packet/userid
|
||||
*/
|
||||
|
||||
module.exports = Userid;
|
||||
|
||||
var util = require('../util.js');
|
||||
var util = require('../util.js'),
|
||||
enums = require('../enums.js');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function Userid() {
|
||||
this.tag = enums.packet.userid;
|
||||
/** A string containing the user id. Usually in the form
|
||||
* John Doe <john@example.com>
|
||||
* @type {String}
|
||||
|
|
|
@ -65,3 +65,9 @@ Keyid.prototype.isNull = function() {
|
|||
module.exports.mapToHex = function (keyId) {
|
||||
return keyId.toHex();
|
||||
};
|
||||
|
||||
module.exports.fromClone = function (clone) {
|
||||
var keyid = new Keyid();
|
||||
keyid.bytes = clone.bytes;
|
||||
return keyid;
|
||||
};
|
||||
|
|
|
@ -100,3 +100,12 @@ MPI.prototype.toBigInteger = function () {
|
|||
MPI.prototype.fromBigInteger = function (bn) {
|
||||
this.data = bn.clone();
|
||||
};
|
||||
|
||||
module.exports.fromClone = function (clone) {
|
||||
clone.data.copyTo = BigInteger.prototype.copyTo;
|
||||
var bn = new BigInteger();
|
||||
clone.data.copyTo(bn);
|
||||
var mpi = new MPI();
|
||||
mpi.data = bn;
|
||||
return mpi;
|
||||
};
|
||||
|
|
|
@ -178,3 +178,12 @@ S2K.prototype.produce_key = function (passphrase, numBytes) {
|
|||
|
||||
return result.substr(0, numBytes);
|
||||
};
|
||||
|
||||
module.exports.fromClone = function (clone) {
|
||||
var s2k = new S2K();
|
||||
this.algorithm = clone.algorithm;
|
||||
this.type = clone.type;
|
||||
this.c = clone.c;
|
||||
this.salt = clone.salt;
|
||||
return s2k;
|
||||
};
|
||||
|
|
297
src/worker/async_proxy.js
Normal file
297
src/worker/async_proxy.js
Normal file
|
@ -0,0 +1,297 @@
|
|||
// 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 2.1 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
|
||||
|
||||
/**
|
||||
* @requires crypto
|
||||
* @requires enums
|
||||
* @requires packet
|
||||
* @requires type_keyid
|
||||
* @requires key
|
||||
* @module async_proxy
|
||||
*/
|
||||
|
||||
var crypto = require('../crypto'),
|
||||
packet = require('../packet'),
|
||||
key = require('../key.js'),
|
||||
type_keyid = require('../type/keyid.js'),
|
||||
enums = require('../enums.js');
|
||||
|
||||
var INITIAL_RANDOM_SEED = 50000, // random bytes seeded to worker
|
||||
RANDOM_SEED_REQUEST = 20000; // random bytes seeded after worker request
|
||||
|
||||
/**
|
||||
* Initializes a new proxy and loads the web worker
|
||||
* @constructor
|
||||
* @param {String} path The path to the worker or 'openpgp.worker.js' by default
|
||||
*/
|
||||
function AsyncProxy(path) {
|
||||
this.worker = new Worker(path || 'openpgp.worker.js');
|
||||
this.worker.onmessage = this.onMessage.bind(this);
|
||||
this.seedRandom(INITIAL_RANDOM_SEED);
|
||||
// FIFO
|
||||
this.tasks = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Message handling
|
||||
*/
|
||||
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);
|
||||
break;
|
||||
case 'request-seed':
|
||||
this.seedRandom(RANDOM_SEED_REQUEST);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unknown Worker Event.');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Send message to worker with random data
|
||||
* @param {Integer} size Number of bytes to send
|
||||
*/
|
||||
AsyncProxy.prototype.seedRandom = function(size) {
|
||||
var buf = this.getRandomBuffer(size);
|
||||
this.worker.postMessage({event: 'seed-random', buf: buf});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get Uint8Array with random numbers
|
||||
* @param {Integer} size Length of buffer
|
||||
* @return {Uint8Array}
|
||||
*/
|
||||
AsyncProxy.prototype.getRandomBuffer = function(size) {
|
||||
if (!size) return null;
|
||||
var buf = new Uint8Array(size);
|
||||
crypto.random.getRandomValues(buf);
|
||||
return buf;
|
||||
};
|
||||
|
||||
/**
|
||||
* Terminates the worker
|
||||
*/
|
||||
AsyncProxy.prototype.terminate = function() {
|
||||
this.worker.terminate();
|
||||
};
|
||||
|
||||
/**
|
||||
* Encrypts message text with keys
|
||||
* @param {Array<module:key~Key>} keys array of keys, 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) {
|
||||
keys = keys.map(function(key) {
|
||||
return key.toPacketlist();
|
||||
});
|
||||
this.worker.postMessage({
|
||||
event: 'encrypt-message',
|
||||
keys: keys,
|
||||
text: text
|
||||
});
|
||||
this.tasks.push(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Signs message text and encrypts it
|
||||
* @param {Array<module:key~Key>} publicKeys array of keys, 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) {
|
||||
publicKeys = publicKeys.map(function(key) {
|
||||
return key.toPacketlist();
|
||||
});
|
||||
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
|
||||
});
|
||||
this.tasks.push(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypts message and verifies signatures
|
||||
* @param {module:key~Key} privateKey private key with decrypted secret key data
|
||||
* @param {Array<module:key~Key>} publicKeys public keys 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();
|
||||
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) {
|
||||
data.signatures = data.signatures.map(function(sig) {
|
||||
sig.keyid = type_keyid.fromClone(sig.keyid);
|
||||
return sig;
|
||||
});
|
||||
}
|
||||
callback(err, data);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Signs a cleartext message
|
||||
* @param {Array<module:key~Key>} privateKeys private 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) {
|
||||
privateKeys = privateKeys.map(function(key) {
|
||||
return key.toPacketlist();
|
||||
});
|
||||
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>} publicKeys public keys 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) {
|
||||
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) {
|
||||
data.signatures = data.signatures.map(function(sig) {
|
||||
sig.keyid = type_keyid.fromClone(sig.keyid);
|
||||
return sig;
|
||||
});
|
||||
}
|
||||
callback(err, data);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a new OpenPGP key pair. Currently only supports RSA keys.
|
||||
* Primary and subkey will be of same type.
|
||||
* @param {module:enums.publicKey} keyType to indicate what type of key to make.
|
||||
* RSA is 1. See {@link http://tools.ietf.org/html/rfc4880#section-9.1}
|
||||
* @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(keyType, numBits, userId, passphrase, callback) {
|
||||
this.worker.postMessage({
|
||||
event: 'generate-key-pair',
|
||||
keyType: keyType,
|
||||
numBits: numBits,
|
||||
userId: userId,
|
||||
passphrase: passphrase
|
||||
});
|
||||
this.tasks.push(function(err, data) {
|
||||
if (data) {
|
||||
var packetlist = packet.List.fromStructuredClone(data.key);
|
||||
data.key = new key.Key(packetlist);
|
||||
}
|
||||
callback(err, data);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
var packetlist = packet.List.fromStructuredClone(data);
|
||||
data = new key.Key(packetlist);
|
||||
}
|
||||
callback(err, data);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypts secret part of key packets matching array of keyids.
|
||||
* @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) {
|
||||
var packetlist = packet.List.fromStructuredClone(data);
|
||||
data = new key.Key(packetlist);
|
||||
}
|
||||
callback(err, data);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = AsyncProxy;
|
154
src/worker/worker.js
Normal file
154
src/worker/worker.js
Normal file
|
@ -0,0 +1,154 @@
|
|||
// 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 2.1 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
|
||||
|
||||
importScripts('openpgp.js');
|
||||
|
||||
var MIN_SIZE_RANDOM_BUFFER = 40000;
|
||||
var MAX_SIZE_RANDOM_BUFFER = 60000;
|
||||
|
||||
window.openpgp.crypto.random.randomBuffer.init(MAX_SIZE_RANDOM_BUFFER);
|
||||
|
||||
onmessage = function (event) {
|
||||
var data = null,
|
||||
err = null,
|
||||
msg = event.data,
|
||||
correct = false;
|
||||
switch (msg.event) {
|
||||
case 'seed-random':
|
||||
window.openpgp.crypto.random.randomBuffer.set(msg.buf);
|
||||
break;
|
||||
case 'encrypt-message':
|
||||
try {
|
||||
msg.keys = msg.keys.map(packetlistCloneToKey);
|
||||
data = window.openpgp.encryptMessage(msg.keys, msg.text);
|
||||
} catch (e) {
|
||||
err = e.message;
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
break;
|
||||
case 'sign-and-encrypt-message':
|
||||
try {
|
||||
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;
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
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});
|
||||
break;
|
||||
case 'decrypt-and-verify-message':
|
||||
try {
|
||||
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
||||
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;
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
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});
|
||||
break;
|
||||
case 'verify-clear-signed-message':
|
||||
try {
|
||||
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;
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
break;
|
||||
case 'generate-key-pair':
|
||||
try {
|
||||
data = window.openpgp.generateKeyPair(msg.keyType, msg.numBits, msg.userId, msg.passphrase);
|
||||
data.key = data.key.toPacketlist();
|
||||
} catch (e) {
|
||||
err = e.message;
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
break;
|
||||
case 'decrypt-key':
|
||||
try {
|
||||
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
||||
correct = msg.privateKey.decrypt(msg.password);
|
||||
if (correct) {
|
||||
data = msg.privateKey.toPacketlist();
|
||||
} else {
|
||||
err = 'Wrong password';
|
||||
}
|
||||
} catch (e) {
|
||||
err = e.message;
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
break;
|
||||
case 'decrypt-key-packet':
|
||||
try {
|
||||
msg.privateKey = packetlistCloneToKey(msg.privateKey);
|
||||
msg.keyIds = msg.keyIds.map(window.openpgp.Keyid.fromClone);
|
||||
correct = msg.privateKey.decryptKeyPacket(msg.keyIds, msg.password);
|
||||
if (correct) {
|
||||
data = msg.privateKey.toPacketlist();
|
||||
} else {
|
||||
err = 'Wrong password';
|
||||
}
|
||||
} catch (e) {
|
||||
err = e.message;
|
||||
}
|
||||
response({event: 'method-return', data: data, err: err});
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unknown Worker Event.');
|
||||
}
|
||||
};
|
||||
|
||||
function response(event) {
|
||||
if (window.openpgp.crypto.random.randomBuffer.size < MIN_SIZE_RANDOM_BUFFER) {
|
||||
postMessage({event: 'request-seed'});
|
||||
}
|
||||
postMessage(event);
|
||||
}
|
||||
|
||||
function packetlistCloneToKey(packetlistClone) {
|
||||
var packetlist = window.openpgp.packet.List.fromStructuredClone(packetlistClone);
|
||||
return new window.openpgp.key.Key(packetlist);
|
||||
}
|
||||
|
||||
function packetlistCloneToMessage(packetlistClone) {
|
||||
var packetlist = window.openpgp.packet.List.fromStructuredClone(packetlistClone);
|
||||
return new window.openpgp.message.Message(packetlist);
|
||||
}
|
|
@ -1,4 +1,7 @@
|
|||
describe('Unit Tests', function () {
|
||||
require('./general');
|
||||
require('./crypto');
|
||||
if (typeof window !== 'undefined') {
|
||||
require('./worker');
|
||||
}
|
||||
});
|
||||
|
|
554
test/worker/api.js
Normal file
554
test/worker/api.js
Normal file
|
@ -0,0 +1,554 @@
|
|||
'use strict';
|
||||
|
||||
var openpgp = typeof window != 'undefined' && window.openpgp ? window.openpgp : require('../../src/index');
|
||||
|
||||
var chai = require('chai'),
|
||||
expect = chai.expect;
|
||||
|
||||
|
||||
var pub_key_rsa =
|
||||
['-----BEGIN PGP PUBLIC KEY BLOCK-----',
|
||||
'Version: GnuPG v2.0.19 (GNU/Linux)',
|
||||
'Type: RSA/RSA',
|
||||
'',
|
||||
'mI0EUmEvTgEEANyWtQQMOybQ9JltDqmaX0WnNPJeLILIM36sw6zL0nfTQ5zXSS3+',
|
||||
'fIF6P29lJFxpblWk02PSID5zX/DYU9/zjM2xPO8Oa4xo0cVTOTLj++Ri5mtr//f5',
|
||||
'GLsIXxFrBJhD/ghFsL3Op0GXOeLJ9A5bsOn8th7x6JucNKuaRB6bQbSPABEBAAG0',
|
||||
'JFRlc3QgTWNUZXN0aW5ndG9uIDx0ZXN0QGV4YW1wbGUuY29tPoi5BBMBAgAjBQJS',
|
||||
'YS9OAhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQSmNhOk1uQJQwDAP6',
|
||||
'AgrTyqkRlJVqz2pb46TfbDM2TDF7o9CBnBzIGoxBhlRwpqALz7z2kxBDmwpQa+ki',
|
||||
'Bq3jZN/UosY9y8bhwMAlnrDY9jP1gdCo+H0sD48CdXybblNwaYpwqC8VSpDdTndf',
|
||||
'9j2wE/weihGp/DAdy/2kyBCaiOY1sjhUfJ1GogF49rC4jQRSYS9OAQQA6R/PtBFa',
|
||||
'JaT4jq10yqASk4sqwVMsc6HcifM5lSdxzExFP74naUMMyEsKHP53QxTF0Grqusag',
|
||||
'Qg/ZtgT0CN1HUM152y7ACOdp1giKjpMzOTQClqCoclyvWOFB+L/SwGEIJf7LSCEr',
|
||||
'woBuJifJc8xAVr0XX0JthoW+uP91eTQ3XpsAEQEAAYkBPQQYAQIACQUCUmEvTgIb',
|
||||
'LgCoCRBKY2E6TW5AlJ0gBBkBAgAGBQJSYS9OAAoJEOCE90RsICyXuqIEANmmiRCA',
|
||||
'SF7YK7PvFkieJNwzeK0V3F2lGX+uu6Y3Q/Zxdtwc4xR+me/CSBmsURyXTO29OWhP',
|
||||
'GLszPH9zSJU9BdDi6v0yNprmFPX/1Ng0Abn/sCkwetvjxC1YIvTLFwtUL/7v6NS2',
|
||||
'bZpsUxRTg9+cSrMWWSNjiY9qUKajm1tuzPDZXAUEAMNmAN3xXN/Kjyvj2OK2ck0X',
|
||||
'W748sl/tc3qiKPMJ+0AkMF7Pjhmh9nxqE9+QCEl7qinFqqBLjuzgUhBU4QlwX1GD',
|
||||
'AtNTq6ihLMD5v1d82ZC7tNatdlDMGWnIdvEMCv2GZcuIqDQ9rXWs49e7tq1NncLY',
|
||||
'hz3tYjKhoFTKEIq3y3Pp',
|
||||
'=h/aX',
|
||||
'-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
|
||||
|
||||
var priv_key_rsa =
|
||||
['-----BEGIN PGP PRIVATE KEY BLOCK-----',
|
||||
'Version: GnuPG v2.0.19 (GNU/Linux)',
|
||||
'Type: RSA/RSA 1024',
|
||||
'Pwd: hello world',
|
||||
'',
|
||||
'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',
|
||||
'=lw5e',
|
||||
'-----END PGP PRIVATE KEY BLOCK-----'].join('\n');
|
||||
|
||||
var pub_key_de =
|
||||
['-----BEGIN PGP PUBLIC KEY BLOCK-----',
|
||||
'Version: GnuPG v2.0.22 (GNU/Linux)',
|
||||
'',
|
||||
'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',
|
||||
'og2umGfGng==',
|
||||
'=v3+L',
|
||||
'-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
|
||||
|
||||
var priv_key_de =
|
||||
['-----BEGIN PGP PRIVATE KEY BLOCK-----',
|
||||
'Version: GnuPG v2.0.22 (GNU/Linux)',
|
||||
'',
|
||||
'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',
|
||||
'DHTORVqAOdoOcu5Qh7AQg1GdSmfFAsx2',
|
||||
'=kyeP',
|
||||
'-----END PGP PRIVATE KEY BLOCK-----'].join('\n');
|
||||
|
||||
|
||||
var plaintext = 'short message\nnext line\n한국어/조선말';
|
||||
|
||||
var pubKeyRSA, privKeyRSA, pubKeyDE, privKeyDE;
|
||||
|
||||
function initKeys() {
|
||||
pubKeyRSA = openpgp.key.readArmored(pub_key_rsa).keys[0];
|
||||
expect(pubKeyRSA).to.exist;
|
||||
privKeyRSA = openpgp.key.readArmored(priv_key_rsa).keys[0];
|
||||
expect(privKeyRSA).to.exist;
|
||||
pubKeyDE = openpgp.key.readArmored(pub_key_de).keys[0];
|
||||
expect(pubKeyDE).to.exist;
|
||||
privKeyDE = openpgp.key.readArmored(priv_key_de).keys[0];
|
||||
expect(privKeyDE).to.exist;
|
||||
}
|
||||
|
||||
describe('High level API', function() {
|
||||
|
||||
var proxy;
|
||||
|
||||
this.timeout(0);
|
||||
|
||||
before(function() {
|
||||
proxy = new openpgp.AsyncProxy('../dist/openpgp.worker.js');
|
||||
expect(proxy).to.exist;
|
||||
initKeys();
|
||||
});
|
||||
|
||||
describe('Encryption', function() {
|
||||
|
||||
it('RSA: encryptMessage async', function (done) {
|
||||
proxy.encryptMessage([pubKeyRSA], plaintext, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
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);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
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('ELG: encryptMessage async', function (done) {
|
||||
proxy.encryptMessage([pubKeyDE], plaintext, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
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);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
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() {
|
||||
|
||||
var msgRSA, msgDE;
|
||||
|
||||
before(function() {
|
||||
privKeyRSA.decrypt('hello world');
|
||||
privKeyDE.decrypt('hello world');
|
||||
msgRSA = openpgp.message.fromText(plaintext).encrypt([pubKeyRSA]);
|
||||
msgDE = openpgp.message.fromText(plaintext).encrypt([pubKeyDE]);
|
||||
});
|
||||
|
||||
it('RSA: decryptMessage async', function (done) {
|
||||
proxy.decryptMessage(privKeyRSA, msgRSA, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
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) {
|
||||
proxy.decryptMessage(privKeyDE, msgDE, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
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) {
|
||||
expect(data.text).to.equal(plaintext);
|
||||
expect(data.signatures).to.have.length(1);
|
||||
expect(data.signatures[0].valid).to.be.true;
|
||||
expect(data.signatures[0].keyid.equals(privKey.getSigningKeyPacket().getKeyId())).to.be.true;
|
||||
}
|
||||
|
||||
describe('Decrypt and Verify', function() {
|
||||
|
||||
var msgRSA, msgDE;
|
||||
|
||||
before(function() {
|
||||
privKeyRSA.decrypt('hello world');
|
||||
privKeyDE.decrypt('hello world');
|
||||
msgRSA = openpgp.message.fromText(plaintext).sign([privKeyRSA]).encrypt([pubKeyRSA]);
|
||||
msgDE = openpgp.message.fromText(plaintext).sign([privKeyDE]).encrypt([pubKeyDE]);
|
||||
});
|
||||
|
||||
it('RSA: decryptAndVerifyMessage async', function (done) {
|
||||
proxy.decryptAndVerifyMessage(privKeyRSA, [pubKeyRSA], msgRSA, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
expect(data).to.exist;
|
||||
verifySignature(data, privKeyRSA);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('ELG: decryptAndVerifyMessage async', function (done) {
|
||||
proxy.decryptAndVerifyMessage(privKeyDE, [pubKeyDE], msgDE, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
expect(data).to.exist;
|
||||
verifySignature(data, privKeyDE);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Sign and Encrypt', function() {
|
||||
|
||||
before(function() {
|
||||
privKeyRSA.decrypt('hello world');
|
||||
});
|
||||
|
||||
it('RSA: signAndEncryptMessage async', function (done) {
|
||||
proxy.signAndEncryptMessage([pubKeyRSA], privKeyRSA, plaintext, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
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);
|
||||
verifySignature(decrypted, privKeyRSA);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Signing', function() {
|
||||
|
||||
before(function() {
|
||||
privKeyRSA.decrypt('hello world');
|
||||
privKeyDE.decrypt('hello world');
|
||||
});
|
||||
|
||||
it('RSA: signClearMessage async', function (done) {
|
||||
proxy.signClearMessage([privKeyRSA], plaintext, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
expect(data).to.exist;
|
||||
expect(data).to.match(/-----BEGIN PGP SIGNED MESSAGE-----/);
|
||||
var msg = openpgp.message.readArmored(data);
|
||||
expect(msg).to.be.an.instanceof(openpgp.message.Message);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('DSA: signClearMessage async', function (done) {
|
||||
proxy.signClearMessage([privKeyDE], plaintext, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
expect(data).to.exist;
|
||||
expect(data).to.match(/-----BEGIN PGP SIGNED MESSAGE-----/);
|
||||
var msg = openpgp.message.readArmored(data);
|
||||
expect(msg).to.be.an.instanceof(openpgp.message.Message);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('RSA: verifyClearSignedMessage async', function (done) {
|
||||
var signed = openpgp.signClearMessage([privKeyRSA], plaintext);
|
||||
signed = openpgp.cleartext.readArmored(signed);
|
||||
proxy.verifyClearSignedMessage([pubKeyRSA], signed, function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
expect(data).to.exist;
|
||||
verifySignature(data, privKeyRSA);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Error handling', function() {
|
||||
|
||||
before(initKeys);
|
||||
|
||||
it('Signing with not decrypted key gives error', function (done) {
|
||||
proxy.signClearMessage([privKeyRSA], plaintext, function(err, data) {
|
||||
expect(data).to.not.exist;
|
||||
expect(err).to.exist;
|
||||
expect(err.message).to.equal('Private key is not decrypted.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Depleted random buffer in worker gives error', function (done) {
|
||||
var wProxy = new openpgp.AsyncProxy('../dist/openpgp.worker.js');
|
||||
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;
|
||||
expect(err).to.exist;
|
||||
expect(err).to.eql(new Error('Random number buffer depleted.'));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Key generation', function() {
|
||||
|
||||
it('Generate 1024-bit RSA/RSA key async', function (done) {
|
||||
proxy.generateKeyPair(3, 1024, 'Test McTestington <test@example.com>', 'hello world', function(err, data) {
|
||||
expect(err).to.not.exist;
|
||||
expect(data).to.exist;
|
||||
expect(data.publicKeyArmored).to.match(/^-----BEGIN PGP PUBLIC/);
|
||||
expect(data.privateKeyArmored).to.match(/^-----BEGIN PGP PRIVATE/);
|
||||
expect(data.key).to.be.an.instanceof(openpgp.key.Key);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Generate 1024-bit RSA/RSA key sync', function () {
|
||||
var key = openpgp.generateKeyPair(3, 1024, 'Test McTestington <test@example.com>', '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() {
|
||||
|
||||
var msg;
|
||||
|
||||
beforeEach(function() {
|
||||
initKeys();
|
||||
msg = openpgp.message.fromText(plaintext).encrypt([pubKeyRSA]);
|
||||
});
|
||||
|
||||
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;
|
||||
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);
|
||||
expect(text).to.equal(plaintext);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Decrypt key packet', function (done) {
|
||||
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;
|
||||
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);
|
||||
expect(text).to.equal(plaintext);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Error on wrong password decryptKey', function (done) {
|
||||
proxy.decryptKey(privKeyRSA, 'what?', function(err, data) {
|
||||
expect(err).to.eql(new Error('Wrong password'));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Error on wrong password decryptKeyPacket', function (done) {
|
||||
var keyid = privKeyRSA.subKeys[0].subKey.getKeyId();
|
||||
proxy.decryptKeyPacket(privKeyRSA, [keyid], 'what?', function(err, data) {
|
||||
expect(err).to.eql(new Error('Wrong password'));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Random Buffer', function() {
|
||||
|
||||
var randomBuffer;
|
||||
|
||||
before(function() {
|
||||
randomBuffer = new openpgp.crypto.random.randomBuffer.constructor();
|
||||
expect(randomBuffer).to.exist;
|
||||
});
|
||||
|
||||
it('Throw error if not initialized', function () {
|
||||
expect(randomBuffer.set).to.throw('RandomBuffer is not initialized');
|
||||
expect(randomBuffer.get).to.throw('RandomBuffer is not initialized');
|
||||
});
|
||||
|
||||
it('Initialization', function () {
|
||||
randomBuffer.init(5);
|
||||
expect(randomBuffer.buffer).to.exist;
|
||||
expect(randomBuffer.buffer).to.have.length(5);
|
||||
expect(randomBuffer.size).to.equal(0);
|
||||
});
|
||||
|
||||
function equal(buf, arr) {
|
||||
for (var i = 0; i < buf.length; i++) {
|
||||
if (buf[i] !== arr[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
it('Set Method', function () {
|
||||
randomBuffer.init(5);
|
||||
var buf = new Uint32Array(2);
|
||||
buf[0] = 1; buf[1] = 2;
|
||||
randomBuffer.set(buf);
|
||||
expect(equal(randomBuffer.buffer, [1,2,0,0,0])).to.be.true;
|
||||
expect(randomBuffer.size).to.equal(2);
|
||||
randomBuffer.set(buf);
|
||||
expect(equal(randomBuffer.buffer, [1,2,1,2,0])).to.be.true;
|
||||
expect(randomBuffer.size).to.equal(4);
|
||||
randomBuffer.set(buf);
|
||||
expect(equal(randomBuffer.buffer, [1,2,1,2,1])).to.be.true;
|
||||
expect(randomBuffer.size).to.equal(5);
|
||||
randomBuffer.init(1);
|
||||
var buf = new Uint32Array(2);
|
||||
buf[0] = 1; buf[1] = 2;
|
||||
randomBuffer.set(buf);
|
||||
expect(buf).to.to.have.property('0', 1);
|
||||
expect(randomBuffer.size).to.equal(1);
|
||||
});
|
||||
|
||||
it('Get Method', function () {
|
||||
randomBuffer.init(5);
|
||||
var buf = new Uint32Array(5);
|
||||
buf[0] = 1; buf[1] = 2; buf[2] = 5; buf[3] = 7; buf[4] = 8;
|
||||
randomBuffer.set(buf);
|
||||
var buf = new Uint32Array(2);
|
||||
randomBuffer.get(buf);
|
||||
expect(equal(randomBuffer.buffer, [1,2,5,7,8])).to.be.true;
|
||||
expect(randomBuffer.size).to.equal(3);
|
||||
expect(buf).to.to.have.property('0', 8);
|
||||
expect(buf).to.to.have.property('1', 7);
|
||||
expect(equal(randomBuffer.buffer, [1,2,5,7,8])).to.be.true;
|
||||
randomBuffer.get(buf);
|
||||
expect(buf).to.to.have.property('0', 5);
|
||||
expect(buf).to.to.have.property('1', 2);
|
||||
expect(randomBuffer.size).to.equal(1);
|
||||
expect(function() { randomBuffer.get(buf) }).to.throw('Random number buffer depleted.');
|
||||
});
|
||||
|
||||
});
|
4
test/worker/index.js
Normal file
4
test/worker/index.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
describe('Web Worker', function () {
|
||||
require('./api.js');
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user