用PGP/GPG签名的Python代码

12
我想要对Python代码进行(PGP/GPG)签名。是的,我已经阅读了此文和其他许多谈论保护和混淆Python代码的网站 - 这一切都不是我想要的。我不想混淆代码。 我希望客户和用户能够看到代码,他们可以修改代码、复制它并创建派生作品,我希望将软件发布在GPLv3下。 但我希望插件是“签名”的,这样它们在执行过程中就可以被视为是有信任度的。
在Python中是否可以实现这一点?我能否在检查其GPG签名后导入一个库? 最简单的方法是:检查文件的GPG签名,然后通过import导入它,否则引发异常。但这只适用于单文件导入,而不适用于目录python模块。
显然,如果客户更改程序中的GPG密钥或自己删除检查算法中的某些行,则所有内容都会消失 - 但这不是问题。他可以做任何他想做的事情 - 但这很愚蠢。 他想要的是可信度。 我希望他能通过将第三方插件复制到“插件”目录中来添加插件,并让程序检查插件的“可信度”,然后导入它。 (因此,他可以运行未签名的插件,但风险自负。)

2
我认为你应该仔细检查Python的“导入”系统,因为它允许你编写自定义的“导入钩子”。我的做法是:将插件提供为包含模块/包及其签名的“zip”文件。然后,导入首先会检查签名,如果正确,则可以将存档解压缩到临时目录中并从那里导入模块(或直接从“zip”中导入)。用户可以解压缩档案并进行修改。 - Bakuriu
@Bakuriu 很好的评论,那应该是一个答案。 - Eugene Mayevski 'Callback
这正是我先前的想法,使用一个压缩文件。这将是我的功能之一:从专用服务器下载签名的zip /其他“插件包”文件,检查gpg,解压缩它。好的,那么安装到专用的“插件”目录也应该由软件完成,如果我理解正确,那么问题就解决了。通过以root身份更改代码,系统管理员可以规避此问题。而我之前并不知道import hooks,非常感谢。 - nerdoc
哦,@Bakuriu,你能把那个也发成“答案”吗?这样我就可以标记它为正确答案了。如果你愿意的话,可以直接从你上面的评论中复制粘贴文本。 - nerdoc
2个回答

9
Python的 import机制已经提供了实现您所需的所有工具。您可以安装不同种类的import钩子来支持您的需求。
特别是,安装一个元路径钩子可能会更加方便,该钩子搜索“已签名模块”,并返回一个 Loader,该加载器能够从这个已签名格式中执行导入操作。
您的已签名插件的一个非常简单和方便的格式可以是一个包含以下内容的zip档案:
  1. 以模块/包形式表示的插件代码
  2. 上述代码的PGP签名
这样做有以下好处:
  • 你的加载器应该解压缩zip文件并检查其签名。如果匹配,则可以安全地加载插件,如果不匹配,则应询问用户是否信任插件(或中止)。
  • 如果用户想要修改插件,只需简单地解压缩zip归档文件,然后根据需要进行修改。
  • zip归档文件的导入已经在zipimport模块中实现。这意味着您无需从头编写加载器。

实际上,如果要将钩子代码减少到最小,只需验证签名,然后将zip归档文件的路径添加到sys.path中,因为Python即使不显式使用zipimport也会处理来自zip归档文件的导入。

使用此设计,您只需安装这些钩子,然后就可以像导入普通模块一样import插件,验证等操作将自动完成。


1
谢谢@Bakuriu,这正是我所需要的。 - nerdoc

3
我知道这是一个旧帖子,但我们已经开发出了一种新的解决方案。我们面临着同样的挑战——分发Python源代码,但防止黑客篡改代码。我们开发的解决方案是使用 signet http://jamercee.github.io/signet/ 创建我们应用程序的自定义加载器。
signet 的作用是扫描您的脚本及其依赖项,并创建 SHA1 哈希值。它将这些哈希值嵌入到自定义加载器中,然后将其与您的脚本一起交付给客户端。您的客户端运行加载器,在将控制权传递给您的脚本进行正常执行之前重新验证哈希值。如果有篡改,则会发出错误消息,并拒绝运行被篡改的代码。
Signet 是跨平台的,可以在 Windows、Unix、Linux、FreeBSD 等系统上运行。如果您部署到 Windows,加载器构建过程甚至可以应用您公司的代码证书,以对您的代码进行 100% 的验证。它还可以进行 PE 验证。
该代码是完全开源的,包括默认加载器模板的 C++ 源代码。您可以扩展加载器以进行其他验证,甚至在检测到代码篡改时采取行动(如撤销篡改...)。

2
嗯,SHA1是一种加密校验和,而不是签名。任何人都可以构建相同的校验和并将其放入软件中,对吧?你必须随着你的“插件”一起发布校验和 - 但攻击者防止修改插件代码并重新构建校验和呢?校验和只能防止意外的代码更改(例如通过下载错误),但不能防止篡改。所需的是类似GPG的非对称密钥。软件知道公钥,并使用私钥对插件进行签名。这无法被攻击者更改。Linux软件包(rpm / deb)就是用这种方式签名的。 - nerdoc
嗯。一个“通用”的解决方案将是公钥签名。我需要在Linux上运行这个... - nerdoc
据我所知,Linux 上没有“证书存储”。没有它,就无法验证信任链。黑客可以剥离您的证书,插入自己签名的证书(甚至伪造您的组织名称),这将欺骗所有人。我们找到的最接近的是 signelf(http://sourceforge.net/projects/signelf/),但是如果没有一种验证链的方法,它并不比仅依赖代码哈希更好。当然,如果您知道解决此问题的方法-我很想知道,以便我们可以尽快将其纳入 signet! - user590028
并不完全是这样。你说的是有一条信任链。如果你不信任操作系统(证书存储),你就不能信任任何人。例如,在Linux下,Debian软件包使用GPG私钥进行签名。只要黑客没有root权限并更改了本地系统中的公共Debian密钥,我认为可以比任何其他东西都更加信任已签名的软件包。通过调用WinVerifyTrust函数,你信任操作系统。但是你无法确定没有人入侵了Windows系统并绕过了WinVerifyTrust函数,对吧? - nerdoc
我的意思是:如果你想安装恶意插件,那么你无法真正防止将其安装到你的系统中。我试图实现的是,在我拥有一个干净的系统(TM)时,确保加载已签名和正确的插件。这应该可以通过PGP签名完美地实现。如果我的Python解释器被黑客攻击,那么这里的一切都没有意义。 - nerdoc
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接