【问题标题】:PDF - set password protected print, copy, paste options?python: pdf - 设置受密码保护的打印、复制、粘贴选项?
【发布时间】:2012-10-18 01:45:30
【问题描述】:

您好,我正在寻找一个 python 库,它允许我在一些现有的 pdf 上设置受密码保护的打印、复制、粘贴选项

我查看了 reportlab pdfencrypt 模块:这正是我需要的选项,但开源版本受到严格限制 - 甚至无法设置真实密码,并且许可证不是一个选项(超过 1000 英镑/年) -这将是相对较低的数量(

任何建议都非常感谢!

【问题讨论】:

  • 您对安全性的关注程度如何? PDF加密和使用限制很容易被破解。请记住,绕过 PDF DRM 所需要的只是谷歌搜索“pdf 破解”。
  • 是的,不用担心安全性 - 显然使用我使用的工具解密 pdf 是微不足道的。然而,大约 90% 的用户不会费心破解,而且没有办法阻止那些确实想要破解的用户 - 除了执行更严厉的措施,例如创建付费墙等。

标签: python security pdf reportlab


【解决方案1】:

PyPDF 允许encrypting PDF 文件。

【讨论】:

  • 是的,但没有选项 re:打印、复制、粘贴等 - 请参阅:pybrary.net/pyPdf/…
  • 您可能必须使用命令行工具,正如@user1202136 所建议的那样。我不知道有任何免费的 Python 包可以做到这一点。
【解决方案2】:

您是否尝试过 PDF 工具包,命令行界面 (pdftk)?

http://www.pdflabs.com/docs/pdftk-cli-examples/

【讨论】:

【解决方案3】:

Laaate 回答,但我想开始贡献...

在 pdf.py 文件中,在 encypt() 方法中,更改标志:

    # permit everything:
    P = -1

到:

    # prevent everything:
    P = -3904

这将阻止除简单查看之外的所有功能。请务必传递一个不同的所有者密码。

【讨论】:

  • 你能解释一下吗?这个 pdf.py 文件在哪里?你用的是哪个库??
  • @AbhijithK 它来自 PyPDF2
【解决方案4】:

你(就像我一样)一定想到 - WTF 是来自 Kevin 的 answer"-3904"

请让自己舒服——我有答案)。

我在 PDF 1.6 参考中找到了它。你可以在这里得到它:https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdf_reference_archive/PDFReference16.pdf

第 3.5 节,第 99 页:

32 位整数,包含一组指定访问权限的标志 使用用户打开文档时应授予权限 使用权。表 3.20 显示了这些标志的含义。位位置 标志字内的编号从 1(低位)到 32 (高阶)。任何位置的 1 位启用相应的访问 允许。哪些位是有意义的,在某些情况下它们是如何有意义的 解释,取决于安全处理程序的修订号 (在加密字典的 R 条目中指定)。

*注意:PDF 整数对象在内部以带符号的二进制补码形式表示。由于所有保留的高位标志位 加密字典的 P 值必须为 1,该值 必须指定为负整数。例如,假设 安全处理程序的修订版 2,值 -44 允许打印和 复制但不允许修改内容和注释。

所以,P 是许可!请检查该文档中的表格。 -44 在位表示中是 11010100

我是这样做的(允许打印和复制,但不允许修改内容和注释):

from hashlib import md5

from PyPDF4 import PdfFileReader, PdfFileWriter
from PyPDF4.generic import NameObject, DictionaryObject, ArrayObject, \
    NumberObject, ByteStringObject
from PyPDF4.pdf import _alg33, _alg34, _alg35
from PyPDF4.utils import b_


def encrypt(writer_obj: PdfFileWriter, user_pwd, owner_pwd=None, use_128bit=True):
    """
    Encrypt this PDF file with the PDF Standard encryption handler.

    :param str user_pwd: The "user password", which allows for opening
        and reading the PDF file with the restrictions provided.
    :param str owner_pwd: The "owner password", which allows for
        opening the PDF files without any restrictions.  By default,
        the owner password is the same as the user password.
    :param bool use_128bit: flag as to whether to use 128bit
        encryption.  When false, 40bit encryption will be used.  By default,
        this flag is on.
    """
    import time, random
    if owner_pwd == None:
        owner_pwd = user_pwd
    if use_128bit:
        V = 2
        rev = 3
        keylen = int(128 / 8)
    else:
        V = 1
        rev = 2
        keylen = int(40 / 8)
    # permit copy and printing only:
    P = -44
    O = ByteStringObject(_alg33(owner_pwd, user_pwd, rev, keylen))
    ID_1 = ByteStringObject(md5(b_(repr(time.time()))).digest())
    ID_2 = ByteStringObject(md5(b_(repr(random.random()))).digest())
    writer_obj._ID = ArrayObject((ID_1, ID_2))
    if rev == 2:
        U, key = _alg34(user_pwd, O, P, ID_1)
    else:
        assert rev == 3
        U, key = _alg35(user_pwd, rev, keylen, O, P, ID_1, False)
    encrypt = DictionaryObject()
    encrypt[NameObject("/Filter")] = NameObject("/Standard")
    encrypt[NameObject("/V")] = NumberObject(V)
    if V == 2:
        encrypt[NameObject("/Length")] = NumberObject(keylen * 8)
    encrypt[NameObject("/R")] = NumberObject(rev)
    encrypt[NameObject("/O")] = ByteStringObject(O)
    encrypt[NameObject("/U")] = ByteStringObject(U)
    encrypt[NameObject("/P")] = NumberObject(P)
    writer_obj._encrypt = writer_obj._addObject(encrypt)
    writer_obj._encrypt_key = key


unmeta = PdfFileReader('my_pdf.pdf')

writer = PdfFileWriter()
writer.appendPagesFromReader(unmeta)
encrypt(writer, '1', '123')

with open('my_pdf_encrypted.pdf', 'wb') as fp:
    writer.write(fp)

如果你喜欢我的回答,请投票;)。

【讨论】:

  • 似乎应该提供用户密码。但是如果我不想要用户密码,需要做什么?
猜你喜欢
  • 1970-01-01
  • 2021-10-16
  • 1970-01-01
  • 1970-01-01
  • 2011-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
相关资源
最近更新 更多