简体   繁体   English

如果用用户密码和所有者密码加密,如何用用户密码解密Java中的128bit RC4 pdf文件

[英]How to decrypt 128bit RC4 pdf file in java with user password if it is encrypted with user as well as owner password

I have a PDF file locked with owner and user password. 我有一个用所有者和用户密码锁定的PDF文件。 I don't have the owner password but I have the user password. 我没有所有者密码,但有用户密码。

I am using iText to decrypt the file 我正在使用iText解密文件

So how should I decrypt the PDF file. 那么我该如何解密PDF文件。

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. 如果您从头到尾都阅读Bruno的答案 ,您会发现您的代码用于在iText 5.3.5之前解密PDF文件。 Meanwhile, though, the encryption is kept. 同时,尽管如此,加密仍然保留。 Strictly speaking that indeed is more correct, after all the code nowhere asks iText to drop the encryption. 严格来说,这确实是更正确的,毕竟所有代码都没有要求iText放弃加密。

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. 因此,在当前的iText 5版本(我使用的是当前的5.5.12-SNAPSHOT维护版本)中,您需要做更多的工作, 您必须愚弄iText认为PDF没有像Bruno所说的那样被加密 。他的答案。

Unfortunately the member variable of PdfReader you have to change to do that is not public . 不幸的是,您必须更改的PdfReader成员变量不是public Thus, you cannot simply set it. 因此,您不能简单地设置它。

The member in question is protected . 有关成员protected Thus, you can change it by deriving your own PdfReader subclass and use a method in it to do the change. 因此,您可以通过派生自己的PdfReader子类并使用其中的方法进行更改来进行更改。 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 ) DecryptUserOnly.java测试方法testDecryptAbc


PS: I am aware that this answer hardly adds anything to Bruno's original answer . PS:我知道这个答案几乎不会增加Bruno的原始答案 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. 我之所以没有将这个问题标记为该答案的重复项,仅仅是因为它已被“关闭为题外话”,并且与此同时,该答案中的许多链接都已过时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM