如果使用用户密码加密用户密码,如何用java密码解密128位RC4 pdf文件

时间:2017-07-27 12:51:41

标签: java pdf itext

我有一个用所有者和用户密码锁定的PDF文件。我没有所有者密码,但我有用户密码。

我正在使用iText来解密文件

那么我应该如何解密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();
  }
}

1 个答案:

答案 0 :(得分:2)

使用您的代码和示例文件,遗憾的是我无法重现该问题:代码执行时不会抛出异常。

但它还没有做你想要的:结果文件仍然是加密的。因此,这里有一些信息。

如果您阅读Bruno's answer here到最后,您会在iText 5.3.5之前看到您的代码用于解密PDF文件。但同时,加密仍然存在。严格来说,确实更正确,毕竟代码无处要求iText放弃加密。

因此,在目前的iText 5版本中(我使用当前的5.5.12-SNAPSHOT维护版本),你需要做更多的事情,你必须愚弄iText认为PDF不是&加密,正如布鲁诺在答案中所说的那样。

不幸的是,您必须更改的PdfReader成员变量不是public。因此,你不能简单地设置它。

有问题的成员是protected。因此,您可以通过派生自己的PdfReader子类并使用其中的方法来进行更改来更改它。这已在Bruno的答案中得到证明,这里是非空用户密码的变体:

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();
}

或者你也可以使用反射:

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测试方法testDecryptAbc

PS:我知道这个答案几乎没有为Bruno's original answer添加任何内容。我没有试图将这个问题标记为该答案问题的重复,只是因为它已被关闭为非主题"并且因为那个答案中的许多链接已经变得陈旧。