【发布时间】:2016-02-19 10:48:13
【问题描述】:
我正在开发一个需要验证 OpenPGP 公钥的 Go 项目,以便能够使用它来验证文件签名。
我已经生成了一个根密钥和另一个密钥,我已经用根密钥对其进行了签名(我们称第二个密钥为已签名)。我已将签名密钥的公共部分导出到一个装甲文本文件,以便于分发:
gpg --export -a signed > signed.asc
最后我写了这个 go 代码来说明我想要做什么:
package main
import (
"flag"
"fmt"
"golang.org/x/crypto/openpgp"
"os"
)
func main() {
var keyringpath string
var signedkeypath string
flag.StringVar(&keyringpath, "keyring", "", "keyring")
flag.StringVar(&signedkeypath, "signedkey", "", "signed key")
flag.Parse()
// read the keyring
keyring, err := os.Open(keyringpath)
if err != nil {
panic(err)
}
el, err := openpgp.ReadKeyRing(keyring)
if err != nil {
panic(err)
}
var rootidentity *openpgp.Entity
for _, entity := range el {
if _, ok := entity.Identities["root"]; ok {
rootidentity = entity
}
}
fmt.Printf("%+v\n", rootidentity)
// read the public armored key
signedkey, err := os.Open(signedkeypath)
if err != nil {
panic(err)
}
el, err = openpgp.ReadArmoredKeyRing(signedkey)
if err != nil {
panic(err)
}
signed := el[0]
fmt.Printf("%+v\n", signed)
// there is only one signature on signed, the one produced by root
signature := signed.Identities["signed"].Signatures[0]
err = rootidentity.PrimaryKey.VerifyKeySignature(signed.PrimaryKey, signature)
if err != nil {
panic(err)
}
}
当我运行它时,我给keyring我的公钥环(~/.gnupg/pubring.gpg)和signedkey我导出的签名密钥(signed.asc)。
在生产中,想法是将根公钥从pubring.gpg 导出到装甲文本中,并将其嵌入代码中。
签名验证失败,出现以下错误:
panic: openpgp: invalid signature: hash tag doesn't match
查看VerifyKeySignature(尤其是this comment)的代码,我感觉它只用于验证子密钥上的签名,而不是其他密钥。
所以,问题是,给定两个公共 PGP 密钥,一个由另一个签名,我如何使用 openpgp 库验证该签名?
【问题讨论】:
-
很可能不只是一个签名。通常,会发出一个自签名来绑定用户 ID,并存储一些设置。使用
gpg --list-packets signed.asc查看导出的密钥,您可能会发现多个签名。 -
感谢您的评论!我检查了只有一个签名,并且它是正确的。自签名存储在
SelfSignature下,而不是Signatures切片中,所以我很确定我也没有错误地使用它。