如何使用所有者密码解密 PDF 文档? [英] How can I decrypt a PDF document with the owner password?

查看:20
本文介绍了如何使用所有者密码解密 PDF 文档?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要能够从某些 PDF 文档中删除安全/加密,最好使用 itextsharp 库.这曾经是可能的(如何通过使用 c# 提供文件的密码作为参数来解密 pdf 文件?),但最近的 更改 库意味着解决方案不再有效.

I need to be able to remove the security/encryption from some PDF documents, preferably with the itextsharp library. This used to be possible (How to decrypt a pdf file by supplying password of the file as argument using c#?), but a more recent change to the library means that solution no longer works.

我知道这可以通过 Aspose PDF 库来完成 (example),但这似乎是一个昂贵的选择.

I know this can be done with the Aspose PDF library (example), but that appears to be an expensive option.

编辑

所以一直以来我都认为我拥有用于​​测试的文档的所有者密码.但实际上我的密码是 user 密码.原因我认为这是所有者密码是因为它工作,因为所有者密码和其他值不起作用.我相信用户密码代替用户密码的原因是 PdfReader.unethicalreading 字段被设置为 true(这是一个全局标志,碰巧是在代码中的其他地方设置).

So all this time I thought I was in possession of the owner password for the document I was using to test this. But in fact the password I had was the user password. The reason I thought it was the owner password was because it worked as the owner password and other values did not work. I believe the reason the user password worked in place of the user password was the fact that the PdfReader.unethicalreading field was set to true (it's a global flag that happened to be set elsewhere in code).

推荐答案

为了测试加密 PDF 文件的代码,我们需要一个已加密的示例 PDF.我们将使用 EncryptPdf 示例创建这样一个文件.

In order to test code to encrypt a PDF file, we need a sample PDF that is encrypted. We'll create such a file using the EncryptPdf example.

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    stamper.setEncryption("Hello".getBytes(), "World".getBytes(),
        PdfWriter.ALLOW_PRINTING, PdfWriter.ENCRYPTION_AES_128 | PdfWriter.DO_NOT_ENCRYPT_METADATA);
    stamper.close();
}

使用此代码,我创建了一个加密文件 hello_encrypted.pdf将在第一个示例中使用,演示如何解密文件.

With this code, I create an encrypted file hello_encrypted.pdf that I will use in the first example demonstrating how to decrypt a file.

您最初的问题听起来像是如何使用所有者密码解密 PDF 文档?"

Your original question sounds like "How can I decrypt a PDF document with the owner password?"

这很容易.DecryptPdf 示例向您展示了如何执行此操作:

That is easy. The DecryptPdf example shows you how to do this:

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src, "World".getBytes());
    System.out.println(new String(reader.computeUserPassword()));
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    stamper.close();
    reader.close();
}

我们创建一个 PdfReader 实例,将所有者密码作为第二个参数传递.如果我们想知道用户密码,我们可以使用 computeUserPassword() 方法.如果我们想要加密文件,我们可以使用我们知道的所有者密码和我们计算的用户密码,并使用 setEncryption() 方法重新引入安全性.

We create a PdfReader instance passing the owner password as the second parameter. If we want to know the user password, we can use the computeUserPassword() method. Should we want to encrypt the file, than we can use the owner password we know and the user password we computed and use the setEncryption() method to reintroduce security.

然而,由于我们没有这样做,所有安全措施都被删除了,这正是您想要的.这可以通过查看 hello.pdf 文档来检查.

However, as we didn't do this, all security is removed, which is exactly what you wanted. This can be checked by looking at the hello.pdf document.

有人可能会争辩说,您的问题属于它不起作用"的问题,只能用它对我有用"来回答.可以投票结束您的问题,因为您没有提供可用于重现问题的代码示例,而任何人都可以提供证明您错的代码示例.

One could argue that your question falls in the category of "It doesn't work" questions that can only be answered with an "it works for me" answer. One could vote to close your question because you didn't provide a code sample that can be use to reproduce the problem, whereas anyone can provide a code sample that proves you wrong.

幸运的是,我可以在字里行间阅读,所以我又做了一个例子.

Fortunately, I can read between the lines, so I have made another example.

许多 PDF 是在没有用户密码的情况下加密的.任何人都可以打开它们,但添加了加密以强制执行某些限制(例如,您可以查看文档,但不能打印它).在这种情况下,只有一个所有者密码,如EncryptPdfWithoutUserPassword 示例:

Many PDFs are encrypted without a user password. They can be opened by anyone, but encryption is added to enforce certain restrictions (e.g. you can view the document, but you can not print it). In this case, there is only an owner password, as is shown in the EncryptPdfWithoutUserPassword example:

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    stamper.setEncryption(null, "World".getBytes(),
        PdfWriter.ALLOW_PRINTING, PdfWriter.ENCRYPTION_AES_128 | PdfWriter.DO_NOT_ENCRYPT_METADATA);
    stamper.close();
    reader.close();
}

现在我们得到一个加密的 PDF,但无需用户密码即可打开:hello_encrypted2.pdf

Now we get a PDF that is encrypted, but that can be opened without a user password: hello_encrypted2.pdf

如果我们想操作 PDF,我们仍然需要知道所有者密码.如果我们不传递密码,那么 iText 将理所当然地抛出异常:

We still need to know the owner password if we want to manipulate the PDF. If we don't pass the password, then iText will rightfully throw an exception:

Exception in thread "main" com.itextpdf.text.exceptions.BadPasswordException: Bad user password
    at com.itextpdf.text.pdf.PdfReader.readPdf(PdfReader.java:681)
    at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.java:181)
    at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.java:230)
    at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.java:207)
    at sandbox.security.DecryptPdf.manipulatePdf(DecryptPdf.java:26)
    at sandbox.security.DecryptPdf.main(DecryptPdf.java:22)

但如果我们不记得所有者密码怎么办?如果 PDF 是由第三方制作的,而我们不想尊重该第三方的意愿怎么办?

But what if we don't remember that owner password? What if the PDF was produced by a third party and we do not want to respect the wishes of that third party?

在这种情况下,您可以故意不道德并更改静态 unethicalreading 变量的值.这是在 DecryptPdf2 示例中完成的:

In that case, you can deliberately be unethical and change the value of the static unethicalreading variable. This is done in the DecryptPdf2 example:

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

如果文档是使用用户加密的,则此示例将不起作用,在这种情况下,您必须至少传递一个密码,所有者密码"或用户密码"(您只能使用用户"密码访问 PDF 是不道德阅读的副作用).如果只引入了 所有者 密码,如果您更改 unethicalreading 标志,iText 不需要该所有者密码来操作 PDF.

This example will not work if the document was encrypted with a user and an owner password, in that case, you will have to pass at least one password, either the "owner password" or the "user password" (the fact that you have access to the PDF using only the "user" password is a side-effect of unethical reading). If only an owner password was introduced, iText does not need that owner password to manipulate the PDF if you change the unethicalreading flag.

然而:在这种情况下,iText 中曾经有一个错误也会删除所有者密码.这不是理想的行为.在第一个 PdfDecrypt 示例中,我们看到可以检索用户密码(如果存在用户密码),但无法检索所有者密码.这真的是秘密.对于您所指的旧版 iText,在操作文件后,所有者密码已从文件中删除,并且该所有者密码将永远丢失.

However: there used to be a bug in iText that also removed the owner password(s) in this case. That is not the desired behavior. In the first PdfDecrypt example, we saw that we can retrieve the user password (if a user password was present), but there is no way to retrieve the owner password. It is truly secret. With the older versions of iText you refer to, the owner password was removed from the file after manipulating it, and that owner password was lost for eternity.

我已经修复了这个错误,修复是在 5.3.5 版中.因此,现在保留了所有者密码.您可以通过查看 hello2.pdf 来检查这一点,这是我们解密的文件以不道德"的方式.(如果有所有者和用户密码,则两者都会保留.)

I have fixed this bug and the fix is in release 5.3.5. As a result, the owner password is now preserved. You can check this by looking at hello2.pdf, which is the file we decrypted in an "unethical" way. (If there was an owner and a user password, both are preserved.)

根据这项研究,我假设您的问题不正确.您想问:如何在没有所有者密码的情况下解密 PDF 文档?"或如何使用 用户 密码解密 PDF?"

Based on this research, I am making the assumption that your question is incorrect. You meant to ask: "How can I decrypt a PDF document without the owner password?" or "How can I decrypt a PDF with the user password?"

取消修复一个我曾经修复过的错误是没有意义的.我们不会恢复旧 iText 版本的(错误)行为,但这并不意味着您无法实现您想要的.您只需让 iText 认为 PDF 未加密即可.

It doesn't make sense to unfix a bug that I once fixed. We will not restore the (wrong) behavior of the old iText versions, but that doesn't mean that you can't achieve what you want. You'll only have to fool iText into thinking that the PDF wasn't encrypted.

这显示在 DecryptPdf3 示例中:

class MyReader extends PdfReader {
    public MyReader(String filename) throws IOException {
        super(filename);
    }
    public void decryptOnPurpose() {
        encrypted = false;
    }
}
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    MyReader.unethicalreading = true;
    MyReader reader = new MyReader(src);
    reader.decryptOnPurpose();
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    stamper.close();
    reader.close();
}

我们现在使用的是 PdfReader 的自定义子类,而不是 PdfReader.我将它命名为 MyReader 并添加了一个额外的方法,允许我将 encrypted 变量设置为 false.

Instead of PdfReader, we are now using a custom subclass of PdfReader. I have named it MyReader and I have added an extra method that allows me to set the encrypted variable to false.

我仍然需要使用 unethicalreading 并且在创建 MyReader 实例之后,我必须欺骗这个读者认为原始文件没有通过使用decryptOnPurpose() 方法.

I still need to use unethicalreading and right after creating the MyReader instance, I have to fool this reader into thinking that the original file wasn't encrypted by using the decryptOnPurpose() method.

这导致文件 hello3.pdf 这是一个文件不再使用所有者密码加密.这个例子甚至可以用来从一个用用户和所有者密码加密的文件中删除所有密码,只要你有用户密码.

This results in the file hello3.pdf which is a file that is no longer encrypted with an owner password. This example can even be used to remove all passwords from a file that is encrypted with a user and an owner password as long as you have the user password.

我将用评论来结束这个答案,以回答您关于 Aspose 不是免费的评论.您知道 iText 是免费软件,但您也应该知道 free 不是 for free 的同义词.请阅读我对以下问题的回答以获取更多信息:iText Java 库是免费的还是需要支付任何费用?

I'll conclude this answer with a comment in answer to your remark about Aspose not being free of charge. You know that iText is free software, but you should also know that free isn't a synonym of for free. Please read my answer to the following question for more info: Is iText Java library free of charge or have any fees to be paid?

这篇关于如何使用所有者密码解密 PDF 文档?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆