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 .
This commit is contained in:
parent
d89cc48bf3
commit
2e867956eb
|
@ -23,8 +23,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { AES_CFB } from '@openpgp/asmcrypto.js/dist_es8/aes/cfb';
|
import { AES_CFB } from '@openpgp/asmcrypto.js/dist_es8/aes/cfb';
|
||||||
|
|
||||||
import * as stream from '@openpgp/web-stream-tools';
|
import * as stream from '@openpgp/web-stream-tools';
|
||||||
|
import { getCipher } from '../crypto';
|
||||||
import * as cipher from '../cipher';
|
import * as cipher from '../cipher';
|
||||||
import util from '../../util';
|
import util from '../../util';
|
||||||
import enums from '../../enums';
|
import enums from '../../enums';
|
||||||
|
@ -160,7 +160,7 @@ function xorMut(a, b) {
|
||||||
async function webEncrypt(algo, key, pt, iv) {
|
async function webEncrypt(algo, key, pt, iv) {
|
||||||
const ALGO = 'AES-CBC';
|
const ALGO = 'AES-CBC';
|
||||||
const _key = await webCrypto.importKey('raw', key, { name: ALGO }, false, ['encrypt']);
|
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 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);
|
const ct = new Uint8Array(await webCrypto.encrypt({ name: ALGO, iv }, _key, cbc_pt)).subarray(0, pt.length);
|
||||||
xorMut(ct, pt);
|
xorMut(ct, pt);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../..');
|
const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../..');
|
||||||
|
const sandbox = require('sinon/lib/sinon/sandbox');
|
||||||
const crypto = require('../../src/crypto');
|
const crypto = require('../../src/crypto');
|
||||||
const util = require('../../src/util');
|
const util = require('../../src/util');
|
||||||
|
|
||||||
|
@ -237,13 +238,13 @@ module.exports = () => describe('API functional testing', function() {
|
||||||
algo => algo !== 'idea' && algo !== 'plaintext'
|
algo => algo !== 'idea' && algo !== 'plaintext'
|
||||||
);
|
);
|
||||||
|
|
||||||
async function testCFB(plaintext) {
|
async function testCFB(plaintext, config = openpgp.config) {
|
||||||
await Promise.all(symmAlgoNames.map(async function(algoName) {
|
await Promise.all(symmAlgoNames.map(async function(algoName) {
|
||||||
const algo = openpgp.enums.write(openpgp.enums.symmetric, algoName);
|
const algo = openpgp.enums.write(openpgp.enums.symmetric, algoName);
|
||||||
const { blockSize } = crypto.getCipher(algo);
|
const { blockSize } = crypto.getCipher(algo);
|
||||||
const symmKey = await crypto.generateSessionKey(algo);
|
const symmKey = await crypto.generateSessionKey(algo);
|
||||||
const IV = new Uint8Array(blockSize);
|
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)));
|
const text = util.uint8ArrayToString(await crypto.mode.cfb.decrypt(algo, symmKey, symmencData, new Uint8Array(blockSize)));
|
||||||
expect(text).to.equal(plaintext);
|
expect(text).to.equal(plaintext);
|
||||||
}));
|
}));
|
||||||
|
@ -253,6 +254,19 @@ module.exports = () => describe('API functional testing', function() {
|
||||||
await testCFB('1234567');
|
await testCFB('1234567');
|
||||||
await testCFB('foobarfoobar1234567890');
|
await testCFB('foobarfoobar1234567890');
|
||||||
await testCFB('12345678901234567890123456789012345678901234567890');
|
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 () {
|
it('Asymmetric using RSA with eme_pkcs1 padding', async function () {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user