代码签名新时代:Sigstore技术原理与应用指南

本文深入解析Sigstore代码签名服务的技术架构,涵盖Fulcio证书颁发机构与Rekor透明日志的协同工作机制,详细介绍基于OIDC身份验证的密钥管理方案,并通过实际演示展示如何通过sigstore-python实现代码签名与验证。

我们现在为代码签名 - The Trail of Bits博客

William Woodruff
2022年11月8日
开源, 供应链, 生态系统安全, 密码学

两周前,Sigstore宣布其免费且与生态系统无关的软件签名服务正式全面可用,为开发者提供了一种签名、验证和保护其软件项目及所依赖组件的方式。Trail of Bits非常荣幸能参与该项目,并在首届SigstoreCon上介绍了我们的工作。

虽然有机会谈论Sigstore令人兴奋,但我们并不想止步于此。我们认为Sigstore是实现可访问软件签名的关键且急需的一步,这已成为软件供应链管理和安全的关键组成部分。

以下是Trail of Bits为Sigstore生态系统整体发展做出(并将继续做出!)贡献的一些方式。系好安全带!

什么是Sigstore?

对于不熟悉的人:Sigstore是一个Linux基金会项目,由大型科技公司和知名学术机构贡献,专注于一个简单的使命:让每个人都能进行代码签名和验证。

其实现方式则稍微复杂一些。Sigstore由两个核心服务组成:

  • Fulcio:一个公共根证书颁发机构,为授权身份颁发短期签名证书,并将这些证书提交到证书透明度日志;
  • Rekor:用于签名产物的透明度和时间戳服务,具有强大的完整性保证。

Fulcio和Rekor共同允许程序员创建短期签名证书,公开提交这些证书(使攻击者更难秘密获取有效证书),使用这些证书签名产物,然后公开提交生成的签名(再次使秘密攻击者更难得逞)。

这两个服务使用标准格式和协议(x509v3和CT),以便与现有的验证方案和机制互操作。因此,Sigstore已经被纳入现有工作流程:您现在就可以使用gitsign通过Sigstore签名git提交,而无需对git本身进行任何修改!

Sigstore的特殊之处是什么?

Sigstore基本上是一个PKI生态系统,但专门用于短期签名证书。

但赋予Sigstore独特魅力的是身份:Fulcio是一个根CA,但仅适用于开发人员或机器身份。更准确地说,Fulcio不会让任何证书签名请求通过:请求必须附带OpenID Connect(OIDC)令牌,以证明预期身份。该身份随后被嵌入签名证书,允许任何人针对该证书验证签名。

当Fulcio收到OIDC令牌(实际上只是一个JSON Web令牌)时,它会使用OIDC的.well-known查找协议根据其声称来自的服务进行验证。目前支持一些服务(具有已知高质量IdP),其中包括:

  • GitHub:可以证明个人电子邮件身份(对应GitHub账户),以及工作流操作的机器身份。
  • Google和Microsoft:支持个人电子邮件身份,包括非服务账户。换句话说:只要您拥有Google或Microsoft账户,就可以证明与之关联的电子邮件,即使该电子邮件不受Google或Microsoft控制。
  • Kubernetes:基于云的Kubernetes实例(例如由AWS、Azure和Google Cloud提供的实例)可以证明其集群身份。

这种身份优先的方法颠覆了代码签名:验证者采用他们信任的公共身份,并简单地向公共签名日志询问该身份是否已签名他们想要使用的产物,而不是手动建立对公钥背后身份的信任(这是基于PGP的代码签名的常态)。最终结果:默认使用强大的密码学原语,不再有脆弱的密钥管理(在任何一端),不再有破碎的信任网络,以及一个保持所有签名方诚实的可公开访问的透明度日志。

此模型还支持强大的抗滥用技术,如“无密钥”签名:用户无需持有长期签名密钥,而是可以创建短期密钥,向Fulcio请求证书,并在所有签名操作完成后丢弃它。密钥从不离开内存且从不重复使用,极大减少了密钥被盗的威胁(和爆炸半径)。

如何使用Sigstore?

抽象来看,Sigstore的“身份优先”模型可能有点令人费解。以下是一个使用示例:

首先,我们安装sigstore-python,这是Sigstore的官方(由Trail of Bits维护!)Python实现:

1
$ python -m pip install sigstore

安装后,我们可以使用它来签名本地文件(您可以签名任何内容,包括任何语言的Python包或分发版!):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22

等待浏览器交互...
使用临时证书:
-----BEGIN CERTIFICATE-----
MIICwTCCAkegAwIBAgIUZr4/MflYaUb/SSw0CgNj+qLZDhMwCgYIKoZIzj0EAwMw
NzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRl
cm1lZGlhdGUwHhcNMjIxMDI4MTYzMjQzWhcNMjIxMDI4MTY0MjQzWjAAMHYwEAYH
KoZIzj0CAQYFK4EEACIDYgAEVBG9SWAO0pkbhrsKtDUN4Il5OK115yp+Ai5GiDYW
V1obpF1Ih+/NrtTDN+tdkop0T6Z8eotVjpnyrFpc4TbA6okIZ2eo6oFwRD3tn/mG
4BFPgm4O4Nvgih+f75M845c1o4IBSTCCAUUwDgYDVR0PAQH/BAQDAgeAMBMGA1Ud
JQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQWBBRE3hH5uBNf4l/EDxedz0aNNAZX+zAf
BgNVHSMEGDAWgBTf0+nPViQRlvmo2OkoVaLGLhhkPzAjBgNVHREBAf8EGTAXgRV3
aWxsaWFtQHlvc3Nhcmlhbi5uZXQwLAYKKwYBBAGDvzABAQQeaHR0cHM6Ly9naXRo
dWIuY29tL2xvZ2luL29hdXRoMIGKBgorBgEEAdZ5AgQCBHwEegB4AHYACGCS8ChS
/2hF0dFrJ4ScRWcYrBY9wzjSbea8IgY2b3IAAAGEH3BI7gAABAMARzBFAiEAnrGB
RDQMHW26GT4H/nCvTBQ7RzBI3ix8rRewG6Bii10CIBnjNsSYBhNB77nNmAheoxxj
XQWJuQ4n2iQu9FB4AGeKMAoGCCqGSM49BAMDA2gAMGUCMQDaV/a8myBO5yKDBTvS
fM9ziqC1zOiDrXXg+k4lVg02idTHeukbUZTKsROzOsPSRfUCMCsp30CTXrJPBUfN
dCxmp44zCE7/yGkNCu+5waxPhOI7mXrfQ7FqzmZ0Z5cs9H/CiA==
-----END CERTIFICATE-----

透明度日志条目创建于索引:6052228

这直接就能工作™。在幕后,Sigstore正在:

  1. 创建新的本地临时密钥对;
  2. 通过交互式OAuth2流程或环境凭据检测检索OIDC身份令牌;
  3. 向Fulcio提交证书签名请求,结合OIDC令牌和临时密钥对私钥的拥有证明;
  4. 从Fulcio接收SCT、证书和中间链,并验证所有三项;
  5. 实际使用私钥为输入签名;
  6. 将签名、输入的哈希和签名证书发布到Rekor;
  7. 本地保存所有必要的验证材料,以供后续分发和验证。

然后,我们可以使用任何普通的x509检查工具(如openssl x509)来检查证书,并确认其扩展包含我们签名时使用的身份的Sigstore特定条目。简化为仅证书扩展:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Extended Key Usage:
                Code Signing
            X509v3 Subject Key Identifier:
                96:96:0F:0F:FB:19:76:15:15:D8:82:BB:8A:04:07:14:E8:85:EA:DA
            X509v3 Authority Key Identifier:
                DF:D3:E9:CF:56:24:11:96:F9:A8:D8:E9:28:55:A2:C6:2E:18:64:3F
            X509v3 Subject Alternative Name: critical
                email:william.woodruff@trailofbits.com
            1.3.6.1.4.1.57264.1.1:
                https://accounts.google.com
            CT Precertificate SCTs:
                Signed Certificate Timestamp:
                    Version   : v1 (0x0)
                    Log ID    : 08:60:92:F0:28:52:FF:68:45:D1:D1:6B:27:84:9C:45:
                                67:18:AC:16:3D:C3:38:D2:6D:E6:BC:22:06:36:6F:72
                    Timestamp : Oct 28 16:44:57.279 2022 GMT
                    Extensions: none
                    Signature : ecdsa-with-SHA256
                                30:44:02:20:1E:FB:5C:97:4D:BB:EC:A2:51:14:9A:A7:
                                FC:EB:59:9B:10:AA:37:5F:13:E0:D0:D3:ED:4D:3D:36:
                                18:E1:53:38:02:20:5C:67:61:F4:2E:15:3D:25:14:79:
                                7F:94:F7:5F:A2:9D:2F:15:71:B9:15:29:AF:7A:9F:3D:
                                09:77:3B:C1:5E:68

当然,这仅仅是人工检查。要实际根据其签名产物验证文件,我们可以使用sigstore verify:

1
2
3

$ python -m sigstore verify \
    --cert-email william.woodruff@trailofbits.com \

再次,这直接就能工作™:

  1. 我们检查证书的SAN和颁发者扩展是否与我们预期的身份对应(我的电子邮件地址,由Google的IdP证明);

  2. 我们检查Rekor中是否有与当前验证材料匹配的记录,然后检查结果记录的Merkle包含证明和签名条目时间戳签名;

  3. 最后,我们确认签名在证书有效时被集成到Rekor中。

最后两个Rekor步骤可以通过Chainguard优秀的Rekor Web界面额外可视化:

综合起来,这些检查提供了强有力的证明,表明控制我电子邮件身份的人(即我)在特定时间签名了一个产物,而我和验证方都无需直接管理密钥材料!

光明的现在与未来

既然Sigstore已全面可用,我们可以加速将其集成到目前缺乏强大代码签名模型的生态系统中的计划。我们已经在这方面取得了一些进展,包括:

  • CPython本身现在使用Sigstore签名发布,使用我们自己的sigstore-python创建。您今天就可以使用上述完全相同的sigstore verify命令验证它们!
  • 用于签名产物并自动将签名附加到发布的GitHub Action,全部使用GitHub Actions内置的OIDC提供程序!

也就是说,还有很多工作需要完成:

  • sigstore-python需要大量工作才能达到1.0稳定版本,包括致力于稳定可导入的Python API。
  • 需要关键的UX工作,以确保用户理解在验证身份签名时他们到底在做什么。
  • 作为Sigstore项目对可用性和弹性的整体承诺的一部分,我们正在开发一个一致性测试套件,每个独立的Sigstore客户端实现都需要通过。我们将在未来几个月与每个实现合作,帮助他们将其集成到他们的CI系统中。

Sigstore已经在许多生态系统中成功使用,但我们在Trail of Bits特别感兴趣的是它在PyPI上的使用以及最终在像pip这样的包安装程序中的最终使用。我们正在积极与Python打包社区合作,将Sigstore支持引入PyPI!

总的来说,我们认为Sigstore有一个极其光明的未来,我们很高兴能成为其中的一部分。如果您对Sigstore和我们一样兴奋,那么我们很乐意收到您的来信!

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计