Fix wrong serialization of PKESK v6 for x25519/x448

The cleartext session key symmetric algorithm was accidentally included in the packet.
As a result, the generated messages may fail to parse and/or decrypt in other implementations.
The messages would still decrypt successfully in OpenPGP.js, due to an overly permissive parsing procedure,
which simply discarded the unused additional byte.
This commit is contained in:
larabr 2024-03-20 18:49:06 +01:00
parent 147d043a32
commit 172c674bd2
2 changed files with 7 additions and 4 deletions

View File

@ -39,7 +39,7 @@ import ECDHXSymmetricKey from '../type/ecdh_x_symkey';
* Encrypts data using specified algorithm and public key parameters.
* See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms.
* @param {module:enums.publicKey} keyAlgo - Public key algorithm
* @param {module:enums.symmetric} symmetricAlgo - Cipher algorithm
* @param {module:enums.symmetric|null} symmetricAlgo - Cipher algorithm (v3 only)
* @param {Object} publicParams - Algorithm-specific public key parameters
* @param {Uint8Array} data - Session key data to be encrypted
* @param {Uint8Array} fingerprint - Recipient fingerprint
@ -66,7 +66,7 @@ export async function publicKeyEncrypt(keyAlgo, symmetricAlgo, publicParams, dat
}
case enums.publicKey.x25519:
case enums.publicKey.x448: {
if (!util.isAES(symmetricAlgo)) {
if (symmetricAlgo && !util.isAES(symmetricAlgo)) {
// see https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/276
throw new Error('X25519 and X448 keys can only encrypt AES session keys');
}

View File

@ -174,9 +174,12 @@ class PublicKeyEncryptedSessionKeyPacket {
*/
async encrypt(key) {
const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm);
const encoded = encodeSessionKey(this.version, algo, this.sessionKeyAlgorithm, this.sessionKey);
// No symmetric encryption algorithm identifier is passed to the public-key algorithm for a
// v6 PKESK packet, as it is included in the v2 SEIPD packet.
const sessionKeyAlgorithm = this.version === 3 ? this.sessionKeyAlgorithm : null;
const encoded = encodeSessionKey(this.version, algo, sessionKeyAlgorithm, this.sessionKey);
this.encrypted = await crypto.publicKeyEncrypt(
algo, this.sessionKeyAlgorithm, key.publicParams, encoded, key.getFingerprintBytes());
algo, sessionKeyAlgorithm, key.publicParams, encoded, key.getFingerprintBytes());
}
/**