mirror of
https://github.com/openpgpjs/openpgpjs.git
synced 2025-06-08 15:16:40 +00:00

Every submodule under the 'crypto' directory was exported-imported even if a handful of functions where actually needed. We now only export entire modules behind default exports if it makes sense for readability and if the different submodules would be imported together anyway (e.g. `cipherMode` exports are all needed by the SEIPD class). We've also dropped exports that are not used outside of the crypto modules, e.g. pkcs5 helpers.
176 lines
6.0 KiB
JavaScript
176 lines
6.0 KiB
JavaScript
// Modified by ProtonTech AG
|
|
|
|
// Adapted from https://github.com/artjomb/cryptojs-extension/blob/8c61d159/test/eax.js
|
|
import sinon from 'sinon';
|
|
import { use as chaiUse, expect } from 'chai';
|
|
import chaiAsPromised from 'chai-as-promised'; // eslint-disable-line import/newline-after-import
|
|
chaiUse(chaiAsPromised);
|
|
|
|
import openpgp from '../initOpenpgp.js';
|
|
import { cipherMode } from '../../src/crypto';
|
|
import util from '../../src/util.js';
|
|
|
|
function testAESEAX() {
|
|
it('Passes all test vectors', async function() {
|
|
const vectors = [
|
|
// From http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf ...
|
|
{
|
|
msg: '',
|
|
key: '233952DEE4D5ED5F9B9C6D6FF80FF478',
|
|
nonce: '62EC67F9C3A4A407FCB2A8C49031A8B3',
|
|
header: '6BFB914FD07EAE6B',
|
|
ct: 'E037830E8389F27B025A2D6527E79D01'
|
|
},
|
|
{
|
|
msg: 'F7FB',
|
|
key: '91945D3F4DCBEE0BF45EF52255F095A4',
|
|
nonce: 'BECAF043B0A23D843194BA972C66DEBD',
|
|
header: 'FA3BFD4806EB53FA',
|
|
ct: '19DD5C4C9331049D0BDAB0277408F67967E5'
|
|
},
|
|
{
|
|
msg: '1A47CB4933',
|
|
key: '01F74AD64077F2E704C0F60ADA3DD523',
|
|
nonce: '70C3DB4F0D26368400A10ED05D2BFF5E',
|
|
header: '234A3463C1264AC6',
|
|
ct: 'D851D5BAE03A59F238A23E39199DC9266626C40F80'
|
|
},
|
|
{
|
|
msg: '481C9E39B1',
|
|
key: 'D07CF6CBB7F313BDDE66B727AFD3C5E8',
|
|
nonce: '8408DFFF3C1A2B1292DC199E46B7D617',
|
|
header: '33CCE2EABFF5A79D',
|
|
ct: '632A9D131AD4C168A4225D8E1FF755939974A7BEDE'
|
|
},
|
|
{
|
|
msg: '40D0C07DA5E4',
|
|
key: '35B6D0580005BBC12B0587124557D2C2',
|
|
nonce: 'FDB6B06676EEDC5C61D74276E1F8E816',
|
|
header: 'AEB96EAEBE2970E9',
|
|
ct: '071DFE16C675CB0677E536F73AFE6A14B74EE49844DD'
|
|
},
|
|
{
|
|
msg: '4DE3B35C3FC039245BD1FB7D',
|
|
key: 'BD8E6E11475E60B268784C38C62FEB22',
|
|
nonce: '6EAC5C93072D8E8513F750935E46DA1B',
|
|
header: 'D4482D1CA78DCE0F',
|
|
ct: '835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F'
|
|
},
|
|
{
|
|
msg: '8B0A79306C9CE7ED99DAE4F87F8DD61636',
|
|
key: '7C77D6E813BED5AC98BAA417477A2E7D',
|
|
nonce: '1A8C98DCD73D38393B2BF1569DEEFC19',
|
|
header: '65D2017990D62528',
|
|
ct: '02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2'
|
|
},
|
|
{
|
|
msg: '1BDA122BCE8A8DBAF1877D962B8592DD2D56',
|
|
key: '5FFF20CAFAB119CA2FC73549E20F5B0D',
|
|
nonce: 'DDE59B97D722156D4D9AFF2BC7559826',
|
|
header: '54B9F04E6A09189A',
|
|
ct: '2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A'
|
|
},
|
|
{
|
|
msg: '6CF36720872B8513F6EAB1A8A44438D5EF11',
|
|
key: 'A4A4782BCFFD3EC5E7EF6D8C34A56123',
|
|
nonce: 'B781FCF2F75FA5A8DE97A9CA48E522EC',
|
|
header: '899A175897561D7E',
|
|
ct: '0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700'
|
|
},
|
|
{
|
|
msg: 'CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7',
|
|
key: '8395FCF1E95BEBD697BD010BC766AAC3',
|
|
nonce: '22E7ADD93CFC6393C57EC0B3C17D6B44',
|
|
header: '126735FCC320D25A',
|
|
ct: 'CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E'
|
|
}
|
|
];
|
|
|
|
const cipher = openpgp.enums.symmetric.aes128;
|
|
|
|
await Promise.all(vectors.map(async vec => {
|
|
const keyBytes = util.hexToUint8Array(vec.key);
|
|
const msgBytes = util.hexToUint8Array(vec.msg);
|
|
const nonceBytes = util.hexToUint8Array(vec.nonce);
|
|
const headerBytes = util.hexToUint8Array(vec.header);
|
|
const ctBytes = util.hexToUint8Array(vec.ct);
|
|
|
|
const eaxMode = cipherMode.getAEADMode(openpgp.enums.aead.eax);
|
|
const eax = await eaxMode(cipher, keyBytes);
|
|
|
|
// encryption test
|
|
let ct = await eax.encrypt(msgBytes, nonceBytes, headerBytes);
|
|
expect(util.uint8ArrayToHex(ct)).to.equal(vec.ct.toLowerCase());
|
|
|
|
// decryption test with verification
|
|
let pt = await eax.decrypt(ctBytes, nonceBytes, headerBytes);
|
|
expect(util.uint8ArrayToHex(pt)).to.equal(vec.msg.toLowerCase());
|
|
|
|
// tampering detection test
|
|
ct = await eax.encrypt(msgBytes, nonceBytes, headerBytes);
|
|
ct[2] ^= 8;
|
|
pt = eax.decrypt(ct, nonceBytes, headerBytes);
|
|
await expect(pt).to.eventually.be.rejectedWith('Authentication tag mismatch');
|
|
|
|
// testing without additional data
|
|
ct = await eax.encrypt(msgBytes, nonceBytes, new Uint8Array());
|
|
pt = await eax.decrypt(ct, nonceBytes, new Uint8Array());
|
|
expect(util.uint8ArrayToHex(pt)).to.equal(vec.msg.toLowerCase());
|
|
|
|
// testing with multiple additional data
|
|
ct = await eax.encrypt(msgBytes, nonceBytes, util.concatUint8Array([headerBytes, headerBytes, headerBytes]));
|
|
pt = await eax.decrypt(ct, nonceBytes, util.concatUint8Array([headerBytes, headerBytes, headerBytes]));
|
|
expect(util.uint8ArrayToHex(pt)).to.equal(vec.msg.toLowerCase());
|
|
}));
|
|
});
|
|
}
|
|
|
|
/* eslint-disable no-invalid-this */
|
|
export default () => describe('Symmetric AES-EAX', function() {
|
|
let sinonSandbox;
|
|
let getWebCryptoStub;
|
|
let getNodeCryptoStub;
|
|
|
|
const disableNative = () => {
|
|
enableNative();
|
|
// stubbed functions return undefined
|
|
getWebCryptoStub = sinonSandbox.stub(util, 'getWebCrypto');
|
|
getNodeCryptoStub = sinonSandbox.stub(util, 'getNodeCrypto');
|
|
};
|
|
const enableNative = () => {
|
|
getWebCryptoStub && getWebCryptoStub.restore();
|
|
getNodeCryptoStub && getNodeCryptoStub.restore();
|
|
};
|
|
|
|
describe('Symmetric AES-EAX (native)', function() {
|
|
before(function () {
|
|
const detectNative = () => !!(util.getWebCrypto() || util.getNodeCrypto());
|
|
if (!detectNative()) { this.skip(); }
|
|
});
|
|
|
|
beforeEach(function () {
|
|
sinonSandbox = sinon.createSandbox();
|
|
enableNative();
|
|
});
|
|
|
|
afterEach(function () {
|
|
sinonSandbox.restore();
|
|
});
|
|
|
|
testAESEAX();
|
|
});
|
|
|
|
describe('Symmetric AES-EAX (non-native fallback)', function() {
|
|
beforeEach(function () {
|
|
sinonSandbox = sinon.createSandbox();
|
|
disableNative();
|
|
});
|
|
|
|
afterEach(function () {
|
|
sinonSandbox.restore();
|
|
});
|
|
|
|
testAESEAX();
|
|
});
|
|
});
|