Fix zlib compression for data larger than 65KB

Regression introduced in https://github.com/openpgpjs/openpgpjs/pull/1826
(v6.2.0) .
Due to internal fflate lib changes, part of the compressed data ended up being discarded,
leading to a corrupted compressed payload for the encrypted/signed message,
which cannot be decompressed.

Compression is disabled by default in openpgpjs.
Hence, the issue affects only users who enabled zlib compression via e.g.
`config.preferredCompressionAlgorithm = openpgp.enums.compression.zlib`
and encrypted or signed data larger than 65KB.
This commit is contained in:
larabr 2025-09-02 14:20:59 +02:00
parent 30ce607245
commit 0ab548cb90
No known key found for this signature in database
GPG Key ID: 2A4BEC40729185DD
2 changed files with 26 additions and 2 deletions

View File

@ -151,8 +151,12 @@ function zlib(compressionStreamInstantiator, ZlibStreamedConstructor) {
return streamFromAsync(() => streamReadToEnd(data).then(inputData => { return streamFromAsync(() => streamReadToEnd(data).then(inputData => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const zlibStream = new ZlibStreamedConstructor(); const zlibStream = new ZlibStreamedConstructor();
zlibStream.ondata = processedData => { const processedChunks = [];
resolve(processedData); zlibStream.ondata = (processedData, final) => {
processedChunks.push(processedData);
if (final) {
resolve(util.concatUint8Array(processedChunks));
}
}; };
try { try {
zlibStream.push(inputData, true); // only one chunk to push zlibStream.push(inputData, true); // only one chunk to push

View File

@ -3698,6 +3698,26 @@ XfA3pqV4mTzF
}); });
}); });
it('should encrypt and decrypt with one password (larger message)', async function () {
const largerPlaintext = new Uint8Array(100_000);
const encOpt = modifyCompressionEncryptOptions({
message: await openpgp.createMessage({ binary: largerPlaintext }),
passwords: password1
});
const decOpt = {
passwords: password1,
format: 'binary'
};
return openpgp.encrypt(encOpt).then(async function (encrypted) {
decOpt.message = await openpgp.readMessage({ armoredMessage: encrypted });
return openpgp.decrypt(decOpt);
}).then(function (decrypted) {
expect(util.equalsUint8Array(decrypted.data, largerPlaintext)).to.be.true;
expect(decrypted.signatures.length).to.equal(0);
verifyCompressionDecrypted(decrypted);
});
});
it('Streaming encrypt and decrypt small message roundtrip', async function() { it('Streaming encrypt and decrypt small message roundtrip', async function() {
const plaintext = []; const plaintext = [];
let i = 0; let i = 0;