From 88a7534b8a20cc233732cb896b637ddac2f2f294 Mon Sep 17 00:00:00 2001 From: Bart Butler Date: Tue, 21 Apr 2015 16:58:11 -0700 Subject: [PATCH] Add asmCrypto, native node crypto calls for faster AES --- Gruntfile.js | 4 +- src/config/config.js | 1 + src/crypto/index.js | 6 ++- .../sym_encrypted_integrity_protected.js | 51 +++++++++++++++++-- src/type/s2k.js | 1 - test/crypto/crypto.js | 26 ++++++++++ 6 files changed, 81 insertions(+), 8 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 02f142e9..aad5d5a0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -22,7 +22,7 @@ module.exports = function(grunt) { browserifyOptions: { standalone: 'openpgp' }, - external: [ 'crypto', 'node-localstorage', 'node-fetch' ] + external: [ 'crypto', 'node-localstorage', 'node-fetch', 'buffer' ] } }, openpgp_debug: { @@ -34,7 +34,7 @@ module.exports = function(grunt) { debug: true, standalone: 'openpgp' }, - external: [ 'crypto', 'node-localstorage', 'node-fetch' ] + external: [ 'crypto', 'node-localstorage', 'node-fetch', 'buffer' ] } }, worker: { diff --git a/src/config/config.js b/src/config/config.js index 609f5674..5ff9fba4 100644 --- a/src/config/config.js +++ b/src/config/config.js @@ -41,6 +41,7 @@ module.exports = { ignore_mdc_error: false, rsa_blinding: true, useWebCrypto: true, + useNative: false, // Node crypto library for AES show_version: true, show_comment: true, diff --git a/src/crypto/index.js b/src/crypto/index.js index 88a7e0aa..075d4311 100644 --- a/src/crypto/index.js +++ b/src/crypto/index.js @@ -2,6 +2,10 @@ * @see module:crypto/crypto * @module crypto */ + +// asmCrypto global object +require('./asmcrypto-aes-cfb'); + module.exports = { /** @see module:crypto/cipher */ cipher: require('./cipher'), @@ -16,7 +20,7 @@ module.exports = { /** @see module:crypto/random */ random: require('./random.js'), /** @see module:crypto/pkcs1 */ - pkcs1: require('./pkcs1.js') + pkcs1: require('./pkcs1.js'), }; var crypto = require('./crypto.js'); diff --git a/src/packet/sym_encrypted_integrity_protected.js b/src/packet/sym_encrypted_integrity_protected.js index 0e5ec725..c9a7a1ad 100644 --- a/src/packet/sym_encrypted_integrity_protected.js +++ b/src/packet/sym_encrypted_integrity_protected.js @@ -28,6 +28,7 @@ * @requires crypto * @requires util * @requires enums + * @requires config * @module packet/sym_encrypted_integrity_protected */ @@ -35,6 +36,7 @@ module.exports = SymEncryptedIntegrityProtected; var util = require('../util.js'), crypto = require('../crypto'), + config = require('../config'), enums = require('../enums.js'); /** @@ -91,9 +93,29 @@ SymEncryptedIntegrityProtected.prototype.encrypt = function (sessionKeyAlgorithm tohash = util.concatUint8Array([tohash, hash]); - this.encrypted = crypto.cfb.encrypt(prefixrandom, - sessionKeyAlgorithm, tohash, key, false).subarray(0, - prefix.length + tohash.length); + // AES optimizations. Native code for node, asmCrypto is about 50% faster than the default, but does not support resync. + if(sessionKeyAlgorithm.substr(0,3) === 'aes') { + var blockSize = crypto.cipher[sessionKeyAlgorithm].blockSize; + // Node crypto library. Not clear that it is faster than asmCrypto + if(typeof module !== 'undefined' && module.exports && config.useNative) { + var nodeCrypto = require('crypto'); + var Buffer = require('buffer').Buffer; + var cipherObj = new nodeCrypto.createCipheriv('aes-' + sessionKeyAlgorithm.substr(3,3) + '-cfb', + new Buffer(key), new Buffer(new Uint8Array(blockSize))); + this.encrypted = new Uint8Array(cipherObj.update(new Buffer(util.concatUint8Array([prefix, tohash])))); + //var cipherObj = new nodeCrypto.createCipheriv('aes-' + sessionKeyAlgorithm.substr(3,3) + '-cfb', + // util.Uint8Array2str(key), util.Uint8Array2str(new Uint8Array(blockSize))); + //this.encrypted = new Uint8Array(cipherObj.update(util.Uint8Array2str(util.concatUint8Array([prefix, tohash])))); + } + else { + this.encrypted = asmCrypto.AES_CFB.encrypt(util.concatUint8Array([prefix, tohash]), key); + } + } + else { + this.encrypted = crypto.cfb.encrypt(prefixrandom, + sessionKeyAlgorithm, tohash, key, false).subarray(0, + prefix.length + tohash.length); + } }; /** @@ -106,8 +128,29 @@ SymEncryptedIntegrityProtected.prototype.encrypt = function (sessionKeyAlgorithm * @return {String} The decrypted data of this packet */ SymEncryptedIntegrityProtected.prototype.decrypt = function (sessionKeyAlgorithm, key) { - var decrypted = crypto.cfb.decrypt( + + var decrypted; + // AES optimizations. Native code for node, asmCrypto is about 50% faster than the default, but does not support resync. + if(sessionKeyAlgorithm.substr(0,3) === 'aes') { + var blockSize = crypto.cipher[sessionKeyAlgorithm].blockSize; + // Node crypto library. Not clear that it is faster than asmCrypto + if(typeof module !== 'undefined' && module.exports && config.useNative) { + var nodeCrypto = require('crypto'); + var Buffer = require('buffer').Buffer; + var decipherObj = new nodeCrypto.createDecipheriv('aes-' + sessionKeyAlgorithm.substr(3,3) + '-cfb', + new Buffer(key), new Buffer(new Uint8Array(blockSize))); + decrypted = new Uint8Array(decipherObj.update(new Buffer(this.encrypted))); + } + else { + decrypted = asmCrypto.AES_CFB.decrypt(this.encrypted, key); + } + // Remove random prefix + decrypted = decrypted.subarray(blockSize + 2, decrypted.length); + } + else { + decrypted = crypto.cfb.decrypt( sessionKeyAlgorithm, key, this.encrypted, false); + } // there must be a modification detection code packet as the // last packet and everything gets hashed except the hash itself diff --git a/src/type/s2k.js b/src/type/s2k.js index a84f6fad..e17c304d 100644 --- a/src/type/s2k.js +++ b/src/type/s2k.js @@ -180,7 +180,6 @@ S2K.prototype.produce_key = function (passphrase, numBytes) { var arr = [], rlength = 0, - prefix = ''; prefix = new Uint8Array(numBytes); for(var i = 0; i