繁体   English   中英

如何在 Python 中执行 PGP(生成密钥、加密/解密)

[英]How to do PGP in Python (generate keys, encrypt/decrypt)

我正在用 Python 制作一个程序,通过安装程序分发给 Windows 用户。

该程序需要能够每天下载使用用户公钥加密的文件,然后对其进行解密。

所以我需要找到一个 Python 库,它可以让我生成公共和私人 PGP 密钥,并解密用公共密钥加密的文件。

这是 pyCrypto 会做的事情吗(文档模糊不清)? 还有其他纯 Python 库吗? 任何语言的独立命令行工具怎么样?

到目前为止我所看到的只是 GNUPG,但是在 Windows 上安装它会对注册表做一些事情并在任何地方抛出 dll,然后我不得不担心用户是否已经安装了它,如何备份他们现有的密钥环等。我宁愿只需有一个 python 库或命令行工具并自己管理密钥。

更新:pyME 可能有效,但它似乎与我必须使用的 Python 2.4 不兼容。

您不需要PyCryptoPyMe ,尽管这些软件包可能是好的 - 在 Windows 下构建时会遇到各种问题。 相反,为什么不避开兔子洞并做我所做的呢? 使用gnupg 1.4.9 您不需要在最终用户机器上进行完整安装 - 只gpg.exe发行版中的gpg.exeiconv.dll就足够了,您只需要将它们放在路径中的某个位置或使用完整的 Python 代码访问它们路径名。 不需要更改注册表,如果需要,所有内容(可执行文件和数据文件)都可以限制在一个文件夹中。

有一个模块GPG.py ,最初由 Andrew Kuchling 编写,由 Richard Jones 改进,由 Steve Traugott 进一步改进。 在此处可用,但按原样不适合 Windows,因为它使用os.fork() 虽然最初是PyCrypto一部分,但它完全独立于PyCrypto的其他部分,只需要 gpg.exe/iconv.dll 即可工作

我有一个版本( gnupg.py从Traugott的派生) GPG.py ,它使用了subprocess模块。 它在 Windows 下运行良好,至少就我的目的而言 - 我用它来执行以下操作:

  • 密钥管理 - 生成、列出、导出等。
  • 从外部来源导入密钥(例如从合作伙伴公司收到的公钥)
  • 加密和解密数据
  • 签名并验证签名

我拥有的模块现在不适合展示,因为它包含一些其他不应该存在的东西 - 这意味着我目前无法按原样发布它。 在某个时候,也许在接下来的几周内,我希望能够整理它,添加更多单元测试(例如,我没有任何用于签名/验证的单元测试)并发布它(或者在原始PyCrypto许可证或类似的商业友好许可证)。 如果你等不及了,去与Traugott的模块,并亲自对其进行修改-这不是太多的工作,使之与工作subprocess模块。

这种方法比其他方法(例如基于SWIG的解决方案,或需要使用MinGW / MSYS构建的解决方案)要少得多,我考虑并尝试了这些方法。 我对用其他语言(例如C# )编写的系统使用了相同的( gpg.exe / iconv.dll )方法,结果同样gpg.exe

PS 它适用于 Python 2.4 以及 Python 2.5 及更高版本。 没有用其他版本测试过,但我不认为有任何问题。

经过大量挖掘,我找到了一个对我有用的软件包。 虽然据说支持生成key,但是我没有测试。 但是我确实设法解密了使用 GPG 公钥加密的消息。 这个包的优点是它不需要机器上的 GPG 可执行文件,并且是 OpenPGP 的基于 Python 的实现(而不是可执行文件的包装器)。 我使用 GPG4win 和 kleopatra for windows 创建了私钥和公钥,请参阅下面的代码。

import pgpy
emsg = pgpy.PGPMessage.from_file(<path to the file from the client that was encrypted using your public key>)
key,_  = pgpy.PGPKey.from_file(<path to your private key>)
with key.unlock(<your private key passpharase>):
    print (key.decrypt(emsg).message)

虽然这个问题很老了。 我希望这对未来的用户有所帮助。

PyCrypto 支持 PGP - 尽管您应该对其进行测试以确保它符合您的规范。

尽管文档很难获得,但如果您查看 Util/test.py(模块测试脚本),您可以找到其 PGP 支持的基本示例:

if verbose: print '  PGP mode:',
obj1=ciph.new(password, ciph.MODE_PGP, IV)
obj2=ciph.new(password, ciph.MODE_PGP, IV)
start=time.time()
ciphertext=obj1.encrypt(str)
plaintext=obj2.decrypt(ciphertext)
end=time.time()
if (plaintext!=str):
    die('Error in resulting plaintext from PGP mode')
print_timing(256, end-start, verbose)
del obj1, obj2

此外,PublicKey/pubkey.py 提供了以下相关方法:

def encrypt(self, plaintext, K)
def decrypt(self, ciphertext):
def sign(self, M, K):
def verify (self, M, signature):
def can_sign (self):
    """can_sign() : bool
    Return a Boolean value recording whether this algorithm can
    generate signatures.  (This does not imply that this
    particular key object has the private information required to
    to generate a signature.)
    """
    return 1

PyMe确实声称与 Python 2.4 完全兼容,我引用:

PyMe 的最新版本(在撰写本文时)是 v0.8.0。 它的 Debian 二进制发行版是使用 SWIG v1.3.33 和 GCC v4.2.3 编译的,用于 GPGME v1.1.6 和 Python v2.3.5、v2.4.4 和 v2.5.2(当时以“不稳定”发行版提供)。 它的 Windows 二进制发行版是使用 SWIG v1.3.29 和 MinGW v4.1 编译的,用于 GPGME v1.1.6 和 Python v2.5.2(尽管安装了相同的二进制文件并且在 v2.4.2 中也能正常工作)。

我不确定你为什么说“它似乎与我必须使用的 Python 2.4 不兼容”——请具体说明?

是的,它确实作为 GPGME 上的半 Pythonic (SWIGd) 包装器存在——一旦你拥有一个基本上可以完成这项工作的 C 库,这是一种开发 Python 扩展的流行方式。

PyPgp有一个更简单的方法——这就是为什么它是一个单一的、简单的 Python 脚本:基本上它只是对命令行 PGP 命令进行“shell out”。 例如,解密只是:

def decrypt(data):
    "Decrypt a string - if you have the right key."
    pw,pr = os.popen2('pgpv -f')
    pw.write(data)
    pw.close()
    ptext = pr.read()
    return ptext

即,将加密后的密文写入pgpv -f的标准输入,读取 pgpv 的标准输出作为解密后的明文。

PyPgp 也是一个非常古老的项目,尽管它的简单性意味着让它与现代 Python 一起工作(例如,子进程而不是现在已弃用的 os.popen2)并不难。 但是您仍然需要安装PGP ,否则 PyPgp 不会做任何事情;-)。

M2Crypto有 PGP 模块,但我实际上从未尝试过使用它。 如果您尝试并有效,请告诉我(我是当前的 M2Crypto 维护者)。 一些链接:

更新: PGP 模块不提供生成密钥的方法,但大概可以使用较低级别的RSADSA等模块创建这些方法。 我不知道 PGP 内部,所以你必须挖掘细节。 此外,如果您知道如何使用 openssl 命令行命令生成这些,那么将其转换为 M2Crypto 调用应该相当容易。

正如其他人所指出的,PyMe 是对此的规范解决方案,因为它基于 GpgME,它是 GnuPG 生态系统的一部分。

对于 Windows,我强烈建议使用Gpg4win作为 GnuPG 发行版,原因有二:

它基于 GnuPG 2,其中包括gpg2.exe ,它可以(最后,我可能会添加:)按需启动gpg-agent.exe (gpg v1.x 不能)。

其次,它是 GnuPG 开发人员唯一的官方 Windows 版本。 例如,它完全从 Linux 交叉编译到 Windows,因此在准备它时没有使用任何非自由软件(对于安全套件非常重要:)。

仅使用导出的公钥文件进行签名,而无需密钥环。

使用 PGPy 0.5.2(纯 Python GPG RFC 实现):

key_fpath = './recipient-PUB.gpg'
     
rsa_pub, _ = pgpy.PGPKey.from_file(rkey_fpath)
rkey = rsa_pub.subkeys.values()[0]                                                                                                     
     
text_message = pgpy.PGPMessage.new('my msg')
encrypted_message = rkey.encrypt(text_message)
print encrypted_message.__bytes__()

使用 gpg 1.10.0(gpgme Python 绑定 - 前 PyME):

rkey_fpath = './recipient-PUB.gpg'
cg = gpg.Context()
rkey = list(cg.keylist(source = rkey_fpath))                                                                                                                
 
ciphertext, result, sign_result = cg.encrypt('my msg', recipients=rkey, sign=False, always_trust=True)
print ciphertext

for 循环中的一个简单基准测试表明,对于我系统上的这个简单操作,PGPy 比 gpgme Python 绑定快约 3 倍(请不要接受此声明,因为 X 比 Y 快:我将邀请您在您的环境中进行测试)。

暂无
暂无

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

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