diff --git a/src/UglyToad.PdfPig.Tests/Integration/EncryptedDocumentTests.cs b/src/UglyToad.PdfPig.Tests/Integration/EncryptedDocumentTests.cs index 58cd342bb..04eccdd8c 100644 --- a/src/UglyToad.PdfPig.Tests/Integration/EncryptedDocumentTests.cs +++ b/src/UglyToad.PdfPig.Tests/Integration/EncryptedDocumentTests.cs @@ -63,6 +63,15 @@ public void CanReadDocumentWithEmptyStringEncryptedWithAESEncryptionAndOnlyIV() } } + [Fact] + public void CanReadDocumentWithNoKeyLengthAndRevision4() + { + using (var document = PdfDocument.Open(IntegrationHelpers.GetSpecificTestDocumentPath("r4_aesv2_no_length"))) + { + Assert.Empty(document.Information.Producer); + } + } + private static string GetPath() => IntegrationHelpers.GetSpecificTestDocumentPath(FileName); } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig.Tests/Integration/SpecificTestDocuments/r4_aesv2_no_length.pdf b/src/UglyToad.PdfPig.Tests/Integration/SpecificTestDocuments/r4_aesv2_no_length.pdf new file mode 100644 index 000000000..357f7fa72 Binary files /dev/null and b/src/UglyToad.PdfPig.Tests/Integration/SpecificTestDocuments/r4_aesv2_no_length.pdf differ diff --git a/src/UglyToad.PdfPig/Encryption/EncryptionHandler.cs b/src/UglyToad.PdfPig/Encryption/EncryptionHandler.cs index 1a6fa67be..91ce19498 100644 --- a/src/UglyToad.PdfPig/Encryption/EncryptionHandler.cs +++ b/src/UglyToad.PdfPig/Encryption/EncryptionHandler.cs @@ -82,8 +82,8 @@ public EncryptionHandler(EncryptionDictionary encryptionDictionary, TrailerDicti cryptHandler = cryptHandlerLocal; - useAes = cryptHandlerLocal?.StreamDictionary?.Name == CryptDictionary.Method.AesV2 - || cryptHandlerLocal?.StreamDictionary?.Name == CryptDictionary.Method.AesV3; + useAes = cryptHandlerLocal.StreamDictionary.Name == CryptDictionary.Method.AesV2 + || cryptHandlerLocal.StreamDictionary.Name == CryptDictionary.Method.AesV3; } var charset = OtherEncodings.Iso88591; @@ -96,7 +96,18 @@ public EncryptionHandler(EncryptionDictionary encryptionDictionary, TrailerDicti var length = encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.Rc4OrAes40BitKey ? 5 - : encryptionDictionary.KeyLength.GetValueOrDefault() / 8; + : encryptionDictionary.KeyLength switch + { + // this is as per the PDF specification, (PDF_ISO_32000-2, 7.6.2 Application of encryption, table 20, indicating Length default value is 40) + null when encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.Rc4OrAesGreaterThan40BitKey => 40, + null when encryptionDictionary.EncryptionAlgorithmCode == EncryptionAlgorithmCode.UnpublishedAlgorithm40To128BitKey => 40, + // this is based on a specific use case encountered and tested, in link with the pdf specification (PDF_ISO_32000-2, 7.6.5.3 Public-key encryption algorithms, table 25, CFM comments) + null when cryptHandler?.StreamDictionary.Name == CryptDictionary.Method.AesV2 => 128, + // this is speculation, in link with the pdf spec, in link with the pdf specification (PDF_ISO_32000-2, 7.6.5.3 Public-key encryption algorithms, table 25, CFM comments) + null when cryptHandler?.StreamDictionary.Name == CryptDictionary.Method.AesV3 => 256, + // other use cases + _ => encryptionDictionary.KeyLength.GetValueOrDefault() + } / 8; var foundPassword = false;