From 453a9cee07a89c86330d516f93f78a4677bd2429 Mon Sep 17 00:00:00 2001 From: Tankred Hase Date: Wed, 23 Mar 2016 21:17:36 +0800 Subject: [PATCH] Use web worker for encrypt/decrypt if no native gcm --- src/crypto/gcm.js | 2 +- src/crypto/public_key/rsa.js | 2 +- src/openpgp.js | 4 ++-- src/util.js | 20 ++++++++++++++++++-- test/general/key.js | 8 ++++---- test/general/openpgp.js | 15 +++++++++------ test/general/packet.js | 6 +++--- test/general/signature.js | 2 +- 8 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/crypto/gcm.js b/src/crypto/gcm.js index d21aefa9..663dfbfd 100644 --- a/src/crypto/gcm.js +++ b/src/crypto/gcm.js @@ -25,7 +25,7 @@ import util from '../util.js'; import config from '../config'; import asmCrypto from 'asmcrypto-lite'; -const webCrypto = typeof window !== 'undefined' && window.crypto && window.crypto.subtle; // no GCM support in IE11, Safari 9 +const webCrypto = util.getWebCrypto(); // no GCM support in IE11, Safari 9 const nodeCrypto = util.getNodeCrypto(); const Buffer = util.getNodeBuffer(); diff --git a/src/crypto/public_key/rsa.js b/src/crypto/public_key/rsa.js index 0089de6e..89510f49 100644 --- a/src/crypto/public_key/rsa.js +++ b/src/crypto/public_key/rsa.js @@ -136,7 +136,7 @@ export default function RSA() { // Generate a new random private key B bits long, using public expt E function generate(B, E) { - var webCrypto = util.getWebCrypto(); + var webCrypto = util.getWebCryptoAll(); // // Native RSA keygen using Web Crypto diff --git a/src/openpgp.js b/src/openpgp.js index d5c00587..c881b959 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -99,7 +99,7 @@ export function destroyWorker() { export function generateKey({ userIds=[], passphrase, numBits=2048, unlocked=false } = {}) { const options = formatUserIds({ userIds, passphrase, numBits, unlocked }); - if (!util.getWebCrypto() && asyncProxy) { // use web worker if web crypto apis are not supported + if (!util.getWebCryptoAll() && asyncProxy) { // use web worker if web crypto apis are not supported return asyncProxy.delegate('generateKey', options); } @@ -113,7 +113,7 @@ export function generateKey({ userIds=[], passphrase, numBits=2048, unlocked=fal // js fallback already tried if (config.debug) { console.error(err); } - if (!util.getWebCrypto()) { + if (!util.getWebCryptoAll()) { throw new Error('Error generating keypair using js fallback'); } // fall back to js keygen in a worker diff --git a/src/util.js b/src/util.js index c6f4fa73..4ac04c8e 100644 --- a/src/util.js +++ b/src/util.js @@ -450,8 +450,9 @@ export default { }, /** - * Get native Web Cryptography api. The default configuration is to use - * the api when available. But it can also be deactivated with config.useNative + * Get native Web Cryptography api, only the current versioon of the spec. + * The default configuration is to use the api when available. But it can + * be deactivated with config.useNative * @return {Object} The SubtleCrypto api or 'undefined' */ getWebCrypto: function() { @@ -459,6 +460,21 @@ export default { return; } + return typeof window !== 'undefined' && window.crypto && window.crypto.subtle; + }, + + /** + * Get native Web Cryptography api for all browsers, including legacy + * implementations of the spec e.g IE11 and Safari 8/9. The default + * configuration is to use the api when available. But it can be deactivated + * with config.useNative + * @return {Object} The SubtleCrypto api or 'undefined' + */ + getWebCryptoAll: function() { + if (!config.useNative) { + return; + } + if (typeof window !== 'undefined') { if (window.crypto) { return window.crypto.subtle || window.crypto.webkitSubtle; diff --git a/test/general/key.js b/test/general/key.js index 3584ca78..f90de200 100644 --- a/test/general/key.js +++ b/test/general/key.js @@ -634,7 +634,7 @@ var pgp_desktop_priv = expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.integrity_protect ? [1] : null); // modification detection }; var opt = {numBits: 512, userIds: 'test ', passphrase: 'hello'}; - if (openpgp.util.getWebCrypto()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys openpgp.generateKey(opt).then(function(key) { testPref(key.key); testPref(openpgp.key.readArmored(key.publicKeyArmored).keys[0]); @@ -658,7 +658,7 @@ var pgp_desktop_priv = it('Generated key is not unlocked by default', function(done) { var opt = {numBits: 512, userIds: 'test ', passphrase: '123'}; - if (openpgp.util.getWebCrypto()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys var key; openpgp.generateKey(opt).then(function(newKey) { key = newKey; @@ -674,7 +674,7 @@ var pgp_desktop_priv = it('Generate key - single userid', function(done) { var userId = 'test '; var opt = {numBits: 512, userIds: userId, passphrase: '123'}; - if (openpgp.util.getWebCrypto()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys openpgp.generateKey(opt).then(function(key) { key = key.key; expect(key.users.length).to.equal(1); @@ -687,7 +687,7 @@ var pgp_desktop_priv = var userId1 = 'test '; var userId2 = 'test '; var opt = {numBits: 512, userIds: [userId1, userId2], passphrase: '123'}; - if (openpgp.util.getWebCrypto()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys openpgp.generateKey(opt).then(function(key) { key = key.key; expect(key.users.length).to.equal(2); diff --git a/test/general/openpgp.js b/test/general/openpgp.js index 3be82c67..d42cbaa9 100644 --- a/test/general/openpgp.js +++ b/test/general/openpgp.js @@ -184,7 +184,7 @@ describe('OpenPGP.js public api tests', function() { }); describe('generateKey - unit tests', function() { - var keyGenStub, keyObjStub, getWebCryptoStub; + var keyGenStub, keyObjStub, getWebCryptoAllStub; beforeEach(function() { keyObjStub = { @@ -201,13 +201,13 @@ describe('OpenPGP.js public api tests', function() { }; keyGenStub = sinon.stub(openpgp.key, 'generate'); keyGenStub.returns(resolves(keyObjStub)); - getWebCryptoStub = sinon.stub(openpgp.util, 'getWebCrypto'); + getWebCryptoAllStub = sinon.stub(openpgp.util, 'getWebCryptoAll'); }); afterEach(function() { keyGenStub.restore(); openpgp.destroyWorker(); - getWebCryptoStub.restore(); + getWebCryptoAllStub.restore(); }); it('should fail for invalid user name', function() { @@ -333,7 +333,7 @@ describe('OpenPGP.js public api tests', function() { worker: workerStub }); var proxyGenStub = sinon.stub(openpgp.getWorker(), 'delegate'); - getWebCryptoStub.returns(); + getWebCryptoAllStub.returns(); openpgp.generateKey(); expect(proxyGenStub.calledOnce).to.be.true; @@ -348,7 +348,7 @@ describe('OpenPGP.js public api tests', function() { worker: workerStub }); var proxyGenStub = sinon.stub(openpgp.getWorker(), 'delegate').returns(resolves('proxy_key')); - getWebCryptoStub.returns({}); + getWebCryptoAllStub.returns({}); keyGenStub.returns(rejects(new Error('Native webcrypto keygen failed on purpose :)'))); openpgp.generateKey().then(function(newKey) { @@ -410,7 +410,7 @@ describe('OpenPGP.js public api tests', function() { userIds: [{ name: 'Test User', email: 'text@example.com' }], numBits: 512 }; - if (openpgp.util.getWebCrypto()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys openpgp.generateKey(opt).then(function(newKey) { expect(newKey.key.getUserIds()[0]).to.equal('Test User '); @@ -461,6 +461,9 @@ describe('OpenPGP.js public api tests', function() { it('Configuration', function(done){ openpgp.config.show_version = false; openpgp.config.commentstring = 'different'; + if (openpgp.getWorker()) { // init again to trigger config event + openpgp.initWorker({ path:'../dist/openpgp.worker.js' }); + } openpgp.encrypt({ publicKeys:publicKey.keys, data:plaintext }).then(function(encrypted) { expect(encrypted.data).to.exist; expect(encrypted.data).not.to.match(/^Version:/); diff --git a/test/general/packet.js b/test/general/packet.js index 759630a2..475989ee 100644 --- a/test/general/packet.js +++ b/test/general/packet.js @@ -173,7 +173,7 @@ describe("Packet", function() { it('Public key encrypted symmetric key packet', function(done) { var rsa = new openpgp.crypto.publicKey.rsa(); - var keySize = openpgp.util.getWebCrypto() ? 2048 : 512; // webkit webcrypto accepts minimum 2048 bit keys + var keySize = openpgp.util.getWebCryptoAll() ? 2048 : 512; // webkit webcrypto accepts minimum 2048 bit keys rsa.generate(keySize, "10001").then(function(mpiGen) { @@ -437,7 +437,7 @@ describe("Packet", function() { key.push(new openpgp.packet.SecretKey()); var rsa = new openpgp.crypto.publicKey.rsa(); - var keySize = openpgp.util.getWebCrypto() ? 2048 : 512; // webkit webcrypto accepts minimum 2048 bit keys + var keySize = openpgp.util.getWebCryptoAll() ? 2048 : 512; // webkit webcrypto accepts minimum 2048 bit keys rsa.generate(keySize, "10001").then(function(mipGen) { var mpi = [mipGen.n, mipGen.ee, mipGen.d, mipGen.p, mipGen.q, mipGen.u]; @@ -466,7 +466,7 @@ describe("Packet", function() { var key = new openpgp.packet.SecretKey(); var rsa = new openpgp.crypto.publicKey.rsa(); - var keySize = openpgp.util.getWebCrypto() ? 2048 : 512; // webkit webcrypto accepts minimum 2048 bit keys + var keySize = openpgp.util.getWebCryptoAll() ? 2048 : 512; // webkit webcrypto accepts minimum 2048 bit keys rsa.generate(keySize, "10001").then(function(mpiGen) { var mpi = [mpiGen.n, mpiGen.ee, mpiGen.d, mpiGen.p, mpiGen.q, mpiGen.u]; diff --git a/test/general/signature.js b/test/general/signature.js index 397b4307..7370380e 100644 --- a/test/general/signature.js +++ b/test/general/signature.js @@ -643,7 +643,7 @@ describe("Signature", function() { it('Sign message with key without password', function(done) { var opt = {numBits: 512, userIds: { name:'test', email:'a@b.com' }, passphrase: null}; - if (openpgp.util.getWebCrypto()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys openpgp.generateKey(opt).then(function(gen) { var key = gen.key;