mirror of
https://github.com/openpgpjs/openpgpjs.git
synced 2025-07-01 10:32:30 +00:00
Update to draft-ietf-openpgp-persistent-symmetric-keys-00
This commit is contained in:
parent
1fb0127a6d
commit
151ae75959
@ -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;
|
||||
|
@ -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']
|
||||
|
@ -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;
|
||||
|
@ -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}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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'}]`
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
@ -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);
|
||||
});
|
||||
|
@ -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]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user