larabr 2a8969b437 Internal: improve tree-shaking for crypto modules
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.
2024-11-22 14:32:39 +01:00

187 lines
7.2 KiB
JavaScript

// Modified by ProtonTech AG
// Adapted from https://github.com/artjomb/cryptojs-extension/blob/8c61d159/test/eax.js
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';
export default () => describe('Symmetric AES-OCB', function() {
it('Passes all test vectors', async function() {
const K = '000102030405060708090A0B0C0D0E0F';
const keyBytes = util.hexToUint8Array(K);
const vectors = [
// From https://tools.ietf.org/html/rfc7253#appendix-A
{
N: 'BBAA99887766554433221100',
A: '',
P: '',
C: '785407BFFFC8AD9EDCC5520AC9111EE6'
},
{
N: 'BBAA99887766554433221101',
A: '0001020304050607',
P: '0001020304050607',
C: '6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009'
},
{
N: 'BBAA99887766554433221102',
A: '0001020304050607',
P: '',
C: '81017F8203F081277152FADE694A0A00'
},
{
N: 'BBAA99887766554433221103',
A: '',
P: '0001020304050607',
C: '45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9'
},
{
N: 'BBAA99887766554433221104',
A: '000102030405060708090A0B0C0D0E0F',
P: '000102030405060708090A0B0C0D0E0F',
C: '571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358'
},
{
N: 'BBAA99887766554433221105',
A: '000102030405060708090A0B0C0D0E0F',
P: '',
C: '8CF761B6902EF764462AD86498CA6B97'
},
{
N: 'BBAA99887766554433221106',
A: '',
P: '000102030405060708090A0B0C0D0E0F',
C: '5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436BDF06D8FA1ECA343D'
},
{
N: 'BBAA99887766554433221107',
A: '000102030405060708090A0B0C0D0E0F1011121314151617',
P: '000102030405060708090A0B0C0D0E0F1011121314151617',
C: '1CA2207308C87C010756104D8840CE1952F09673A448A122C92C62241051F57356D7F3C90BB0E07F'
},
{
N: 'BBAA99887766554433221108',
A: '000102030405060708090A0B0C0D0E0F1011121314151617',
P: '',
C: '6DC225A071FC1B9F7C69F93B0F1E10DE'
},
{
N: 'BBAA99887766554433221109',
A: '',
P: '000102030405060708090A0B0C0D0E0F1011121314151617',
C: '221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3CE725F32494B9F914D85C0B1EB38357FF'
},
{
N: 'BBAA9988776655443322110A',
A: '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F',
P: '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F',
C: 'BD6F6C496201C69296C11EFD138A467ABD3C707924B964DEAFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240'
},
{
N: 'BBAA9988776655443322110B',
A: '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F',
P: '',
C: 'FE80690BEE8A485D11F32965BC9D2A32'
},
{
N: 'BBAA9988776655443322110C',
A: '',
P: '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F',
C: '2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF46040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF'
},
{
N: 'BBAA9988776655443322110D',
A: '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627',
P: '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627',
C: 'D5CA91748410C1751FF8A2F618255B68A0A12E093FF454606E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483A7035490C5769E60'
},
{
N: 'BBAA9988776655443322110E',
A: '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627',
P: '',
C: 'C5CD9D1850C141E358649994EE701B68'
},
{
N: 'BBAA9988776655443322110F',
A: '',
P: '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627',
C: '4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95A98CA5F3000B1479'
}
];
const cipher = openpgp.enums.symmetric.aes128;
await Promise.all(vectors.map(async vec => {
const msgBytes = util.hexToUint8Array(vec.P);
const nonceBytes = util.hexToUint8Array(vec.N);
const headerBytes = util.hexToUint8Array(vec.A);
const ctBytes = util.hexToUint8Array(vec.C);
const ocbMode = cipherMode.getAEADMode(openpgp.enums.aead.ocb);
const ocb = await ocbMode(cipher, keyBytes);
// encryption test
let ct = await ocb.encrypt(msgBytes, nonceBytes, headerBytes);
expect(util.uint8ArrayToHex(ct)).to.equal(vec.C.toLowerCase());
// decryption test with verification
let pt = await ocb.decrypt(ctBytes, nonceBytes, headerBytes);
expect(util.uint8ArrayToHex(pt)).to.equal(vec.P.toLowerCase());
// tampering detection test
ct = await ocb.encrypt(msgBytes, nonceBytes, headerBytes);
ct[2] ^= 8;
pt = ocb.decrypt(ct, nonceBytes, headerBytes);
await expect(pt).to.eventually.be.rejectedWith('Authentication tag mismatch');
// testing without additional data
ct = await ocb.encrypt(msgBytes, nonceBytes, new Uint8Array());
pt = await ocb.decrypt(ct, nonceBytes, new Uint8Array());
expect(util.uint8ArrayToHex(pt)).to.equal(vec.P.toLowerCase());
// testing with multiple additional data
ct = await ocb.encrypt(msgBytes, nonceBytes, util.concatUint8Array([headerBytes, headerBytes, headerBytes]));
pt = await ocb.decrypt(ct, nonceBytes, util.concatUint8Array([headerBytes, headerBytes, headerBytes]));
expect(util.uint8ArrayToHex(pt)).to.equal(vec.P.toLowerCase());
}));
});
it('Different key size test vectors', async function() {
const taglen = 128;
const outputs = {
128: '67E944D23256C5E0B6C61FA22FDF1EA2',
192: 'F673F2C3E7174AAE7BAE986CA9F29E17',
256: 'D90EB8E9C977C88B79DD793D7FFA161C'
};
const keylens = [128, 192, 256];
await Promise.all(keylens.map(async keylen => {
const k = new Uint8Array(keylen / 8);
k[k.length - 1] = taglen;
const algo = openpgp.enums.write(openpgp.enums.symmetric, 'aes' + keylen);
const ocbMode = cipherMode.getAEADMode(openpgp.enums.aead.ocb);
const ocb = await ocbMode(algo, k);
const c = [];
let n;
for (let i = 0; i < 128; i++) {
const s = new Uint8Array(i);
n = util.concatUint8Array([new Uint8Array(8), util.writeNumber(3 * i + 1, 4)]);
c.push(await ocb.encrypt(s, n, s));
n = util.concatUint8Array([new Uint8Array(8), util.writeNumber(3 * i + 2, 4)]);
c.push(await ocb.encrypt(s, n, new Uint8Array()));
n = util.concatUint8Array([new Uint8Array(8), util.writeNumber(3 * i + 3, 4)]);
c.push(await ocb.encrypt(new Uint8Array(), n, s));
}
n = util.concatUint8Array([new Uint8Array(8), util.writeNumber(385, 4)]);
const output = await ocb.encrypt(new Uint8Array(), n, util.concatUint8Array(c));
expect(util.uint8ArrayToHex(output)).to.equal(outputs[keylen].toLowerCase());
}));
});
});