mirror of
https://github.com/openpgpjs/openpgpjs.git
synced 2025-10-14 00:59:29 +00:00
Import legacy ciphers (CAST5, TwoFish, BlowFish, DES) only on demand (#1723)
This primarily affects the lightweight build, which will not include these (fairly large) modules in the main bundle file.
This commit is contained in:
parent
b413a113f9
commit
db15f6d6a1
@ -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);
|
||||
|
@ -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];
|
||||
}
|
@ -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) };
|
||||
}
|
||||
|
17
src/crypto/cipher/legacy_ciphers.js
Normal file
17
src/crypto/cipher/legacy_ciphers.js
Normal file
@ -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]
|
||||
]);
|
@ -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 };
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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');
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user