diff --git a/src/crypto/aes_kw.js b/src/crypto/aes_kw.js index e747ecc3..dcd116d7 100644 --- a/src/crypto/aes_kw.js +++ b/src/crypto/aes_kw.js @@ -21,7 +21,7 @@ * @module crypto/aes_kw */ -import * as cipher from './cipher'; +import { getCipher } from './cipher'; import util from '../util'; /** @@ -31,8 +31,9 @@ import util from '../util'; * @param {Uint8Array} data * @returns {Uint8Array} */ -export function wrap(key, data) { - const aes = new cipher['aes' + (key.length * 8)](key); +export async function wrap(algo, key, data) { + const Cipher = await getCipher(algo); + const aes = new Cipher(key); const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); const P = unpack(data); let A = IV; @@ -71,8 +72,9 @@ export function wrap(key, data) { * @returns {Uint8Array} * @throws {Error} */ -export function unwrap(key, data) { - const aes = new cipher['aes' + (key.length * 8)](key); +export async function unwrap(algo, key, data) { + const Cipher = await getCipher(algo); + const aes = new Cipher(key); const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); const C = unpack(data); let A = C.subarray(0, 2); diff --git a/src/crypto/cipher/getCipher.js b/src/crypto/cipher/getCipher.js deleted file mode 100644 index a74ef75a..00000000 --- a/src/crypto/cipher/getCipher.js +++ /dev/null @@ -1,13 +0,0 @@ -import * as cipher from '.'; -import enums from '../../enums'; - -/** - * Get implementation of the given cipher - * @param {enums.symmetric} algo - * @returns {Object} - * @throws {Error} on invalid algo - */ -export default function getCipher(algo) { - const algoName = enums.read(enums.symmetric, algo); - return cipher[algoName]; -} diff --git a/src/crypto/cipher/index.js b/src/crypto/cipher/index.js index d40c8e08..878b05c0 100644 --- a/src/crypto/cipher/index.js +++ b/src/crypto/cipher/index.js @@ -1,80 +1,73 @@ -/** - * @fileoverview Symmetric cryptography functions - * @module crypto/cipher - */ +import aes from './aes'; // can be imported dynamically once Web Crypto is used for AES-KW too +import enums from '../../enums'; -import aes from './aes'; -import { DES, TripleDES } from './des'; -import CAST5 from './cast5'; -import TF from './twofish'; -import BF from './blowfish'; +export async function getCipher(algo) { + switch (algo) { + case enums.symmetric.aes128: + case enums.symmetric.aes192: + case enums.symmetric.aes256: + return aes(getCipherKeySize(algo)); + case enums.symmetric.cast5: + case enums.symmetric.blowfish: + case enums.symmetric.twofish: + case enums.symmetric.tripledes: { + const { legacyCiphers } = await import('./legacy_ciphers'); + const cipher = legacyCiphers.get(algo); + if (!cipher) { + throw new Error('Unsupported cipher algorithm'); + } + return cipher; + } + default: + throw new Error('Unsupported cipher algorithm'); + } +} /** - * AES-128 encryption and decryption (ID 7) - * @function - * @param {String} key - 128-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} + * Get block size for given cipher algo + * @param {module:enums.symmetric} algo - alrogithm identifier */ -export const aes128 = aes(128); +function getCipherBlockSize(algo) { + switch (algo) { + case enums.symmetric.aes128: + case enums.symmetric.aes192: + case enums.symmetric.aes256: + case enums.symmetric.twofish: + return 16; + case enums.symmetric.blowfish: + case enums.symmetric.cast5: + case enums.symmetric.tripledes: + return 8; + default: + throw new Error('Unsupported cipher'); + } +} + /** - * AES-128 Block Cipher (ID 8) - * @function - * @param {String} key - 192-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} + * Get key size for given cipher algo + * @param {module:enums.symmetric} algo - alrogithm identifier */ -export const aes192 = aes(192); +function getCipherKeySize(algo) { + switch (algo) { + case enums.symmetric.aes128: + case enums.symmetric.blowfish: + case enums.symmetric.cast5: + return 16; + case enums.symmetric.aes192: + case enums.symmetric.tripledes: + return 24; + case enums.symmetric.aes256: + case enums.symmetric.twofish: + return 32; + default: + throw new Error('Unsupported cipher'); + } +} + /** - * AES-128 Block Cipher (ID 9) - * @function - * @param {String} key - 256-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} + * Get block and key size for given cipher algo + * @param {module:enums.symmetric} algo - alrogithm identifier */ -export const aes256 = aes(256); -// Not in OpenPGP specifications -export const des = DES; -/** - * Triple DES Block Cipher (ID 2) - * @function - * @param {String} key - 192-bit key - * @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67} - * @returns {Object} - */ -export const tripledes = TripleDES; -/** - * CAST-128 Block Cipher (ID 3) - * @function - * @param {String} key - 128-bit key - * @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm} - * @returns {Object} - */ -export const cast5 = CAST5; -/** - * Twofish Block Cipher (ID 10) - * @function - * @param {String} key - 256-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH} - * @returns {Object} - */ -export const twofish = TF; -/** - * Blowfish Block Cipher (ID 4) - * @function - * @param {String} key - 128-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH} - * @returns {Object} - */ -export const blowfish = BF; -/** - * Not implemented - * @function - * @throws {Error} - */ -export const idea = function() { - throw new Error('IDEA symmetric-key algorithm not implemented'); -}; +export function getCipherParams(algo) { + return { keySize: getCipherKeySize(algo), blockSize: getCipherBlockSize(algo) }; +} diff --git a/src/crypto/cipher/legacy_ciphers.js b/src/crypto/cipher/legacy_ciphers.js new file mode 100644 index 00000000..f091d471 --- /dev/null +++ b/src/crypto/cipher/legacy_ciphers.js @@ -0,0 +1,17 @@ +/** + * This file is needed to dynamic import the legacy ciphers. + * Separate dynamic imports are not convenient as they result in multiple chunks. + */ + +import { TripleDES } from './des'; +import CAST5 from './cast5'; +import TwoFish from './twofish'; +import BlowFish from './blowfish'; +import enums from '../../enums'; + +export const legacyCiphers = new Map([ + [enums.symmetric.tripledes, TripleDES], + [enums.symmetric.cast5, CAST5], + [enums.symmetric.blowfish, BlowFish], + [enums.symmetric.twofish, TwoFish] +]); diff --git a/src/crypto/crypto.js b/src/crypto/crypto.js index f24c4a74..486c4c11 100644 --- a/src/crypto/crypto.js +++ b/src/crypto/crypto.js @@ -26,7 +26,7 @@ import publicKey from './public_key'; import mode from './mode'; import { getRandomBytes } from './random'; -import getCipher from './cipher/getCipher'; +import { getCipher, getCipherParams } from './cipher'; import ECDHSymkey from '../type/ecdh_symkey'; import KDFParams from '../type/kdf_params'; import enums from '../enums'; @@ -442,7 +442,7 @@ export async function validateParams(algo, publicParams, privateParams) { * @async */ export async function getPrefixRandom(algo) { - const { blockSize } = getCipher(algo); + const { blockSize } = getCipherParams(algo); const prefixrandom = await getRandomBytes(blockSize); const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); return util.concat([prefixrandom, repeat]); @@ -455,7 +455,7 @@ export async function getPrefixRandom(algo) { * @returns {Uint8Array} Random bytes as a string to be used as a key. */ export function generateSessionKey(algo) { - const { keySize } = getCipher(algo); + const { keySize } = getCipherParams(algo); return getRandomBytes(keySize); } @@ -470,8 +470,6 @@ export function getAEADMode(algo) { return mode[algoName]; } -export { getCipher }; - /** * Check whether the given curve OID is supported * @param {module:type/oid} oid - EC object identifier @@ -524,3 +522,6 @@ export function getPreferredCurveHashAlgo(algo, oid) { throw new Error('Unknown elliptic signing algo'); } } + + +export { getCipher, getCipherParams }; diff --git a/src/crypto/mode/cfb.js b/src/crypto/mode/cfb.js index 6fce90c1..30fea08b 100644 --- a/src/crypto/mode/cfb.js +++ b/src/crypto/mode/cfb.js @@ -23,9 +23,9 @@ import { AES_CFB } from '@openpgp/asmcrypto.js/aes/cfb.js'; import * as stream from '@openpgp/web-stream-tools'; -import getCipher from '../cipher/getCipher'; import util from '../../util'; import enums from '../../enums'; +import { getCipher, getCipherParams } from '../cipher'; const webCrypto = util.getWebCrypto(); const nodeCrypto = util.getNodeCrypto(); @@ -60,7 +60,7 @@ export async function encrypt(algo, key, plaintext, iv, config) { return aesEncrypt(algo, key, plaintext, iv, config); } - const Cipher = getCipher(algo); + const Cipher = await getCipher(algo); const cipherfn = new Cipher(key); const block_size = cipherfn.blockSize; @@ -103,7 +103,7 @@ export async function decrypt(algo, key, ciphertext, iv) { return aesDecrypt(algo, key, ciphertext, iv); } - const Cipher = getCipher(algo); + const Cipher = await getCipher(algo); const cipherfn = new Cipher(key); const block_size = cipherfn.blockSize; @@ -131,7 +131,7 @@ export async function decrypt(algo, key, ciphertext, iv) { class WebCryptoEncryptor { constructor(algo, key, iv) { - const { blockSize } = getCipher(algo); + const { blockSize } = getCipherParams(algo); this.key = key; this.prevBlock = iv; this.nextBlock = new Uint8Array(blockSize); @@ -141,7 +141,7 @@ class WebCryptoEncryptor { } static async isSupported(algo) { - const { keySize } = getCipher(algo); + const { keySize } = getCipherParams(algo); return webCrypto.importKey('raw', new Uint8Array(keySize), 'aes-cbc', false, ['encrypt']) .then(() => true, () => false); } diff --git a/src/crypto/mode/ocb.js b/src/crypto/mode/ocb.js index 3cd1926c..7c60921a 100644 --- a/src/crypto/mode/ocb.js +++ b/src/crypto/mode/ocb.js @@ -20,9 +20,8 @@ * @module crypto/mode/ocb */ -import * as ciphers from '../cipher'; +import { getCipher } from '../cipher'; import util from '../../util'; -import enums from '../../enums'; const blockLength = 16; const ivLength = 15; @@ -68,11 +67,11 @@ async function OCB(cipher, key) { let decipher; let mask; - constructKeyVariables(cipher, key); + await constructKeyVariables(cipher, key); - function constructKeyVariables(cipher, key) { - const cipherName = enums.read(enums.symmetric, cipher); - const aes = new ciphers[cipherName](key); + async function constructKeyVariables(cipher, key) { + const Cipher = await getCipher(cipher); + const aes = new Cipher(key); encipher = aes.encrypt.bind(aes); decipher = aes.decrypt.bind(aes); diff --git a/src/crypto/public_key/elliptic/ecdh.js b/src/crypto/public_key/elliptic/ecdh.js index cc4d3952..8bd03f82 100644 --- a/src/crypto/public_key/elliptic/ecdh.js +++ b/src/crypto/public_key/elliptic/ecdh.js @@ -29,7 +29,7 @@ import enums from '../../../enums'; import util from '../../../util'; import { b64ToUint8Array } from '../../../encoding/base64'; import * as pkcs5 from '../../pkcs5'; -import getCipher from '../../cipher/getCipher'; +import { getCipherParams } from '../../cipher'; const webCrypto = util.getWebCrypto(); const nodeCrypto = util.getNodeCrypto(); @@ -133,9 +133,9 @@ export async function encrypt(oid, kdfParams, data, Q, fingerprint) { const curve = new CurveWithOID(oid); const { publicKey, sharedKey } = await genPublicEphemeralKey(curve, Q); const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); - const { keySize } = getCipher(kdfParams.cipher); + const { keySize } = getCipherParams(kdfParams.cipher); const Z = await kdf(kdfParams.hash, sharedKey, keySize, param); - const wrappedKey = aesKW.wrap(Z, m); + const wrappedKey = await aesKW.wrap(kdfParams.cipher, Z, m); return { publicKey, wrappedKey }; } @@ -195,13 +195,13 @@ export async function decrypt(oid, kdfParams, V, C, Q, d, fingerprint) { const curve = new CurveWithOID(oid); const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d); const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); - const { keySize } = getCipher(kdfParams.cipher); + const { keySize } = getCipherParams(kdfParams.cipher); let err; for (let i = 0; i < 3; i++) { try { // Work around old go crypto bug and old OpenPGP.js bug, respectively. const Z = await kdf(kdfParams.hash, sharedKey, keySize, param, i === 1, i === 2); - return pkcs5.decode(aesKW.unwrap(Z, C)); + return pkcs5.decode(await aesKW.unwrap(kdfParams.cipher, Z, C)); } catch (e) { err = e; } diff --git a/src/crypto/public_key/elliptic/ecdh_x.js b/src/crypto/public_key/elliptic/ecdh_x.js index a517e88a..641af020 100644 --- a/src/crypto/public_key/elliptic/ecdh_x.js +++ b/src/crypto/public_key/elliptic/ecdh_x.js @@ -9,8 +9,8 @@ import { getRandomBytes } from '../../random'; import enums from '../../../enums'; import util from '../../../util'; -import getCipher from '../../cipher/getCipher'; import computeHKDF from '../../hkdf'; +import { getCipherParams } from '../../cipher'; const HKDF_INFO = { x25519: util.encodeUTF8('OpenPGP X25519'), @@ -97,9 +97,10 @@ export async function encrypt(algo, data, recipientA) { recipientA, sharedSecret ]); - const { keySize } = getCipher(enums.symmetric.aes128); + const cipherAlgo = enums.symmetric.aes128; + const { keySize } = getCipherParams(cipherAlgo); const encryptionKey = await computeHKDF(enums.hash.sha256, hkdfInput, new Uint8Array(), HKDF_INFO.x25519, keySize); - const wrappedKey = aesKW.wrap(encryptionKey, data); + const wrappedKey = await aesKW.wrap(cipherAlgo, encryptionKey, data); return { ephemeralPublicKey, wrappedKey }; } case enums.publicKey.x448: { @@ -112,9 +113,10 @@ export async function encrypt(algo, data, recipientA) { recipientA, sharedSecret ]); - const { keySize } = getCipher(enums.symmetric.aes256); + const cipherAlgo = enums.symmetric.aes256; + const { keySize } = getCipherParams(enums.symmetric.aes256); const encryptionKey = await computeHKDF(enums.hash.sha512, hkdfInput, new Uint8Array(), HKDF_INFO.x448, keySize); - const wrappedKey = aesKW.wrap(encryptionKey, data); + const wrappedKey = await aesKW.wrap(cipherAlgo, encryptionKey, data); return { ephemeralPublicKey, wrappedKey }; } @@ -143,9 +145,10 @@ export async function decrypt(algo, ephemeralPublicKey, wrappedKey, A, k) { A, sharedSecret ]); - const { keySize } = getCipher(enums.symmetric.aes128); + const cipherAlgo = enums.symmetric.aes128; + const { keySize } = getCipherParams(cipherAlgo); const encryptionKey = await computeHKDF(enums.hash.sha256, hkdfInput, new Uint8Array(), HKDF_INFO.x25519, keySize); - return aesKW.unwrap(encryptionKey, wrappedKey); + return aesKW.unwrap(cipherAlgo, encryptionKey, wrappedKey); } case enums.publicKey.x448: { const x448 = await util.getNobleCurve(enums.publicKey.x448); @@ -155,9 +158,10 @@ export async function decrypt(algo, ephemeralPublicKey, wrappedKey, A, k) { A, sharedSecret ]); - const { keySize } = getCipher(enums.symmetric.aes256); + const cipherAlgo = enums.symmetric.aes256; + const { keySize } = getCipherParams(enums.symmetric.aes256); const encryptionKey = await computeHKDF(enums.hash.sha512, hkdfInput, new Uint8Array(), HKDF_INFO.x448, keySize); - return aesKW.unwrap(encryptionKey, wrappedKey); + return aesKW.unwrap(cipherAlgo, encryptionKey, wrappedKey); } default: throw new Error('Unsupported ECDH algorithm'); diff --git a/src/packet/secret_key.js b/src/packet/secret_key.js index a80feba7..2cdac5b6 100644 --- a/src/packet/secret_key.js +++ b/src/packet/secret_key.js @@ -174,7 +174,7 @@ class SecretKeyPacket extends PublicKeyPacket { if (this.s2kUsage !== 253 || this.isLegacyAEAD) { this.iv = bytes.subarray( i, - i + crypto.getCipher(this.symmetric).blockSize + i + crypto.getCipherParams(this.symmetric).blockSize ); this.usedModernAEAD = false; } else { @@ -388,7 +388,7 @@ class SecretKeyPacket extends PublicKeyPacket { const cleartext = crypto.serializeParams(this.algorithm, this.privateParams); this.symmetric = enums.symmetric.aes256; - const { blockSize } = crypto.getCipher(this.symmetric); + const { blockSize } = crypto.getCipherParams(this.symmetric); if (config.aeadProtect) { this.s2kUsage = 253; @@ -568,7 +568,7 @@ class SecretKeyPacket extends PublicKeyPacket { * @returns encryption key */ async function produceEncryptionKey(keyVersion, s2k, passphrase, cipherAlgo, aeadMode, serializedPacketTag, isLegacyAEAD) { - const { keySize } = crypto.getCipher(cipherAlgo); + const { keySize } = crypto.getCipherParams(cipherAlgo); const derivedKey = await s2k.produceKey(passphrase, keySize); if (!aeadMode || keyVersion === 5 || isLegacyAEAD) { return derivedKey; diff --git a/src/packet/sym_encrypted_integrity_protected_data.js b/src/packet/sym_encrypted_integrity_protected_data.js index f7c70646..764c0f6a 100644 --- a/src/packet/sym_encrypted_integrity_protected_data.js +++ b/src/packet/sym_encrypted_integrity_protected_data.js @@ -138,7 +138,7 @@ class SymEncryptedIntegrityProtectedDataPacket { this.chunkSizeByte = config.aeadChunkSizeByte; this.encrypted = await runAEAD(this, 'encrypt', key, bytes); } else { - const { blockSize } = crypto.getCipher(sessionKeyAlgorithm); + const { blockSize } = crypto.getCipherParams(sessionKeyAlgorithm); const prefix = await crypto.getPrefixRandom(sessionKeyAlgorithm); const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet @@ -169,7 +169,7 @@ class SymEncryptedIntegrityProtectedDataPacket { if (this.version === 2) { packetbytes = await runAEAD(this, 'decrypt', key, encrypted); } else { - const { blockSize } = crypto.getCipher(sessionKeyAlgorithm); + const { blockSize } = crypto.getCipherParams(sessionKeyAlgorithm); const decrypted = await crypto.mode.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize)); // there must be a modification detection code packet as the @@ -231,7 +231,7 @@ export async function runAEAD(packet, fn, key, data) { let iv; let ivView; if (isSEIPDv2) { - const { keySize } = crypto.getCipher(packet.cipherAlgorithm); + const { keySize } = crypto.getCipherParams(packet.cipherAlgorithm); const { ivLength } = mode; const info = new Uint8Array(adataBuffer, 0, 5); const derived = await computeHKDF(enums.hash.sha256, key, packet.salt, info, keySize + ivLength); diff --git a/src/packet/sym_encrypted_session_key.js b/src/packet/sym_encrypted_session_key.js index 2dcfea54..464be72e 100644 --- a/src/packet/sym_encrypted_session_key.js +++ b/src/packet/sym_encrypted_session_key.js @@ -163,7 +163,7 @@ class SymEncryptedSessionKeyPacket { this.sessionKeyEncryptionAlgorithm : this.sessionKeyAlgorithm; - const { blockSize, keySize } = crypto.getCipher(algo); + const { blockSize, keySize } = crypto.getCipherParams(algo); const key = await this.s2k.produceKey(passphrase, keySize); if (this.version >= 5) { @@ -199,7 +199,7 @@ class SymEncryptedSessionKeyPacket { this.s2k = newS2KFromConfig(config); this.s2k.generateSalt(); - const { blockSize, keySize } = crypto.getCipher(algo); + const { blockSize, keySize } = crypto.getCipherParams(algo); const key = await this.s2k.produceKey(passphrase, keySize); if (this.sessionKey === null) { diff --git a/src/packet/symmetrically_encrypted_data.js b/src/packet/symmetrically_encrypted_data.js index ff4fd3d3..41e3cae7 100644 --- a/src/packet/symmetrically_encrypted_data.js +++ b/src/packet/symmetrically_encrypted_data.js @@ -86,7 +86,7 @@ class SymmetricallyEncryptedDataPacket { throw new Error('Message is not authenticated.'); } - const { blockSize } = crypto.getCipher(sessionKeyAlgorithm); + const { blockSize } = crypto.getCipherParams(sessionKeyAlgorithm); const encrypted = await stream.readToEnd(stream.clone(this.encrypted)); const decrypted = await crypto.mode.cfb.decrypt(sessionKeyAlgorithm, key, encrypted.subarray(blockSize + 2), @@ -107,7 +107,7 @@ class SymmetricallyEncryptedDataPacket { */ async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { const data = this.packets.write(); - const { blockSize } = crypto.getCipher(sessionKeyAlgorithm); + const { blockSize } = crypto.getCipherParams(sessionKeyAlgorithm); const prefix = await crypto.getPrefixRandom(sessionKeyAlgorithm); const FRE = await crypto.mode.cfb.encrypt(sessionKeyAlgorithm, key, prefix, new Uint8Array(blockSize), config); diff --git a/test/crypto/aes_kw.js b/test/crypto/aes_kw.js index 1a3b04c4..7c7cb60b 100644 --- a/test/crypto/aes_kw.js +++ b/test/crypto/aes_kw.js @@ -2,41 +2,48 @@ import { expect } from 'chai'; import * as aesKW from '../../src/crypto/aes_kw.js'; import util from '../../src/util.js'; +import enums from '../../src/enums.js'; export default () => describe('AES Key Wrap and Unwrap', function () { const test_vectors = [ [ '128 bits of Key Data with a 128-bit KEK', + enums.symmetric.aes128, '000102030405060708090A0B0C0D0E0F', '00112233445566778899AABBCCDDEEFF', '1FA68B0A8112B447 AEF34BD8FB5A7B82 9D3E862371D2CFE5' ], [ '128 bits of Key Data with a 192-bit KEK', + enums.symmetric.aes192, '000102030405060708090A0B0C0D0E0F1011121314151617', '00112233445566778899AABBCCDDEEFF', '96778B25AE6CA435 F92B5B97C050AED2 468AB8A17AD84E5D' ], [ '128 bits of Key Data with a 256-bit KEK', + enums.symmetric.aes256, '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F', '00112233445566778899AABBCCDDEEFF', '64E8C3F9CE0F5BA2 63E9777905818A2A 93C8191E7D6E8AE7' ], [ '192 bits of Key Data with a 192-bit KEK', + enums.symmetric.aes192, '000102030405060708090A0B0C0D0E0F1011121314151617', '00112233445566778899AABBCCDDEEFF0001020304050607', '031D33264E15D332 68F24EC260743EDC E1C6C7DDEE725A93 6BA814915C6762D2' ], [ '192 bits of Key Data with a 256-bit KEK', + enums.symmetric.aes256, '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F', '00112233445566778899AABBCCDDEEFF0001020304050607', 'A8F9BC1612C68B3F F6E6F4FBE30E71E4 769C8B80A32CB895 8CD5D17D6B254DA1' ], [ '256 bits of Key Data with a 256-bit KEK', + enums.symmetric.aes256, '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F', '00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F', '28C9F404C4B810F4 CBCCB35CFB87F826 3F5786E2D80ED326 CBC7F0E71A99F43B FB988B9B7A02DD21' @@ -44,15 +51,15 @@ export default () => describe('AES Key Wrap and Unwrap', function () { ]; test_vectors.forEach(function(test) { - it(test[0], function(done) { - const kek = util.hexToUint8Array(test[1]); - const input = test[2].replace(/\s/g, ''); + it(test[0], async function() { + const algo = test[1]; + const kek = util.hexToUint8Array(test[2]); + const input = test[3].replace(/\s/g, ''); const input_bin = util.uint8ArrayToString(util.hexToUint8Array(input)); - const output = test[3].replace(/\s/g, ''); + const output = test[4].replace(/\s/g, ''); const output_bin = util.uint8ArrayToString(util.hexToUint8Array(output)); - expect(util.uint8ArrayToHex(aesKW.wrap(kek, input_bin)).toUpperCase()).to.equal(output); - expect(util.uint8ArrayToHex(aesKW.unwrap(kek, output_bin)).toUpperCase()).to.equal(input); - done(); + expect(util.uint8ArrayToHex(await aesKW.wrap(algo, kek, input_bin)).toUpperCase()).to.equal(output); + expect(util.uint8ArrayToHex(await aesKW.unwrap(algo, kek, output_bin)).toUpperCase()).to.equal(input); }); }); }); diff --git a/test/crypto/cipher/aes.js b/test/crypto/cipher/aes.js index 6ec39863..7f97648c 100644 --- a/test/crypto/cipher/aes.js +++ b/test/crypto/cipher/aes.js @@ -1,9 +1,11 @@ import { expect } from 'chai'; -import { aes128 as AES128 } from '../../../src/crypto/cipher'; +import enums from '../../../src/enums'; +import { getCipher } from '../../../src/crypto/cipher'; export default () => describe('AES Rijndael cipher test with test vectors from ecb_tbl.txt', function() { - function test_aes(input, key, output) { + async function test_aes(input, key, output) { + const AES128 = await getCipher(enums.symmetric.aes128); const aes = new AES128(new Uint8Array(key)); const encrypted = aes.encrypt(new Uint8Array(input)); @@ -61,24 +63,21 @@ export default () => describe('AES Rijndael cipher test with test vectors from e [[0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10,0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A,0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24,0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E],[0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21],[0x08,0x0E,0x95,0x17,0xEB,0x16,0x77,0x71,0x9A,0xCF,0x72,0x80,0x86,0x04,0x0A,0xE3]], [[0x30,0x31,0x32,0x33,0x35,0x36,0x37,0x38,0x3A,0x3B,0x3C,0x3D,0x3F,0x40,0x41,0x42,0x44,0x45,0x46,0x47,0x49,0x4A,0x4B,0x4C,0x4E,0x4F,0x50,0x51,0x53,0x54,0x55,0x56],[0x72,0x61,0x65,0xC1,0x72,0x3F,0xBC,0xF6,0xC0,0x26,0xD7,0xD0,0x0B,0x09,0x10,0x27],[0x7C,0x17,0x00,0x21,0x1A,0x39,0x91,0xFC,0x0E,0xCD,0xED,0x0A,0xB3,0xE5,0x76,0xB0]]]; - it('128 bit key', function (done) { + it('128 bit key', async function () { for (let i = 0; i < testvectors128.length; i++) { - test_aes(testvectors128[i][1],testvectors128[i][0],testvectors128[i][2]); + await test_aes(testvectors128[i][1],testvectors128[i][0],testvectors128[i][2]); } - done(); }); - it('192 bit key', function (done) { + it('192 bit key', async function () { for (let i = 0; i < testvectors192.length; i++) { - test_aes(testvectors192[i][1],testvectors192[i][0],testvectors192[i][2]); + await test_aes(testvectors192[i][1],testvectors192[i][0],testvectors192[i][2]); } - done(); }); - it('256 bit key', function (done) { + it('256 bit key', async function () { for (let i = 0; i < testvectors256.length; i++) { - test_aes(testvectors256[i][1],testvectors256[i][0],testvectors256[i][2]); + await test_aes(testvectors256[i][1],testvectors256[i][0],testvectors256[i][2]); } - done(); }); }); diff --git a/test/crypto/crypto.js b/test/crypto/crypto.js index 1d017d84..c6bd5828 100644 --- a/test/crypto/crypto.js +++ b/test/crypto/crypto.js @@ -254,7 +254,7 @@ export default () => describe('API functional testing', function() { 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 { blockSize } = crypto.getCipherParams(algo); const symmKey = crypto.generateSessionKey(algo); const IV = new Uint8Array(blockSize); const symmencData = await crypto.mode.cfb.encrypt(algo, symmKey, util.stringToUint8Array(plaintext), IV, config);