Merge pull request #1 from openpgpjs/master

Pull updates
This commit is contained in:
bartbutler 2015-02-27 23:52:46 -08:00
commit f0808c6e0c
19 changed files with 17014 additions and 62 deletions

2
.gitignore vendored
View File

@ -5,5 +5,7 @@ npm*
src/compression/ src/compression/
test/lib/ test/lib/
dist/ dist/
dist/*.tgz
dist/*_debug.js
openpgp.store/ openpgp.store/
doc/ doc/

View File

@ -1,5 +1,7 @@
module.exports = function(grunt) { module.exports = function(grunt) {
var version = grunt.option('release');
// Project configuration. // Project configuration.
grunt.initConfig({ grunt.initConfig({
pkg: grunt.file.readJSON('package.json'), pkg: grunt.file.readJSON('package.json'),
@ -150,6 +152,34 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-connect');
grunt.registerTask('set_version', function() {
if (!version) {
throw new Error('You must specify the version: "--release=1.0.0"');
}
patchFile({
fileName: 'package.json',
version: version
});
patchFile({
fileName: 'bower.json',
version: version
});
});
function patchFile(options) {
var fs = require('fs'),
path = './' + options.fileName,
file = require(path);
if (options.version) {
file.version = options.version;
}
fs.writeFileSync(path, JSON.stringify(file, null, 2));
}
grunt.registerTask('default', 'Build OpenPGP.js', function() { grunt.registerTask('default', 'Build OpenPGP.js', function() {
grunt.task.run(['clean', 'copy:zlib', 'browserify', 'replace', 'uglify', 'npm_pack']); grunt.task.run(['clean', 'copy:zlib', 'browserify', 'replace', 'uglify', 'npm_pack']);
//TODO jshint is not run because of too many discovered issues, once these are addressed it should autorun //TODO jshint is not run because of too many discovered issues, once these are addressed it should autorun
@ -187,6 +217,6 @@ module.exports = function(grunt) {
npm.stderr.pipe(process.stderr); npm.stderr.pipe(process.stderr);
}); });
// Test/Dev tasks // Test/Dev tasks
grunt.registerTask('test', ['copy:npm', 'mochaTest', 'mocha_phantomjs']); grunt.registerTask('test', ['copy:npm', 'mochaTest', 'mocha_phantomjs']);
}; };

View File

@ -18,7 +18,7 @@ For use in browser, install via bower:
bower install --save openpgp bower install --save openpgp
Or Fetch a minified build under [releases](https://github.com/openpgpjs/openpgpjs/releases). Or Fetch a minified build under [dist](https://github.com/openpgpjs/openpgpjs/tree/master/dist).
The library can be loaded via AMD/require.js or accessed globally via `window.openpgp`. The library can be loaded via AMD/require.js or accessed globally via `window.openpgp`.

View File

@ -1,12 +1,17 @@
{ {
"name": "openpgpjs", "name": "openpgp",
"version": "0.7.2", "version": "0.11.0",
"homepage": "http://openpgpjs.org/", "homepage": "http://openpgpjs.org/",
"authors": [ "authors": [
"OpenPGP Development Team <list@openpgpjs.org> (https://github.com/openpgpjs/openpgpjs/graphs/contributors)" "OpenPGP Development Team <list@openpgpjs.org> (https://github.com/openpgpjs/openpgpjs/graphs/contributors)"
], ],
"description": "OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.", "description": "OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.",
"main": "src/index.js", "main": [
"dist/openpgp.js",
"dist/openpgp.worker.js",
"dist/openpgp.min.js",
"dist/openpgp.worker.min.js"
],
"moduleType": [ "moduleType": [
"amd", "amd",
"es6", "es6",
@ -23,13 +28,12 @@
"license": "LGPL 3.0 or any later version", "license": "LGPL 3.0 or any later version",
"ignore": [ "ignore": [
"**/.*", "**/.*",
"dist/openpgp*.tgz", "dist/*.tgz",
"dist/*_debug.js",
"node_modules", "node_modules",
"bower_components", "bower_components",
"test", "test",
"tests", "tests",
"dist",
"doc" "doc"
] ]
} }

16599
dist/openpgp.js vendored Normal file

File diff suppressed because it is too large Load Diff

8
dist/openpgp.min.js vendored Normal file

File diff suppressed because one or more lines are too long

193
dist/openpgp.worker.js vendored Normal file
View File

@ -0,0 +1,193 @@
;(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
// 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;
var MAX_SIZE_RANDOM_BUFFER = 60000;
window.openpgp.crypto.random.randomBuffer.init(MAX_SIZE_RANDOM_BUFFER);
self.onmessage = function (event) {
var data = null,
err = null,
msg = event.data,
correct = false;
switch (msg.event) {
case 'configure':
for (var i in msg.config) {
window.openpgp.config[i] = msg.config[i];
}
break;
case 'seed-random':
if (!(msg.buf instanceof Uint8Array)) {
msg.buf = new Uint8Array(msg.buf);
}
window.openpgp.crypto.random.randomBuffer.set(msg.buf);
break;
case 'encrypt-message':
if (!msg.keys.length) {
msg.keys = [msg.keys];
}
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':
if (!msg.publicKeys.length) {
msg.publicKeys = [msg.publicKeys];
}
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':
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':
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);
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':
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':
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);
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':
window.openpgp.generateKeyPair(msg.options).then(function(data) {
data.key = data.key.toPacketlist();
response({event: 'method-return', data: data});
}).catch(function(e) {
response({event: 'method-return', err: e.message});
});
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])
;

1
dist/openpgp.worker.min.js vendored Normal file
View File

@ -0,0 +1 @@
/*! OpenPGPjs.org this is LGPL licensed code, see LICENSE/our website for more information.- v0.11.0 - 2015-02-16 */!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(){function a(a){window.openpgp.crypto.random.randomBuffer.size<d&&postMessage({event:"request-seed"}),postMessage(a)}function b(a){var b=window.openpgp.packet.List.fromStructuredClone(a);return new window.openpgp.key.Key(b)}function c(a){var b=window.openpgp.packet.List.fromStructuredClone(a);return new window.openpgp.message.Message(b)}window={},Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d&&a?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),importScripts("openpgp.min.js");var d=4e4,e=6e4;window.openpgp.crypto.random.randomBuffer.init(e),self.onmessage=function(d){var e=null,f=null,g=d.data,h=!1;switch(g.event){case"configure":for(var i in g.config)window.openpgp.config[i]=g.config[i];break;case"seed-random":g.buf instanceof Uint8Array||(g.buf=new Uint8Array(g.buf)),window.openpgp.crypto.random.randomBuffer.set(g.buf);break;case"encrypt-message":g.keys.length||(g.keys=[g.keys]),g.keys=g.keys.map(b),window.openpgp.encryptMessage(g.keys,g.text).then(function(b){a({event:"method-return",data:b})})["catch"](function(b){a({event:"method-return",err:b.message})});break;case"sign-and-encrypt-message":g.publicKeys.length||(g.publicKeys=[g.publicKeys]),g.publicKeys=g.publicKeys.map(b),g.privateKey=b(g.privateKey),window.openpgp.signAndEncryptMessage(g.publicKeys,g.privateKey,g.text).then(function(b){a({event:"method-return",data:b})})["catch"](function(b){a({event:"method-return",err:b.message})});break;case"decrypt-message":g.privateKey=b(g.privateKey),g.message=c(g.message.packets),window.openpgp.decryptMessage(g.privateKey,g.message).then(function(b){a({event:"method-return",data:b})})["catch"](function(b){a({event:"method-return",err:b.message})});break;case"decrypt-and-verify-message":g.privateKey=b(g.privateKey),g.publicKeys.length||(g.publicKeys=[g.publicKeys]),g.publicKeys=g.publicKeys.map(b),g.message=c(g.message.packets),window.openpgp.decryptAndVerifyMessage(g.privateKey,g.publicKeys,g.message).then(function(b){a({event:"method-return",data:b})})["catch"](function(b){a({event:"method-return",err:b.message})});break;case"sign-clear-message":g.privateKeys=g.privateKeys.map(b),window.openpgp.signClearMessage(g.privateKeys,g.text).then(function(b){a({event:"method-return",data:b})})["catch"](function(b){a({event:"method-return",err:b.message})});break;case"verify-clear-signed-message":g.publicKeys.length||(g.publicKeys=[g.publicKeys]),g.publicKeys=g.publicKeys.map(b);var j=window.openpgp.packet.List.fromStructuredClone(g.message.packets);g.message=new window.openpgp.cleartext.CleartextMessage(g.message.text,j),window.openpgp.verifyClearSignedMessage(g.publicKeys,g.message).then(function(b){a({event:"method-return",data:b})})["catch"](function(b){a({event:"method-return",err:b.message})});break;case"generate-key-pair":window.openpgp.generateKeyPair(g.options).then(function(b){b.key=b.key.toPacketlist(),a({event:"method-return",data:b})})["catch"](function(b){a({event:"method-return",err:b.message})});break;case"decrypt-key":try{g.privateKey=b(g.privateKey),h=g.privateKey.decrypt(g.password),h?e=g.privateKey.toPacketlist():f="Wrong password"}catch(k){f=k.message}a({event:"method-return",data:e,err:f});break;case"decrypt-key-packet":try{g.privateKey=b(g.privateKey),g.keyIds=g.keyIds.map(window.openpgp.Keyid.fromClone),h=g.privateKey.decryptKeyPacket(g.keyIds,g.password),h?e=g.privateKey.toPacketlist():f="Wrong password"}catch(k){f=k.message}a({event:"method-return",data:e,err:f});break;default:throw new Error("Unknown Worker Event.")}}},{}]},{},[1]);

View File

@ -1,7 +1,7 @@
{ {
"name": "openpgp", "name": "openpgp",
"description": "OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.", "description": "OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.",
"version": "0.9.0", "version": "0.11.0",
"homepage": "http://openpgpjs.org/", "homepage": "http://openpgpjs.org/",
"engines": { "engines": {
"node": ">=0.8" "node": ">=0.8"
@ -18,6 +18,10 @@
}, },
"files": [ "files": [
"src/", "src/",
"dist/openpgp.js",
"dist/openpgp.worker.js",
"dist/openpgp.min.js",
"dist/openpgp.worker.min.js",
"test/unittests.js", "test/unittests.js",
"test/general", "test/general",
"test/crypto" "test/crypto"

34
release.sh Executable file
View File

@ -0,0 +1,34 @@
#!/bin/sh
# abort if tests fail
set -e
# go to root
cd `dirname $0`
if [ "$#" -ne 1 ] ; then
echo 'Usage: ./release.sh 0.0.0'
exit 0
fi
# install dependencies
rm -rf node_modules/
npm install
# set version
grunt set_version --release=$1
# build and test
npm test
# Add build files to git
sed -i "" '/^dist\/$/d' .gitignore
git add dist/ *.json
git commit -m "Release new version"
git checkout .gitignore
git tag v$1
git push
git push --tag
# publish to npm
npm publish

View File

@ -37,6 +37,7 @@ module.exports = {
compression: enums.compression.zip, compression: enums.compression.zip,
integrity_protect: true, integrity_protect: true,
rsa_blinding: true, rsa_blinding: true,
useWebCrypto: true,
show_version: true, show_version: true,
show_comment: true, show_comment: true,

View File

@ -102,14 +102,18 @@ function DSA() {
function verify(hashalgo, s1, s2, m, p, q, g, y) { function verify(hashalgo, s1, s2, m, p, q, g, y) {
var hashed_data = util.getLeftNBits(hashModule.digest(hashalgo, m), q.bitLength()); var hashed_data = util.getLeftNBits(hashModule.digest(hashalgo, m), q.bitLength());
var hash = new BigInteger(util.hexstrdump(hashed_data), 16); var hash = new BigInteger(util.hexstrdump(hashed_data), 16);
if (BigInteger.ZERO.compareTo(s1) > 0 || if (BigInteger.ZERO.compareTo(s1) >= 0 ||
s1.compareTo(q) > 0 || s1.compareTo(q) >= 0 ||
BigInteger.ZERO.compareTo(s2) > 0 || BigInteger.ZERO.compareTo(s2) >= 0 ||
s2.compareTo(q) > 0) { s2.compareTo(q) >= 0) {
util.print_debug("invalid DSA Signature"); util.print_debug("invalid DSA Signature");
return null; return null;
} }
var w = s2.modInverse(q); var w = s2.modInverse(q);
if (BigInteger.ZERO.compareTo(w) == 0) {
util.print_debug("invalid DSA Signature");
return null;
}
var u1 = hash.multiply(w).mod(q); var u1 = hash.multiply(w).mod(q);
var u2 = s1.multiply(w).mod(q); var u2 = s1.multiply(w).mod(q);
return g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q); return g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);

View File

@ -135,7 +135,6 @@ function RSA() {
function generate(B, E) { function generate(B, E) {
var webCrypto = util.getWebCrypto(); var webCrypto = util.getWebCrypto();
var promise;
// //
// Native RSA keygen using Web Crypto // Native RSA keygen using Web Crypto
@ -144,22 +143,41 @@ function RSA() {
if (webCrypto) { if (webCrypto) {
var Euint32 = new Uint32Array([parseInt(E, 16)]); // get integer of exponent var Euint32 = new Uint32Array([parseInt(E, 16)]); // get integer of exponent
var Euint8 = new Uint8Array(Euint32.buffer); // get bytes of exponent var Euint8 = new Uint8Array(Euint32.buffer); // get bytes of exponent
var keyGenOpt = { var keyGenOpt;
name: 'RSASSA-PKCS1-v1_5',
modulusLength: B, // the specified keysize in bits if (window.crypto.subtle) {
publicExponent: Euint8.subarray(0, 3), // take three bytes (max 65537) // current standard spec
hash: { keyGenOpt = {
name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' name: 'RSASSA-PKCS1-v1_5',
} modulusLength: B, // the specified keysize in bits
}; publicExponent: Euint8.subarray(0, 3), // take three bytes (max 65537)
promise = webCrypto.generateKey(keyGenOpt, true, ['sign', 'verify']); hash: {
return promise.then(exportKey).then(decodeKey); name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify'
}
};
return webCrypto.generateKey(keyGenOpt, true, ['sign', 'verify']).then(exportKey).then(decodeKey);
} else if (window.crypto.webkitSubtle) {
// outdated spec implemented by Webkit
keyGenOpt = {
name: 'RSA-OAEP',
modulusLength: B, // the specified keysize in bits
publicExponent: Euint8.subarray(0, 3), // take three bytes (max 65537)
};
return webCrypto.generateKey(keyGenOpt, true, ['encrypt', 'decrypt']).then(exportKey).then(function(key) {
if (key instanceof ArrayBuffer) {
// parse raw ArrayBuffer bytes to jwk/json (WebKit/Safari quirk)
return decodeKey(JSON.parse(String.fromCharCode.apply(null, new Uint8Array(key))));
}
return decodeKey(key);
});
}
} }
function exportKey(key) { function exportKey(keypair) {
// export the generated keys as JsonWebKey (JWK) // export the generated keys as JsonWebKey (JWK)
// https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33
return webCrypto.exportKey('jwk', key.privateKey); return webCrypto.exportKey('jwk', keypair.privateKey);
} }
function decodeKey(jwk) { function decodeKey(jwk) {
@ -185,7 +203,7 @@ function RSA() {
// JS code // JS code
// //
promise = new Promise(function(resolve) { return new Promise(function(resolve) {
var key = new keyObject(); var key = new keyObject();
var rng = new SecureRandom(); var rng = new SecureRandom();
var qs = B >> 1; var qs = B >> 1;
@ -223,8 +241,6 @@ function RSA() {
resolve(key); resolve(key);
}); });
return promise;
} }
this.encrypt = encrypt; this.encrypt = encrypt;

View File

@ -46,14 +46,32 @@ if (typeof Promise === 'undefined') {
require('es6-promise').polyfill(); require('es6-promise').polyfill();
} }
var asyncProxy; // instance of the asyncproxy var asyncProxy = null; // instance of the asyncproxy
/** /**
* Set the path for the web worker script and create an instance of the async proxy * Set the path for the web worker script and create an instance of the async proxy
* @param {String} path relative path to the worker scripts * @param {String} path relative path to the worker scripts, default: 'openpgp.worker.js'
* @param {Object} [options.worker=Object] alternative to path parameter:
* web worker initialized with 'openpgp.worker.js'
* @return {Boolean} true if worker created successfully
*/ */
function initWorker(path) { function initWorker(path, options) {
asyncProxy = new AsyncProxy(path); if (options && options.worker || typeof window !== 'undefined' && window.Worker) {
options = options || {};
options.config = this.config;
asyncProxy = new AsyncProxy(path, options);
return true;
} else {
return false;
}
}
/**
* Returns a reference to the async proxy if the worker was initialized with openpgp.initWorker()
* @return {module:worker/async_proxy~AsyncProxy|null} the async proxy or null if not initialized
*/
function getWorker() {
return asyncProxy;
} }
/** /**
@ -68,7 +86,7 @@ function encryptMessage(keys, text) {
keys = [keys]; keys = [keys];
} }
if (useWorker()) { if (asyncProxy) {
return asyncProxy.encryptMessage(keys, text); return asyncProxy.encryptMessage(keys, text);
} }
@ -95,7 +113,7 @@ function signAndEncryptMessage(publicKeys, privateKey, text) {
publicKeys = [publicKeys]; publicKeys = [publicKeys];
} }
if (useWorker()) { if (asyncProxy) {
return asyncProxy.signAndEncryptMessage(publicKeys, privateKey, text); return asyncProxy.signAndEncryptMessage(publicKeys, privateKey, text);
} }
@ -119,7 +137,7 @@ function signAndEncryptMessage(publicKeys, privateKey, text) {
* @static * @static
*/ */
function decryptMessage(privateKey, msg) { function decryptMessage(privateKey, msg) {
if (useWorker()) { if (asyncProxy) {
return asyncProxy.decryptMessage(privateKey, msg); return asyncProxy.decryptMessage(privateKey, msg);
} }
@ -145,7 +163,7 @@ function decryptAndVerifyMessage(privateKey, publicKeys, msg) {
publicKeys = [publicKeys]; publicKeys = [publicKeys];
} }
if (useWorker()) { if (asyncProxy) {
return asyncProxy.decryptAndVerifyMessage(privateKey, publicKeys, msg); return asyncProxy.decryptAndVerifyMessage(privateKey, publicKeys, msg);
} }
@ -174,7 +192,7 @@ function signClearMessage(privateKeys, text) {
privateKeys = [privateKeys]; privateKeys = [privateKeys];
} }
if (useWorker()) { if (asyncProxy) {
return asyncProxy.signClearMessage(privateKeys, text); return asyncProxy.signClearMessage(privateKeys, text);
} }
@ -199,7 +217,7 @@ function verifyClearSignedMessage(publicKeys, msg) {
publicKeys = [publicKeys]; publicKeys = [publicKeys];
} }
if (useWorker()) { if (asyncProxy) {
return asyncProxy.verifyClearSignedMessage(publicKeys, msg); return asyncProxy.verifyClearSignedMessage(publicKeys, msg);
} }
@ -229,7 +247,7 @@ function verifyClearSignedMessage(publicKeys, msg) {
*/ */
function generateKeyPair(options) { function generateKeyPair(options) {
// use web worker if web crypto apis are not supported // use web worker if web crypto apis are not supported
if (!util.getWebCrypto() && useWorker()) { if (!util.getWebCrypto() && asyncProxy) {
return asyncProxy.generateKeyPair(options); return asyncProxy.generateKeyPair(options);
} }
@ -259,22 +277,6 @@ function generateKeyPair(options) {
// helper functions // helper functions
// //
/**
* Are we in a browser and do we support worker?
*/
function useWorker() {
if (typeof window === 'undefined' || !window.Worker) {
return false;
}
if (!asyncProxy) {
console.log('You need to set the worker path!');
return false;
}
return true;
}
/** /**
* Command pattern that wraps synchronous code into a promise * Command pattern that wraps synchronous code into a promise
* @param {function} cmd The synchronous function with a return value * @param {function} cmd The synchronous function with a return value
@ -307,6 +309,7 @@ function onError(message, error) {
} }
exports.initWorker = initWorker; exports.initWorker = initWorker;
exports.getWorker = getWorker;
exports.encryptMessage = encryptMessage; exports.encryptMessage = encryptMessage;
exports.signAndEncryptMessage = signAndEncryptMessage; exports.signAndEncryptMessage = signAndEncryptMessage;
exports.decryptMessage = decryptMessage; exports.decryptMessage = decryptMessage;

View File

@ -71,3 +71,9 @@ module.exports.fromClone = function (clone) {
keyid.bytes = clone.bytes; keyid.bytes = clone.bytes;
return keyid; return keyid;
}; };
module.exports.fromId = function (hex) {
var keyid = new Keyid();
keyid.read(util.hex2bin(hex));
return keyid;
};

View File

@ -320,8 +320,8 @@ module.exports = {
return; return;
} }
if (typeof window !== 'undefined' && window.crypto && window.crypto.subtle) { if (typeof window !== 'undefined' && window.crypto) {
return window.crypto.subtle; return window.crypto.subtle || window.crypto.webkitSubtle;
} }
} }
}; };

View File

@ -38,9 +38,16 @@ var INITIAL_RANDOM_SEED = 50000, // random bytes seeded to worker
* Initializes a new proxy and loads the web worker * Initializes a new proxy and loads the web worker
* @constructor * @constructor
* @param {String} path The path to the worker or 'openpgp.worker.js' by default * @param {String} path The path to the worker or 'openpgp.worker.js' by default
* @param {Object} [options.config=Object] config The worker configuration
* @param {Object} [options.worker=Object] alternative to path parameter:
* web worker initialized with 'openpgp.worker.js'
*/ */
function AsyncProxy(path) { function AsyncProxy(path, options) {
this.worker = new Worker(path || 'openpgp.worker.js'); if (options && options.worker) {
this.worker = options.worker;
} else {
this.worker = new Worker(path || 'openpgp.worker.js');
}
this.worker.onmessage = this.onMessage.bind(this); this.worker.onmessage = this.onMessage.bind(this);
this.worker.onerror = function(e) { this.worker.onerror = function(e) {
throw new Error('Unhandled error in openpgp worker: ' + e.message + ' (' + e.filename + ':' + e.lineno + ')'); throw new Error('Unhandled error in openpgp worker: ' + e.message + ' (' + e.filename + ':' + e.lineno + ')');
@ -48,6 +55,9 @@ function AsyncProxy(path) {
this.seedRandom(INITIAL_RANDOM_SEED); this.seedRandom(INITIAL_RANDOM_SEED);
// FIFO // FIFO
this.tasks = []; this.tasks = [];
if (options && options.config) {
this.worker.postMessage({event: 'configure', config: options.config});
}
} }
/** /**

View File

@ -53,6 +53,11 @@ self.onmessage = function (event) {
correct = false; correct = false;
switch (msg.event) { switch (msg.event) {
case 'configure':
for (var i in msg.config) {
window.openpgp.config[i] = msg.config[i];
}
break;
case 'seed-random': case 'seed-random':
if (!(msg.buf instanceof Uint8Array)) { if (!(msg.buf instanceof Uint8Array)) {
msg.buf = new Uint8Array(msg.buf); msg.buf = new Uint8Array(msg.buf);

View File

@ -172,6 +172,25 @@ var priv_key_de =
expect(privKeyDE).to.exist; expect(privKeyDE).to.exist;
} }
describe('Init Worker', function() {
this.timeout(0);
it('openpgp.getWorker method', function (done) {
expect(openpgp.getWorker()).to.be.null;
var workerAvailable = openpgp.initWorker('../dist/openpgp.worker.js');
expect(workerAvailable).to.be.true;
expect(openpgp.getWorker()).to.exist;
privKeyRSA = openpgp.key.readArmored(priv_key_rsa).keys[0];
expect(privKeyRSA.primaryKey.isDecrypted).to.be.false;
openpgp.getWorker().decryptKeyPacket(privKeyRSA, [privKeyRSA.primaryKey.getKeyId()], 'hello world').then(function(key) {
expect(key.primaryKey.isDecrypted).to.be.true;
done();
}).catch(done);
});
});
describe('High level API', function() { describe('High level API', function() {
this.timeout(0); this.timeout(0);
@ -181,8 +200,21 @@ describe('High level API', function() {
initKeys(); initKeys();
}); });
describe('Encryption', function() { describe('Main', function(){
it('Configuration', function(done){
openpgp.config.show_version = false;
openpgp.config.commentstring = 'different';
openpgp.initWorker('../dist/openpgp.worker.js');
openpgp.encryptMessage([pubKeyRSA], plaintext).then(function(data) {
expect(data).to.exist;
expect(data).not.to.match(/^Version:/);
expect(data).to.match(/Comment: different/);
done();
});
});
});
describe('Encryption', function() {
it('RSA: encryptMessage async', function (done) { it('RSA: encryptMessage async', function (done) {
openpgp.encryptMessage([pubKeyRSA], plaintext).then(function(data) { openpgp.encryptMessage([pubKeyRSA], plaintext).then(function(data) {
expect(data).to.exist; expect(data).to.exist;