How to decrypt 128bit RC4 pdf file in java with user password if it is encrpted with user as well as owner password

I have a PDF file locked with owner and user password. I don’t have the owner password but I have the user password.

I am using iText to decrypt the file

So how should I decrypt the PDF file.

public class Decrypt {

  public static final String SRC = "D://GitCodeBase(Master)//pdf//src//main//resources//encrypt//abc.pdf";
  public static final String DEST = "D://GitCodeBase(Master)//pdf//src//main//resources//decrypt//def.pdf";

  public static void main(String[] args) throws Exception {
      PdfReader.unethicalreading = true;
      PdfReader reader = new PdfReader(SRC,"abc123".getBytes());
      PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(DEST));
      stamper.close();
      reader.close();
  }
}

Using your code and your example file, I unfortunately cannot reproduce the issue: The code executes without throwing an exception.

But it does not yet do what you want either: The result file still is encrypted. Thus, here some information on that.


If you read Bruno’s answer here up to its end, you’ll see that your code used to decrypt PDF files before iText 5.3.5. Meanwhile, though, the encryption is kept. Strictly speaking that indeed is more correct, after all the code nowhere asks iText to drop the encryption.

Thus, in current iText 5 versions (I’m using the current 5.5.12-SNAPSHOT maintenance version), you have to do a bit more, you have to fool iText into thinking that the PDF wasn’t encrypted as Bruno put it in his answer.

Unfortunately the member variable of PdfReader you have to change to do that is not public. Thus, you cannot simply set it.

The member in question is protected. Thus, you can change it by deriving your own PdfReader subclass and use a method in it to do the change. This has been demonstrated in Bruno’s answer, here a variation for non-empty user passwords:

class MyReader extends PdfReader {
    public MyReader(final String filename, final byte password[]) throws IOException {
        super(filename, password);
    }
    public void decryptOnPurpose() {
        encrypted = false;
    }
}

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    MyReader.unethicalreading = true;
    MyReader reader = new MyReader(src, "abc123".getBytes());
    reader.decryptOnPurpose();
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    stamper.close();
    reader.close();
}

Alternatively you can also use reflection:

PdfReader.unethicalreading = true;
PdfReader reader = new PdfReader(inputStream, "abc123".getBytes());

Field encryptedField = PdfReader.class.getDeclaredField("encrypted");
encryptedField.setAccessible(true);
encryptedField.set(reader, false);

PdfStamper stamper = new PdfStamper(reader, outputStream);
stamper.close();
reader.close();

(DecryptUserOnly.java test method testDecryptAbc)


PS: I am aware that this answer hardly adds anything to Bruno’s original answer. I did not try to mark this question a duplicate of the question of that answer only because it has been “closed as off-topic” and because numerous links in that answer meanwhile have become stale.