20

更新

我已将我用于此的脚本发布到 StackExchange 代码审查网站。

我最初的问题是有没有办法可以用 X.509 证书和时间戳签署 Git 提交?. 有一段时间,我以为我只能得到我用我的 X.509 证书签名的东西,由受信任的第三方加盖时间戳。不是这种情况。带有 X.509 证书的数字签名和受信任的时间戳是相互排斥的。我已经更新了我的问题以反映这一点。

正如 VonC 所指出的,使用 X.509 证书签署 Git 提交不会增加任何价值。由于 Git 的内置支持,使用 GPG 密钥是一个更好的选择。

我接受了 Greg 的回答,因为它最接近我的要求,尽管我最初的问题有点模棱两可。正如 Greg 指出的那样,如果您可以证明您在某个时间点知道提交哈希,则可以保证您知道当时哈希所针对的存储库内容,并且无需在存储库中存储任何额外的数据。时间戳数据可以存储在任何地方。

可以使用openssl(v1.0.0+) 并curl为提交哈希请求 RFC3161 时间戳。

请求时间戳

您需要为此提供一些信息:

  • URL - 一个 RFC3161 时间戳服务
  • REV - 您想要时间戳记的修订版(哈希)。必须是完整的哈希。
CONTENT_TYPE="Content-Type: application/timestamp-query"
ACCEPT_TYPE="Accept: application/timestamp-reply"

openssl ts -query -cert -digest "$REV" -sha1 \
    | curl -s -H "$CONTENT_TYPE" -H "$ACCEPT_TYPE" --data-binary @- $URL

以上会将签名的时间戳输出到stdout. 如果时间戳服务拒绝请求,它也可能会输出错误。

验证时间戳

这与请求时间戳非常相似,但您还需要:

  • CAFILE - 从时间戳服务返回根 CA 的证书链

时间戳服务应该使用由受信任的机构颁发的证书对时间戳进行签名。如果没有,您的时间戳就没有多少可信度。如果您无法找到或创建合适的证书链,请尝试使用cacert.pemcurl. 它在这里

下面的代码片段假设一个现有的、签名的时间戳回复被传递给stdin. 应该可以将上述请求直接传送到下面的验证命令中。如果您将请求的响应存储在变量中,则可能需要对其进行 base64 编码/解码 ( man base64)。

openssl ts -verify -digest "$REV" -in /dev/stdin -CAfile "$CAFILE"

如果您检查回复,您会注意到请求摘要与使用的 Git 修订相匹配。您可以使用此命令检查纯文本版本的回复。

openssl ts -reply -in /dev/stdin -text

这是一个回复示例,我在顶部添加了 Git 修订。

--------------------------------------------------------------------------------
Revision: 871d715e5c072b1fbfacecc986f678214fa0b585
--------------------------------------------------------------------------------
Status info:
Status: Granted.
Status description: unspecified
Failure info: unspecified

TST info:
Version: 1
Policy OID: 1.3.6.1.4.1.6449.2.1.1
Hash Algorithm: sha1
Message data:
    0000 - 87 1d 71 5e 5c 07 2b 1f-bf ac ec c9 86 f6 78 21   ..q^\.+.......x!
    0010 - 4f a0 b5 85                                       O...
Serial number: 0xB2EA9485C1AFF55C6FFEDC0491F257C8393DB5DC
Time stamp: Aug 15 08:41:48 2012 GMT
Accuracy: unspecified
Ordering: no
Nonce: 0x615F0BF6FCBBFE23
TSA: DirName:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO Time Stamping Signer
Extensions:

其他注意事项

许多时间戳服务要求用户为脚本签名请求添加延迟。确保您了解您计划使用的服务是否需要它。在撰写本文时,我使用的 Comodo 要求脚本请求之间有 15 秒的延迟。我选择使用 Comodo 的唯一原因是我从那里购买了我的代码签名证书。

Git 笔记似乎是存储签名时间戳回复的明显选择,但我并没有完整的解决方案来发布。我现在被困在这个问题上。

我的原始问题和更新如下。


我希望能够证明我的 Git 提交何时发生并且我的存储库的历史没有被重写。它不必是每个提交。一天一次或一周一次就足够了。有推荐的方法吗?

我知道我可以使用 GPG 密钥签署 Git 提交,但我想知道是否有一种方法可以使用 X.509 证书和使用在线时间戳服务(如http://timestamp.comodoca)签署我的提交.com/rfc3161

如果不是,是否每天一次将当前修订版转储git rev-parse --verify HEAD到文本文件中,签署该文件并提交足以证明(大致)何时编写我的代码?

为清晰添加信息

我知道 Git 可以保证存储库的完整性,但是据我所知,如果我控制了存储库,第三方将不得不相信我没有重写存储库的历史或回滚我的时钟并且创建一个完全伪造的存储库只是为了“证明”我的代码比实际旧?我也不想公开发布我的存储库。

这是一个虚构的用例,应该可以更好地了解我想要做什么。

我在网上发布了一些代码。一年后,有人复制并在一本书或文章中发布了相同的代码,并声称我是复制它们的人。那时,我希望能够使用我的存储库并证明我在一年前提交了该代码,然后他们重新发布了它。

通过使用带有时间戳服务的 X.509 证书,我可以证明签名发生的时间。只要我能证明我知道一年前提交的哈希值,Git 就可以保证存档的完整性。

或者,有没有办法使用 GPG 密钥签署提交,但带有经过验证的时间戳?是否有受信任的第三方提供与 X.509 证书可用的时间戳服务类似但适用于 GPG 的时间戳服务?

也许我可以使用 GPG 密钥和 X.509 证书的组合。假设我在存储库中保留了我的(公共)GPG 密钥的副本,如果我在每天结束时执行以下操作,是否会起作用?

  1. 使用我的 X.509 证书和在线时间戳服务签署我的(公共)GPG 密钥。
  2. 使用我的(私有)GPG 密钥的签名将更改提交到存储库。
4

5 回答 5

7

您所要做的就是公开发布 SHA1(提交 ID)。如果您愿意,您可以使用该 SHA1 并使用您的 X.509 证书(使用适当的时间戳服务)对其进行签名并保留它。如果有人质疑您的作者身份,您可以轻松地表明您在生成特定 SHA1 的特定时间知道存储库的内容。您不需要在代码存储库中实际存储任何签名

于 2012-08-17T08:30:10.740 回答
3

只需将时间戳证书添加到您的最新提交。sha1 将验证证书未被修改,证书本身将验证它声称的所有“事实”,例如来自受信任服务器的日期和时间戳,以及您声称的身份等。是,提交签署证书,根据 Linus 演讲中 VonC 的引述;-)


[编辑] 显然,您确实需要发布该新提交的 sha1,否则您可以修改它(和证书)并使用新的 sha1 来声明该新提交历史中的任何内容。与往常一样,它正在创建相互信任的网络。

于 2012-08-11T22:09:05.883 回答
1

我不喜欢我跟随,因为 Linus 确实在制作 Git 时考虑到了该特定功能(即,您所输入的内容的完整性正是结果的完整性)

请参阅2007 年在 Google 上的演讲成绩单):

他们中的大多数我什至不尝试就可以丢弃。

  • 如果你不是分布式的,你就不值得使用,就这么简单。
  • 如果你表现不好,你就不值得使用,就这么简单。
  • 如果你不能保证我放入单片机的东西完全一样,你就不值得使用

坦率地说,这几乎可以解决所有问题。

有很多 SCM 系统不能保证你再次从中得到的和你放入的一样。
如果你有内存损坏,如果你有磁盘损坏,你可能永远不会知道。
您知道的唯一方法是您在签出文件时注意到文件中存在损坏。而且源代码控制管理系统根本不保护你。
这甚至并不少见。这是非常非常常见的。.

所以我认为添加另一个完整性功能不会增加任何价值。
而且“时间戳”也不是一个好主意,因为它们一开始就没有为 DVCS 记录(请参阅“ Git: check out old file WITH original create/modified timestamps ”和“什么相当于git 的使用提交时间? ")

于 2012-08-11T20:03:48.270 回答
0

为此,我刚刚编写了一个名为“ GitLock ”的程序。它将可信时间戳添加到您的存储库中。

https://www.npmjs.com/package/gitlock

于 2016-06-08T20:40:24.500 回答
0

我写了一篇文章,详细介绍了使用 RFC3161 时间戳为 git 存储库添加时间戳的详细信息,并提供了一个自动执行此操作的提交后挂钩:

https://matthias-buehlmann.medium.com/git-as-cryptographically-tamperproof-file-archive-using-chained-rfc3161-timestamps-ad15836b883

关键点如下:

  1. SHA1 可能不再被认为是安全的,特别是如果它要在几年后证明某些事情(https://sha-mbles.github.io/)。因此,建议使用 sha256 哈希初始化 git 存储库git init --object-type=sha256(即使 sha256 支持仍被认为是实验性的)

  2. 将时间戳(和 LTV 数据)与存储库一起存储是有好处的 - 特别是为了任意延长时间戳令牌的生命周期,并通过添加先前的 CRL 数据来保护它们不因泄露的私钥而变得无效存储库的时间戳,然后使用新的时间戳对其进行时间戳。

  3. Git 非常适合使用 RFC3161 进行时间戳记,这为它提供了所有数据更改的防篡改证据记录。

于 2021-02-22T16:22:10.637 回答