Merge pull request #21485 from calixteman/bug2046659

Use AES256 for V=5 documents with a mislabeled AESV2 crypt filter (bug 2046659)
This commit is contained in:
Tim van der Meij 2026-06-22 20:44:48 +02:00 committed by GitHub
commit b6469341c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 56 additions and 0 deletions

View File

@ -1280,6 +1280,12 @@ class CipherTransformFactory {
PasswordResponses.NEED_PASSWORD
);
}
if (this.algorithm === 5) {
// V=5 always uses 256-bit AES with the file encryption key, even
// when a producer wrongly sets the crypt filter's CFM to AESV2
// (bug 2046659).
return AES256Cipher.bind(null, this.encryptionKey);
}
if (cfm.name === "V2") {
return ARCFourCipher.bind(
null,

View File

@ -597,6 +597,23 @@ describe("CipherTransformFactory", function () {
expect(string).toEqual(decrypted);
}
function ensureCrossCipherIsIdentity(
encryptDict,
decryptDict,
fileId,
password,
string
) {
const encrypted = new CipherTransformFactory(encryptDict, fileId, password)
.createCipherTransform(123, 0)
.encryptString(string);
const decrypted = new CipherTransformFactory(decryptDict, fileId, password)
.createCipherTransform(123, 0)
.decryptString(encrypted);
expect(decrypted).toEqual(string);
}
let fileId1, fileId2, dict1, dict2, dict3;
let aes256Dict, aes256IsoDict, aes256BlankDict, aes256IsoBlankDict;
@ -853,6 +870,39 @@ describe("CipherTransformFactory", function () {
"aaaaaaaaaaaaaaaaaaaaaa"
);
});
it("should decrypt V=5 with an AESV2 crypt filter using AES256", function () {
// Some producers wrongly set the crypt filter's CFM to AESV2 for V=5
// documents, which must still be decrypted with AES256 (bug 2046659).
dict3.CF = buildDict({
Identity: buildDict({
CFM: Name.get("AESV3"),
}),
});
const aesv3Dict = buildDict(dict3);
dict3.CF = buildDict({
Identity: buildDict({
CFM: Name.get("AESV2"),
}),
});
const aesv2Dict = buildDict(dict3);
for (const string of ["", "aaaa", "aaaaa", "aaaaaaaaaaaaaaaa"]) {
ensureCrossCipherIsIdentity(
aesv3Dict,
aesv2Dict,
fileId1,
"user",
string
);
ensureCrossCipherIsIdentity(
aesv2Dict,
aesv3Dict,
fileId1,
"user",
string
);
}
});
it("should encrypt and have the correct length using AES128", function () {
dict3.CF = buildDict({
Identity: buildDict({