更新
我已将我用于此的脚本发布到 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.pem
由curl
. 它在这里。
下面的代码片段假设一个现有的、签名的时间戳回复被传递给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 密钥的副本,如果我在每天结束时执行以下操作,是否会起作用?
- 使用我的 X.509 证书和在线时间戳服务签署我的(公共)GPG 密钥。
- 使用我的(私有)GPG 密钥的签名将更改提交到存储库。