Update to draft-ietf-openpgp-persistent-symmetric-keys-00

This commit is contained in:
Daniel Huigens 2024-11-05 12:19:32 +01:00
parent 1fb0127a6d
commit 151ae75959
12 changed files with 99 additions and 138 deletions

View File

@ -28,9 +28,7 @@ import mode from './mode';
import { getRandomBytes } from './random';
import { getCipherParams } from './cipher';
import ECDHSymkey from '../type/ecdh_symkey';
import ShortByteString from '../type/short_byte_string';
import hash from './hash';
import config from '../config';
import KDFParams from '../type/kdf_params';
import { SymAlgoEnum, AEADEnum, HashEnum } from '../type/enum';
import enums from '../enums';
@ -85,16 +83,16 @@ export async function publicKeyEncrypt(keyAlgo, symmetricAlgo, publicParams, pri
if (!privateParams) {
throw new Error('Cannot encrypt with symmetric key missing private parameters');
}
const { cipher: algo } = publicParams;
const algoValue = algo.getValue();
const { symAlgo, aeadMode } = publicParams;
const { keyMaterial } = privateParams;
const aeadMode = config.preferredAEADAlgorithm;
const mode = getAEADMode(config.preferredAEADAlgorithm);
const mode = getAEADMode(aeadMode.getValue());
const { ivLength } = mode;
const iv = getRandomBytes(ivLength);
const modeInstance = await mode(algoValue, keyMaterial);
const c = await modeInstance.encrypt(data, iv, new Uint8Array());
return { aeadMode: new AEADEnum(aeadMode), iv, c: new ShortByteString(c) };
const modeInstance = await mode(symAlgo.getValue(), keyMaterial);
const ciphertext = await modeInstance.encrypt(data, iv, new Uint8Array());
const ivAndCiphertext = util.concatUint8Array([iv, ciphertext]);
return { ivAndCiphertext };
}
case enums.publicKey.pqc_mlkem_x25519: {
const { eccPublicKey, mlkemPublicKey } = publicParams;
@ -155,15 +153,17 @@ export async function publicKeyDecrypt(keyAlgo, publicKeyParams, privateKeyParam
keyAlgo, ephemeralPublicKey, C.wrappedKey, A, k);
}
case enums.publicKey.aead: {
const { cipher: algo } = publicKeyParams;
const algoValue = algo.getValue();
const { symAlgo, aeadMode } = publicKeyParams;
const { keyMaterial } = privateKeyParams;
const { aeadMode, iv, c } = sessionKeyParams;
const { ivAndCiphertext } = sessionKeyParams;
const mode = getAEADMode(aeadMode.getValue());
const modeInstance = await mode(algoValue, keyMaterial);
return modeInstance.decrypt(c.data, iv, new Uint8Array());
const { ivLength } = mode;
const modeInstance = await mode(symAlgo.getValue(), keyMaterial);
const iv = ivAndCiphertext.subarray(0, ivLength);
const ciphertext = ivAndCiphertext.subarray(ivLength);
return modeInstance.decrypt(ciphertext, iv, new Uint8Array());
}
case enums.publicKey.pqc_mlkem_x25519: {
const { eccSecretKey, mlkemSecretKey } = privateKeyParams;
@ -235,12 +235,16 @@ export function parsePublicKeyParams(algo, bytes) {
const A = util.readExactSubarray(bytes, read, read + getCurvePayloadSize(algo)); read += A.length;
return { read, publicParams: { A } };
}
case enums.publicKey.hmac:
case enums.publicKey.hmac: {
const hashAlgo = new HashEnum(); read += hashAlgo.read(bytes);
const fpSeed = bytes.subarray(read, read + 32); read += 32;
return { read: read, publicParams: { hashAlgo, fpSeed } };
}
case enums.publicKey.aead: {
const algo = new SymAlgoEnum(); read += algo.read(bytes);
const digestLength = hash.getHashByteLength(enums.hash.sha256);
const digest = bytes.subarray(read, read + digestLength); read += digestLength;
return { read: read, publicParams: { cipher: algo, digest } };
const symAlgo = new SymAlgoEnum(); read += symAlgo.read(bytes);
const aeadMode = new AEADEnum(); read += aeadMode.read(bytes.subarray(read));
const fpSeed = bytes.subarray(read, read + 32); read += 32;
return { read: read, publicParams: { symAlgo, aeadMode, fpSeed } };
}
case enums.publicKey.pqc_mlkem_x25519: {
const eccPublicKey = util.readExactSubarray(bytes, read, read + getCurvePayloadSize(enums.publicKey.x25519)); read += eccPublicKey.length;
@ -310,18 +314,16 @@ export async function parsePrivateKeyParams(algo, bytes, publicParams) {
return { read, privateParams: { k } };
}
case enums.publicKey.hmac: {
const { cipher: algo } = publicParams;
const keySize = hash.getHashByteLength(algo.getValue());
const hashSeed = bytes.subarray(read, read + 32); read += 32;
const { hashAlgo } = publicParams;
const keySize = hash.getHashByteLength(hashAlgo.getValue());
const keyMaterial = bytes.subarray(read, read + keySize); read += keySize;
return { read, privateParams: { hashSeed, keyMaterial } };
return { read, privateParams: { keyMaterial } };
}
case enums.publicKey.aead: {
const { cipher: algo } = publicParams;
const hashSeed = bytes.subarray(read, read + 32); read += 32;
const { keySize } = getCipherParams(algo.getValue());
const { symAlgo } = publicParams;
const { keySize } = getCipherParams(symAlgo.getValue());
const keyMaterial = bytes.subarray(read, read + keySize); read += keySize;
return { read, privateParams: { hashSeed, keyMaterial } };
return { read, privateParams: { keyMaterial } };
}
case enums.publicKey.pqc_mlkem_x25519: {
const eccSecretKey = util.readExactSubarray(bytes, read, read + getCurvePayloadSize(enums.publicKey.x25519)); read += eccSecretKey.length;
@ -385,18 +387,13 @@ export function parseEncSessionKeyParams(algo, bytes) {
return { ephemeralPublicKey, C };
}
// Algorithm-Specific Fields for symmetric AEAD encryption:
// - AEAD algorithm
// - Starting initialization vector
// - Symmetric key encryption of "m" dependent on cipher and AEAD mode prefixed with a one-octet length
// - Symmetric key encryption of "m" using cipher and AEAD mode
// - An authentication tag generated by the AEAD mode.
case enums.publicKey.aead: {
const aeadMode = new AEADEnum(); read += aeadMode.read(bytes.subarray(read));
const { ivLength } = getAEADMode(aeadMode.getValue());
const ivAndCiphertext = bytes;
const iv = bytes.subarray(read, read + ivLength); read += ivLength;
const c = new ShortByteString(); read += c.read(bytes.subarray(read));
return { aeadMode, iv, c };
return { ivAndCiphertext };
}
case enums.publicKey.pqc_mlkem_x25519: {
const eccCipherText = util.readExactSubarray(bytes, read, read + getCurvePayloadSize(enums.publicKey.x25519)); read += eccCipherText.length;
@ -451,10 +448,11 @@ export function serializeParams(algo, params) {
* @param {Integer} bits - Bit length for RSA keys
* @param {module:type/oid} oid - Object identifier for ECC keys
* @param {module:enums.symmetric|enums.hash} symmetric - Hash or cipher algorithm for symmetric keys
* @param {module:enums.aead} aeadMode - AEAD mode for AEAD keys
* @returns {Promise<{ publicParams: {Object}, privateParams: {Object} }>} The parameters referenced by name.
* @async
*/
export async function generateParams(algo, bits, oid, symmetric) {
export async function generateParams(algo, bits, oid, symmetric, aeadMode) {
switch (algo) {
case enums.publicKey.rsaEncrypt:
case enums.publicKey.rsaEncryptSign:
@ -496,11 +494,30 @@ export async function generateParams(algo, bits, oid, symmetric) {
}));
case enums.publicKey.hmac: {
const keyMaterial = await publicKey.hmac.generate(symmetric);
return createSymmetricParams(keyMaterial, new HashEnum(symmetric));
const fpSeed = getRandomBytes(32);
return {
privateParams: {
keyMaterial
},
publicParams: {
hashAlgo: new HashEnum(symmetric),
fpSeed
}
};
}
case enums.publicKey.aead: {
const keyMaterial = generateSessionKey(symmetric);
return createSymmetricParams(keyMaterial, new SymAlgoEnum(symmetric));
const fpSeed = getRandomBytes(32);
return {
privateParams: {
keyMaterial
},
publicParams: {
symAlgo: new SymAlgoEnum(symmetric),
aeadMode: new AEADEnum(aeadMode),
fpSeed
}
};
}
case enums.publicKey.pqc_mlkem_x25519:
return publicKey.postQuantum.kem.generate(algo).then(({ eccSecretKey, eccPublicKey, mlkemSeed, mlkemSecretKey, mlkemPublicKey }) => ({
@ -520,21 +537,6 @@ export async function generateParams(algo, bits, oid, symmetric) {
}
}
async function createSymmetricParams(key, algo) {
const seed = getRandomBytes(32);
const bindingHash = await hash.sha256(seed);
return {
privateParams: {
hashSeed: seed,
keyMaterial: key
},
publicParams: {
cipher: algo,
digest: bindingHash
}
};
}
/**
* Validate algorithm-specific key parameters
* @param {module:enums.publicKey} algo - The public key algorithm
@ -589,20 +591,9 @@ export async function validateParams(algo, publicParams, privateParams) {
const { k } = privateParams;
return publicKey.elliptic.ecdhX.validateParams(algo, A, k);
}
case enums.publicKey.hmac: {
const { cipher: algo, digest } = publicParams;
const { hashSeed, keyMaterial } = privateParams;
const keySize = hash.getHashByteLength(algo.getValue());
return keySize === keyMaterial.length &&
util.equalsUint8Array(digest, await hash.sha256(hashSeed));
}
case enums.publicKey.aead: {
const { cipher: algo, digest } = publicParams;
const { hashSeed, keyMaterial } = privateParams;
const { keySize } = getCipherParams(algo.getValue());
return keySize === keyMaterial.length &&
util.equalsUint8Array(digest, await hash.sha256(hashSeed));
}
case enums.publicKey.hmac:
case enums.publicKey.aead:
throw new Error('Persistent symmetric keys must be encrypted using AEAD');
case enums.publicKey.pqc_mlkem_x25519: {
const { eccSecretKey, mlkemSeed } = privateParams;
const { eccPublicKey, mlkemPublicKey } = publicParams;

View File

@ -1,5 +1,6 @@
import enums from '../../enums';
import util from '../../util';
import hash from '../hash';
const supportedHashAlgos = new Set([enums.hash.sha1, enums.hash.sha256, enums.hash.sha512]);
@ -11,12 +12,14 @@ export async function generate(hashAlgo) {
throw new Error('Unsupported hash algorithm.');
}
const hashName = enums.read(enums.webHash, hashAlgo);
const keySize = hash.getHashByteLength(hashAlgo);
const crypto = webCrypto || nodeCrypto.webcrypto.subtle;
const key = await crypto.generateKey(
{
name: 'HMAC',
hash: { name: hashName }
hash: { name: hashName },
length: keySize * 8
},
true,
['sign', 'verify']

View File

@ -6,7 +6,6 @@
import publicKey from './public_key';
import enums from '../enums';
import util from '../util';
import ShortByteString from '../type/short_byte_string';
import { UnsupportedError } from '../packet/packet';
/**
@ -67,7 +66,7 @@ export function parseSignatureParams(algo, signature) {
return { read, signatureParams: { RS } };
}
case enums.publicKey.hmac: {
const mac = new ShortByteString(); read += mac.read(signature.subarray(read));
const mac = signature; read += signature.length;
return { read, signatureParams: { mac } };
}
case enums.publicKey.pqc_mldsa_ed25519: {
@ -136,9 +135,9 @@ export async function verify(algo, hashAlgo, signature, publicParams, privatePar
if (!privateParams) {
throw new Error('Cannot verify HMAC signature with symmetric key missing private parameters');
}
const { cipher: algo } = publicParams;
const { hashAlgo } = publicParams;
const { keyMaterial } = privateParams;
return publicKey.hmac.verify(algo.getValue(), keyMaterial, signature.mac.data, hashed);
return publicKey.hmac.verify(hashAlgo.getValue(), keyMaterial, signature.mac, hashed);
}
case enums.publicKey.pqc_mldsa_ed25519: {
const { eccPublicKey, mldsaPublicKey } = publicParams;
@ -200,10 +199,10 @@ export async function sign(algo, hashAlgo, publicKeyParams, privateKeyParams, da
return publicKey.elliptic.eddsa.sign(algo, hashAlgo, data, A, seed, hashed);
}
case enums.publicKey.hmac: {
const { cipher: algo } = publicKeyParams;
const { hashAlgo } = publicKeyParams;
const { keyMaterial } = privateKeyParams;
const mac = await publicKey.hmac.sign(algo.getValue(), keyMaterial, hashed);
return { mac: new ShortByteString(mac) };
const mac = await publicKey.hmac.sign(hashAlgo.getValue(), keyMaterial, hashed);
return { mac };
}
case enums.publicKey.pqc_mldsa_ed25519: {
const { eccPublicKey } = publicKeyParams;

View File

@ -102,9 +102,9 @@ export default {
pqc_mldsa_ed25519: 107,
/** Persistent symmetric keys: encryption algorithm */
aead: 100,
aead: 128,
/** Persistent symmetric keys: authentication algorithm */
hmac: 101
hmac: 129
},
/** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2}

View File

@ -17,7 +17,7 @@ export async function generateSecretSubkey(options, config) {
const secretSubkeyPacket = new SecretSubkeyPacket(options.date, config);
secretSubkeyPacket.packets = null;
secretSubkeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm);
await secretSubkeyPacket.generate(options.rsaBits, options.curve, options.symmetric);
await secretSubkeyPacket.generate(options.rsaBits, options.curve, options.symmetric, config.preferredAEADAlgorithm);
await secretSubkeyPacket.computeFingerprintAndKeyID();
return secretSubkeyPacket;
}
@ -26,7 +26,7 @@ export async function generateSecretKey(options, config) {
const secretKeyPacket = new SecretKeyPacket(options.date, config);
secretKeyPacket.packets = null;
secretKeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm);
await secretKeyPacket.generate(options.rsaBits, options.curve, options.symmetric);
await secretKeyPacket.generate(options.rsaBits, options.curve, options.symmetric, config.preferredAEADAlgorithm);
await secretKeyPacket.computeFingerprintAndKeyID();
return secretKeyPacket;
}
@ -506,6 +506,7 @@ export function validateDecryptionKeyPacket(keyPacket, signature, config) {
case enums.publicKey.ecdh:
case enums.publicKey.x25519:
case enums.publicKey.x448:
case enums.publicKey.aead:
case enums.publicKey.pqc_mlkem_x25519: {
const isValidSigningKeyPacket = !signature.keyFlags || (signature.keyFlags[0] & enums.keyFlags.signData) !== 0;
if (isValidSigningKeyPacket && config.allowInsecureDecryptionWithSigningKeys) {

View File

@ -50,7 +50,7 @@ class PrivateKey extends PublicKey {
switch (keyPacket.constructor.tag) {
case enums.packet.secretKey: {
if (keyPacket.algorithm === enums.publicKey.aead || keyPacket.algorithm === enums.publicKey.hmac) {
throw new Error('Cannot create public key from symmetric private');
throw new Error('Cannot create public key from symmetric private key');
}
const pubKeyPacket = PublicKeyPacket.fromSecretKeyPacket(keyPacket);
packetlist.push(pubKeyPacket);
@ -238,7 +238,7 @@ class PrivateKey extends PublicKey {
* @param {String} options.curve (optional) Elliptic curve for ECC keys
* @param {Integer} options.rsaBits (optional) Number of bits for RSA subkeys
* @param {String} options.symmetricCipher (optional) Symmetric algorithm for persistent symmetric aead keys
* @param {String} options.symmetricHash (optional)Hash lgorithm for persistent symmetric hmac keys
* @param {String} options.symmetricHash (optional) Hash algorithm for persistent symmetric hmac keys
* @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires
* @param {Date} options.date (optional) Override the creation date of the key and the key signatures
* @param {Boolean} options.sign (optional) Indicates whether the subkey should sign rather than encrypt. Defaults to false

View File

@ -45,7 +45,7 @@ import { checkKeyRequirements } from './key/helper';
* curve25519Legacy (default), nistP256, nistP384, nistP521, secp256k1,
* brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1
* @param {String} options.symmetricCipher (optional) Symmetric algorithm for persistent symmetric aead keys
* @param {String} options.symmetricHash (optional)Hash lgorithm for persistent symmetric hmac keys
* @param {String} options.symmetricHash (optional) Hash algorithm for persistent symmetric hmac keys
* @param {Date} [options.date=current date] - Override the creation date of the key and the key signatures
* @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires
* @param {Array<Object>} [options.subkeys=a single encryption subkey] - Options for each subkey e.g. `[{sign: true, passphrase: '123'}]`

View File

@ -283,8 +283,11 @@ class PublicKeyPacket {
result.bits = util.uint8ArrayBitLength(modulo);
} else if (this.publicParams.oid) {
result.curve = this.publicParams.oid.getName();
} else if (this.publicParams.cipher) {
result.symmetric = this.publicParams.cipher.getName();
} else if (this.publicParams.symAlgo) {
result.symmetric = this.publicParams.symAlgo.getName();
result.aeadMode = this.publicParams.aeadMode.getName();
} else if (this.publicParams.hashAlgo) {
result.symmetric = this.publicParams.hashAlgo.getName();
}
return result;
}

View File

@ -523,7 +523,7 @@ class SecretKeyPacket extends PublicKeyPacket {
}
}
async generate(bits, curve, symmetric) {
async generate(bits, curve, symmetric, aeadMode) {
// The deprecated OIDs for Ed25519Legacy and Curve25519Legacy are used in legacy version 4 keys and signatures.
// Implementations MUST NOT accept or generate v6 key material using the deprecated OIDs.
if (this.version === 6 && (
@ -538,7 +538,7 @@ class SecretKeyPacket extends PublicKeyPacket {
)) {
throw new Error(`Cannot generate v${this.version} keys of type 'pqc'. Generate a v6 key instead`);
}
const { privateParams, publicParams } = await crypto.generateParams(this.algorithm, bits, curve, symmetric);
const { privateParams, publicParams } = await crypto.generateParams(this.algorithm, bits, curve, symmetric, aeadMode);
this.privateParams = privateParams;
this.publicParams = publicParams;
this.isEncrypted = false;

View File

@ -1,32 +0,0 @@
import util from '../util';
class ShortByteString {
constructor(data) {
if (typeof data === 'undefined') {
data = new Uint8Array([]);
}
if (!util.isUint8Array(data)) {
throw new Error('data must be in the form of a Uint8Array');
}
this.data = data;
this.length = this.data.byteLength;
}
write() {
return util.concatUint8Array([new Uint8Array([this.length]), this.data]);
}
read(input) {
if (input.length >= 1) {
const length = input[0];
if (input.length >= length + 1) {
this.data = input.subarray(1, 1 + length);
this.length = length;
return 1 + length;
}
}
throw new Error('Invalid octet string');
}
}
export default ShortByteString;

View File

@ -4757,7 +4757,7 @@ I8kWVkXU6vFOi+HWvv/ira7ofJu16NnoUkhclkUrk0mXubZvyl4GBg==
expect(subKey).to.exist;
expect(newPrivateKey.getSubkeys().length).to.be.equal(total + 1);
expect(subKey.getAlgorithmInfo().symmetric).to.be.equal('aes256');
expect(subKey.keyPacket.publicParams.digest).to.exist.and.to.have.length(32);
expect(subKey.keyPacket.publicParams.fpSeed).to.exist.and.to.have.length(32);
expect(subKey.keyPacket.privateParams.keyMaterial).to.exist.and.to.have.length(32);
await subKey.verify(privateKey.primaryKey);
});
@ -4773,9 +4773,9 @@ I8kWVkXU6vFOi+HWvv/ira7ofJu16NnoUkhclkUrk0mXubZvyl4GBg==
expect(newKey.getSubkeys().length).to.be.equal(1);
expect(subKey).to.exist;
expect(subKey.getAlgorithmInfo().symmetric).to.be.equal('aes256');
expect(subKey.keyPacket.publicParams.cipher).to.exist;
expect(subKey.keyPacket.publicParams.cipher.getValue()).to.be.equal(openpgp.enums.symmetric.aes256);
expect(subKey.keyPacket.publicParams.digest).to.exist.and.to.have.length(32);
expect(subKey.keyPacket.publicParams.symAlgo).to.exist;
expect(subKey.keyPacket.publicParams.symAlgo.getValue()).to.be.equal(openpgp.enums.symmetric.aes256);
expect(subKey.keyPacket.publicParams.fpSeed).to.exist.and.to.have.length(32);
expect(subKey.keyPacket.privateParams.keyMaterial).to.exist.and.to.have.length(32);
await subKey.verify(newKey.primaryKey);
});
@ -4789,9 +4789,9 @@ I8kWVkXU6vFOi+HWvv/ira7ofJu16NnoUkhclkUrk0mXubZvyl4GBg==
expect(privateKey.getSubkeys().length).to.be.equal(1);
expect(subKey).to.exist;
expect(subKey.getAlgorithmInfo().symmetric).to.be.equal('aes256');
expect(subKey.keyPacket.publicParams.cipher).to.exist;
expect(subKey.keyPacket.publicParams.cipher.getValue()).to.be.equal(openpgp.enums.symmetric.aes256);
expect(subKey.keyPacket.publicParams.digest).to.exist.and.to.have.length(32);
expect(subKey.keyPacket.publicParams.symAlgo).to.exist;
expect(subKey.keyPacket.publicParams.symAlgo.getValue()).to.be.equal(openpgp.enums.symmetric.aes256);
expect(subKey.keyPacket.publicParams.fpSeed).to.exist.and.to.have.length(32);
expect(subKey.keyPacket.privateParams.keyMaterial).to.exist.and.to.have.length(32);
await subKey.verify(privateKey.primaryKey);
});

View File

@ -1229,19 +1229,17 @@ V+HOQJQxXJkVRYa3QrFUehiMzTeqqMdgC6ZqJy7+
it('Parse persistent key encrypted session key packet (PKESK encrypted with persistent symmetric key)', () => {
const serializedPacket = new Uint8Array([
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x64, 0x01, 0x4c, 0x80, 0x3d, 0x9b, 0xb6,
0x00, 0x80, 0x4c, 0x80, 0x3d, 0x9b, 0xb6,
0x44, 0x13, 0x25, 0x90, 0x24, 0x6e, 0x59, 0x0d,
0x68, 0xee, 0x1e, 0x23, 0x75, 0x8a, 0x90, 0x85,
0x68, 0xee, 0x1e, 0x75, 0x8a, 0x90, 0x85,
0x78, 0x1b, 0xf7, 0xc4, 0x4d, 0x58, 0xc7, 0x64,
0xd2, 0xe5, 0xb3, 0x4f, 0xf6, 0x6e, 0xef, 0x53,
0xc4, 0xc3, 0x76, 0x7b, 0xba, 0xf9, 0x03, 0x86,
0xee, 0xc0, 0x9d, 0x60, 0x23, 0xa6, 0x8a
]);
const expectedIV = new Uint8Array([
const expectedIVAndCiphertext = new Uint8Array([
0x4c, 0x80, 0x3d, 0x9b, 0xb6, 0x44, 0x13, 0x25,
0x90, 0x24, 0x6e, 0x59, 0x0d, 0x68, 0xee, 0x1e
]);
const expectedCiphertext = new Uint8Array([
0x90, 0x24, 0x6e, 0x59, 0x0d, 0x68, 0xee, 0x1e,
0x75, 0x8a, 0x90, 0x85, 0x78, 0x1b, 0xf7, 0xc4,
0x4d, 0x58, 0xc7, 0x64, 0xd2, 0xe5, 0xb3, 0x4f,
0xf6, 0x6e, 0xef, 0x53, 0xc4, 0xc3, 0x76, 0x7b,
@ -1252,17 +1250,15 @@ V+HOQJQxXJkVRYa3QrFUehiMzTeqqMdgC6ZqJy7+
packet.read(serializedPacket);
expect(packet.publicKeyAlgorithm).to.equal(openpgp.enums.publicKey.aead);
expect(packet.encrypted.aeadMode.data).to.equal(openpgp.enums.aead.eax);
expect(util.equalsUint8Array(packet.encrypted.iv, expectedIV)).to.be.true;
expect(util.equalsUint8Array(packet.encrypted.c.data, expectedCiphertext)).to.be.true;
expect(util.equalsUint8Array(packet.encrypted.ivAndCiphertext, expectedIVAndCiphertext)).to.be.true;
});
it('Parse signature packet from persistent symmetric key', () => {
const serializedPacket = new Uint8Array([
0x04, 0x00, 0x65, 0x08, 0x00, 0x10, 0x05, 0x02,
0x04, 0x00, 0x81, 0x08, 0x00, 0x10, 0x05, 0x02,
0x60, 0x64, 0x52, 0x28, 0x09, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6b, 0x1d, 0x40, 0x76, 0xf9, 0x35, 0xf8,
0x6b, 0x1d, 0x76, 0xf9, 0x35, 0xf8,
0xe4, 0xc5, 0x2f, 0x49, 0xce, 0xf7, 0x91, 0x23,
0xb4, 0x00, 0x3b, 0x77, 0x92, 0x60, 0x2a, 0xfe,
0x2e, 0x4c, 0xf5, 0x5f, 0x6c, 0x75, 0x80, 0x5a,
@ -1287,7 +1283,7 @@ V+HOQJQxXJkVRYa3QrFUehiMzTeqqMdgC6ZqJy7+
const packet = new openpgp.SignaturePacket();
packet.read(serializedPacket);
const readMAC = packet.params.mac.data;
const readMAC = packet.params.mac;
expect(packet.publicKeyAlgorithm).to.equal(openpgp.enums.publicKey.hmac);
expect(util.equalsUint8Array(readMAC, expectedMAC)).to.be.true;
@ -1297,7 +1293,7 @@ V+HOQJQxXJkVRYa3QrFUehiMzTeqqMdgC6ZqJy7+
const persistentSymmetricKeyPacket = new openpgp.SecretSubkeyPacket();
persistentSymmetricKeyPacket.version = 4;
persistentSymmetricKeyPacket.algorithm = openpgp.enums.publicKey.aead;
await persistentSymmetricKeyPacket.generate(null, null, openpgp.enums.symmetric.aes256);
await persistentSymmetricKeyPacket.generate(null, null, openpgp.enums.symmetric.aes256, openpgp.enums.aead.gcm);
await persistentSymmetricKeyPacket.computeFingerprintAndKeyID();
const sessionKey = new Uint8Array([1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2]);