diff --git a/src/crypto/public_key/elliptic/ecdh.js b/src/crypto/public_key/elliptic/ecdh.js index b57362a8..9f5cd1f6 100644 --- a/src/crypto/public_key/elliptic/ecdh.js +++ b/src/crypto/public_key/elliptic/ecdh.js @@ -53,7 +53,7 @@ function buildEcdhParam(public_algo, oid, kdfParams, fingerprint) { new Uint8Array([public_algo]), kdfParams.write(), util.stringToUint8Array('Anonymous Sender '), - fingerprint.subarray(0, 20) + fingerprint ]); } @@ -123,7 +123,7 @@ async function genPublicEphemeralKey(curve, Q) { * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use * @param {Uint8Array} data - Unpadded session key data * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} fingerprint - Recipient fingerprint + * @param {Uint8Array} fingerprint - Recipient fingerprint, already truncated depending on the key version * @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>} * @async */ @@ -188,7 +188,7 @@ async function genPrivateEphemeralKey(curve, V, Q, d) { * @param {Uint8Array} C - Encrypted and wrapped value derived from session key * @param {Uint8Array} Q - Recipient public key * @param {Uint8Array} d - Recipient private key - * @param {Uint8Array} fingerprint - Recipient fingerprint + * @param {Uint8Array} fingerprint - Recipient fingerprint, already truncated depending on the key version * @returns {Promise} Value derived from session key. * @async */ diff --git a/src/packet/public_key_encrypted_session_key.js b/src/packet/public_key_encrypted_session_key.js index 23a10563..f0bdc402 100644 --- a/src/packet/public_key_encrypted_session_key.js +++ b/src/packet/public_key_encrypted_session_key.js @@ -180,9 +180,10 @@ class PublicKeyEncryptedSessionKeyPacket { // 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 fingerprint = key.version === 5 ? key.getFingerprintBytes().subarray(0, 20) : key.getFingerprintBytes(); const encoded = encodeSessionKey(this.version, algo, sessionKeyAlgorithm, this.sessionKey); this.encrypted = await crypto.publicKeyEncrypt( - algo, sessionKeyAlgorithm, key.publicParams, encoded, key.getFingerprintBytes()); + algo, sessionKeyAlgorithm, key.publicParams, encoded, fingerprint); } /** @@ -202,7 +203,8 @@ class PublicKeyEncryptedSessionKeyPacket { const randomPayload = randomSessionKey ? encodeSessionKey(this.version, this.publicKeyAlgorithm, randomSessionKey.sessionKeyAlgorithm, randomSessionKey.sessionKey) : null; - const decryptedData = await crypto.publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, key.getFingerprintBytes(), randomPayload); + const fingerprint = key.version === 5 ? key.getFingerprintBytes().subarray(0, 20) : key.getFingerprintBytes(); + const decryptedData = await crypto.publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, fingerprint, randomPayload); const { sessionKey, sessionKeyAlgorithm } = decodeSessionKey(this.version, this.publicKeyAlgorithm, decryptedData, randomSessionKey); diff --git a/test/general/ecc_nist.js b/test/general/ecc_nist.js index aecfe062..5e661248 100644 --- a/test/general/ecc_nist.js +++ b/test/general/ecc_nist.js @@ -75,5 +75,44 @@ export default () => describe('Elliptic Curve Cryptography for NIST P-256,P-384, expect(await result.signatures[0].verified).to.be.true; }); + it('should decrypt a message using the correct fingerprint size in the KDF (v6 key)', async function() { + // this test is to ensure the KDF function uses the correct fingerprint size (the fingerprint should not be truncated) + const key = await openpgp.readKey({ + armoredKey: `-----BEGIN PGP PRIVATE KEY BLOCK----- + +xXkGZoVjGhMAAABMCCqGSM49AwEHAgMEUqR9vqdSZv8I+DGuSOYUSf4cNVlE +H16loiqRcAsDY9SHSTVHQkEWbc63HyEvV3jGSbSk2dNF64faN3nbhlZ0PgAB +APcoOjqcdJ9/LHRgxWvSbrKAmKNm0yJE9U9DY9hwshqhwqEGHxMIAAAAPgWC +ZoVjGgMLCQcFFQgKDA4EFgACAQKbAwIeASKhBk+e6Xq0rbnjKzVy/3Qitc2h +eW/w/IuxgPXjJW3nfTRxAAAAABQOEKxf0tyJS3Pbs1xApVxWKP4BAM8Bkygn +ddtiBifou11xgxOjT0y0CsbjIKyOnPTvIh/4AQCfyLJIAmQUN36mSInEepvy +NVk8jmweVYOCT8RluvFtG80OPHRlc3RAdGVzdC5pdD7CjwYTEwgAAAAsBYJm +hWMaAhkBIqEGT57perStueMrNXL/dCK1zaF5b/D8i7GA9eMlbed9NHEAAAAA +g9UQJqaRsvniF1WYuuRLpqMpOAEAvAhGhNpom/L2iIZLCpeyFCfGe5VDUBQB +1cjGpTbnrJoBAIjy1tgUH1gjixchymNf5LfUqwdXwEiLfv2f/Iq+KEX/x30G +ZoVjGhIAAABQCCqGSM49AwEHAgMESZrMsc0UrXB5/C8FHXAepykqAyueem7p +cjVvWFP9V59w/O/VXVyJBrZqleN0w/KexznRyzvQjH36HRlwVFwJ5QMBCAcA +AQDiiISRsjcPcaGXSAEYmvd80nH1oP8CJ/TQsi8od5nhqMKPBhgTCAAAACwF +gmaFYxoCmwwioQZPnul6tK254ys1cv90IrXNoXlv8PyLsYD14yVt5300cQAA +AAC2GhBn4S5eLyGPjccfUkFRKKWmAP4iHESir/KDsmsfhE5m/RwQcy7feCl7 +2bny7QRNGY8dFQD8CwmHJ0EvMDQcvVWPrj8WdgPblJEEgWd9AUItEFcDee0= +-----END PGP PRIVATE KEY BLOCK-----` + }); + const message = await openpgp.readMessage({ + armoredMessage: `-----BEGIN PGP MESSAGE----- + +wX4DYKEfntV7jkcSAgMEXplJPwjsvhh7xNeBeZtgepG1f0hUaW4eoeFCDpYH +IOr2RZFgRd6KbtmNsI1saqDwDg7EjFk+AWOe7av2xcFStTDfz+9mus03A6tk +7mPFWGsDUrxP2b+tyO6ofr9I4gyj5tI2X7R94AfRWgQxy+O2PvLSNAFXcx4o +SsrtSQmZUKpxuBROy+bZNheNgmN966vqnFBiM1vXikv5OVyprUV0EzzQ3Hnt +69s= +=0Agg +-----END PGP MESSAGE-----` + }); + const decrypted = await openpgp.decrypt({ message, decryptionKeys: key }); + expect(decrypted.data).to.equal('abc'); + }); + + // TODO find test vectors });