[ 
https://issues.apache.org/jira/browse/PDFBOX-4421?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17197520#comment-17197520
 ] 

Christian Appl edited comment on PDFBOX-4421 at 9/17/20, 8:56 AM:
------------------------------------------------------------------

Hmmm, I am not entirely sure yet, but possibly the current code is missing only 
2 simple steps for success? (speaking about decryption)

I must state this first: I am absolutely uncertain about the following!

I tried to understand and play arround with your code and attempted to 
understand which part does what and which variable represents what COS 
Structure. Leading me to two simple assumptions, that I guessed would lead to 
satisfying results.
(I can neither guarantee, that this really solves the issue, nor that this 
won't brake for some cases, but your thoughts about it would be absolutely 
helpful!)

*Basic Assumption:*
This should work! I can find the parts of the Reference manual, that are 
represented here and I can't find big definition gaps at first glance.

*1. Assumption: The assumed key length is wrong (40 instead of 128):*
The method "prepareForDecryption" in PublicKeySecurityHandler is currently 
determining the key length via the PDEncryption dictionary 
encryption.getLength(). for the case +if (encryption.getVersion() == 4 || 
encryption.getVersion() == 5)+ possibly it should be modified like:

{code:java}
// detect whether AES encryption is used. This assumes that the encryption algo 
is 
// stored in the PDCryptFilterDictionary
// However, crypt filters are used only when V is 4 or 5.
PDCryptFilterDictionary defaultCryptFilterDictionary = 
encryption.getDefaultCryptFilterDictionary();
if (defaultCryptFilterDictionary != null) {
   if (defaultCryptFilterDictionary.getLength() != 0) {
      setKeyLength(defaultCryptFilterDictionary.getLength());
   }
}
{code}

*2. Assumption: Now that it accepts, that the key length is 128, the message 
digest is wrong.*
For my test document it now succeeded in creating the cipher, but reported a 
wrong padding / a wrong key, when trying doFinal(). I was absolutely certain to 
provide the corrrect password, alias and keystore to a matching document, 
therefore: The message digest - determining the key - can not be correct. I 
found this:
{code:java}
if (encryption.getVersion() == 4 || encryption.getVersion() == 5) {
   mdResult = MessageDigests.getSHA256().digest(sha1Input);
{code}
And simply changed it to:
{code:java}
if (encryption.getVersion() == 4 || encryption.getVersion() == 5) {
   mdResult = MessageDigests.getSHA1().digest(sha1Input);
{code}
A change which will most definately brake the AES256 handling, but I ignored 
that for now. (possibly V4 and V5 should be handled in separate cases for this 
reason?

*Could these assumptions be possibly correct?*
I created a AES128 encrypted document using Adobe DC and wrote a most 
simplistic test, that shall load said document using my testkeystore and shall 
determine the number of pages:
{code:java}
private static final String password = "w!z%C*F-JaNdRgUk";
private static final String alias = "testnutzer";

@Test
public void openEncDoc() throws Exception {
    File keystore = new File("C:\\Users\\cap.SVD\\Desktop", "keystore.pfx");
    File encDoc = new File("C:\\Users\\cap.SVD\\Desktop", 
"B2-Adobe-128-aes-sec.pdf");

    System.out.println("Now loading and decrypting: " + 
encDoc.getAbsolutePath());
    InputStream keyStoreData = new FileInputStream(keystore);
    PDDocument doc = PDDocument.load(encDoc, password, keyStoreData, alias);
    try {
       System.out.println(" SUCCESS decrypting document, it has " + 
doc.getNumberOfPages() + " pages.");
    } finally {
       keyStoreData.close();
       doc.close();
    }
 }
{code}

Which failed previously for said document and now results in the output:
_Now loading and decrypting: C:\Users\cap.SVD\Desktop\B2-Adobe-128-aes-sec.pdf
 SUCCESS decrypting document, it has 3 pages._

-The document has been successfully decrypted and the number of pages could be 
determined?

I really don't trust myself here, therefore: 
- Where am I seeing things too simple or could this possibly be the solution?
I will definately follow this lead for now - as it resulted in a success - but 
I don't trust that success yet neither, further testing is required and this is 
for now quick and dirty trash code, to simply make it work (somehow).


was (Author: capsvd):
Hmmm, I am not entirely sure yet, but possibly the current code is missing only 
2 simple steps for success? (speaking about decryption)

I must state this first: I am absolutely uncertain about the following!

I tried to understand and play arround with your code and attempted to 
understand which part does what and which variable represents what COS 
Structure. Leading me to two simple assumptions, that I guessed would lead to 
satisfying results.
(I can neither guarantee, that this really solves the issue, nor that this 
won't brake for some cases, but your thoughts about it would be absolutely 
helpful!)

*Basic Assumption:*
This should work! I can find the parts of the Reference manual, that are 
represented here and I can't find big definition gaps at first glance.

*1. Assumption: The assumed key length is wrong (40 instead of 128):*
The method "prepareForDecryption" in PublicKeySecurityHandler is currently 
determining the key length via the PDEncryption dictionary 
encryption.getLength(). for the case +if (encryption.getVersion() == 4 || 
encryption.getVersion() == 5)+ possibly it should be modified like:

{code:java}
// detect whether AES encryption is used. This assumes that the encryption algo 
is 
// stored in the PDCryptFilterDictionary
// However, crypt filters are used only when V is 4 or 5.
PDCryptFilterDictionary defaultCryptFilterDictionary = 
encryption.getDefaultCryptFilterDictionary();
if (defaultCryptFilterDictionary != null) {
   if (defaultCryptFilterDictionary.getLength() != 0) {
      setKeyLength(defaultCryptFilterDictionary.getLength());
   }
}
{code}

*2. Assumption: Now that it accepts, that the key length is 128, the message 
digest is wrong.*
For my test document it now succeeded in creating the cipher, but reported a 
wrong padding / a wrong key, when trying doFinal(). I was absolutely certain to 
provide the corrrect password, alias and keystore to a matching document, 
therefore: The message digest - determining the key - can not be correct. I 
found this:
{code:java}
if (encryption.getVersion() == 4 || encryption.getVersion() == 5) {
   mdResult = MessageDigests.getSHA256().digest(sha1Input);
{code}
And simply changed it to:
{code:java}
if (encryption.getVersion() == 4 || encryption.getVersion() == 5) {
   mdResult = MessageDigests.getSHA1().digest(sha1Input);
{code}
A change which will most definately brake the AES256 handling, but I ignored 
that for now. (possibly V4 and V5 should be handled in separate cases for this 
reason?

*Could these assumptions be possibly correct?*
I created a AES128 encrypted document using Adobe DC and wrote a most 
simplistic test, that shall load said document using my testkeystore and shall 
determine the number of pages:
{code:java}
private static final String password = "w!z%C*F-JaNdRgUk";
private static final String alias = "testnutzer";

@Test
public void openEncDoc() throws Exception {
    File keystore = new File("C:\\Users\\cap.SVD\\Desktop", "keystore.pfx");
    File encDoc = new File("C:\\Users\\cap.SVD\\Desktop", 
"B2-Adobe-128-aes-sec.pdf");

    System.out.println("Now loading and decrypting: " + 
encDoc.getAbsolutePath());
    InputStream keyStoreData = new FileInputStream(keystore);
    PDDocument doc = PDDocument.load(encDoc, password, keyStoreData, alias);
    try {
       System.out.println(" SUCCESS decrypting document, it has " + 
doc.getNumberOfPages() + " pages.");
    } finally {
       keyStoreData.close();
       doc.close();
    }
 }
{code}

Which failed previously for said document and now results in the output:
_Now loading and decrypting: C:\Users\cap.SVD\Desktop\B2-Adobe-128-aes-sec.pdf
 SUCCESS decrypting document, it has 3 pages._

-The document has been successfully decrypted and the number of pages could be 
determined?

I really don't trust myself here, therefore: 
- Where am I seeing things too simple or could this possibly be the solution?
I will definately follow this lead for now - as it resulted in a success - but 
I don't trust that success yet neither, further testing is required and this is 
for now quick and dirty trash code, to simply make it work (somehow).

> Add support for AES128 encryption for public key
> ------------------------------------------------
>
>                 Key: PDFBOX-4421
>                 URL: https://issues.apache.org/jira/browse/PDFBOX-4421
>             Project: PDFBox
>          Issue Type: Bug
>          Components: Crypto
>    Affects Versions: 2.0.13
>            Reporter: Tilman Hausherr
>            Priority: Major
>              Labels: AES128
>         Attachments: B2-Adobe-128-aes-sec.pdf, 
> image-2020-09-16-10-32-11-060.png, image-2020-09-16-10-33-55-201.png, 
> image-2020-09-16-11-55-33-275.png, keystore.pfx
>
>
> Follow-up of PDFBOX-4413. AES256 works for public key crypto, but AES128 
> doesn't when the file is generated by an external software. (local tests 
> work) We should at least get the decryption to work.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@pdfbox.apache.org
For additional commands, e-mail: dev-h...@pdfbox.apache.org

Reply via email to