From 2e867956eb741441308009a3f7684a42dee77ae3 Mon Sep 17 00:00:00 2001 From: larabr Date: Mon, 14 Mar 2022 19:39:15 +0100 Subject: [PATCH] Fix AES encryption error in browsers for messages larger than 3MB (#1506) In browsers, encryption of messages larger than 3MB (or a custom value based on `config.minBytesForWebCrypto`) would throw the error `Error encrypting message: 'crypto.getCipher' is not a function`. The issue was introduced in v5.1 . --- src/crypto/mode/cfb.js | 4 ++-- test/crypto/crypto.js | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/crypto/mode/cfb.js b/src/crypto/mode/cfb.js index 1871bcda9..9629de4b5 100644 --- a/src/crypto/mode/cfb.js +++ b/src/crypto/mode/cfb.js @@ -23,8 +23,8 @@ */ import { AES_CFB } from '@openpgp/asmcrypto.js/dist_es8/aes/cfb'; - import * as stream from '@openpgp/web-stream-tools'; +import { getCipher } from '../crypto'; import * as cipher from '../cipher'; import util from '../../util'; import enums from '../../enums'; @@ -160,7 +160,7 @@ function xorMut(a, b) { async function webEncrypt(algo, key, pt, iv) { const ALGO = 'AES-CBC'; const _key = await webCrypto.importKey('raw', key, { name: ALGO }, false, ['encrypt']); - const { blockSize } = crypto.getCipher(algo); + const { blockSize } = getCipher(algo); const cbc_pt = util.concatUint8Array([new Uint8Array(blockSize), pt]); const ct = new Uint8Array(await webCrypto.encrypt({ name: ALGO, iv }, _key, cbc_pt)).subarray(0, pt.length); xorMut(ct, pt); diff --git a/test/crypto/crypto.js b/test/crypto/crypto.js index baeb759fb..66326eaf3 100644 --- a/test/crypto/crypto.js +++ b/test/crypto/crypto.js @@ -1,4 +1,5 @@ const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../..'); +const sandbox = require('sinon/lib/sinon/sandbox'); const crypto = require('../../src/crypto'); const util = require('../../src/util'); @@ -237,13 +238,13 @@ module.exports = () => describe('API functional testing', function() { algo => algo !== 'idea' && algo !== 'plaintext' ); - async function testCFB(plaintext) { + async function testCFB(plaintext, config = openpgp.config) { await Promise.all(symmAlgoNames.map(async function(algoName) { const algo = openpgp.enums.write(openpgp.enums.symmetric, algoName); const { blockSize } = crypto.getCipher(algo); const symmKey = await crypto.generateSessionKey(algo); const IV = new Uint8Array(blockSize); - const symmencData = await crypto.mode.cfb.encrypt(algo, symmKey, util.stringToUint8Array(plaintext), IV, openpgp.config); + const symmencData = await crypto.mode.cfb.encrypt(algo, symmKey, util.stringToUint8Array(plaintext), IV, config); const text = util.uint8ArrayToString(await crypto.mode.cfb.decrypt(algo, symmKey, symmencData, new Uint8Array(blockSize))); expect(text).to.equal(plaintext); })); @@ -253,6 +254,19 @@ module.exports = () => describe('API functional testing', function() { await testCFB('1234567'); await testCFB('foobarfoobar1234567890'); await testCFB('12345678901234567890123456789012345678901234567890'); + // test using webCrypto + const sinonSandbox = sandbox.create(); + const webCrypto = util.getWebCrypto(); + if (webCrypto) { + const webCryptoSpy = sinonSandbox.spy(webCrypto, 'encrypt'); + try { + await testCFB('12345678901234567890123456789012345678901234567890', { ...openpgp.config, minBytesForWebCrypto: 0 }); + } finally { + expect(webCryptoSpy.called).to.be.true; + sinonSandbox.restore(); + } + } + }); it('Asymmetric using RSA with eme_pkcs1 padding', async function () {