如何验证公钥上的OpenPGP签名?

huangapple go评论87阅读模式
英文:

How to verify an OpenPGP signature on a public key?

问题

我正在处理一个Go项目,需要验证OpenPGP公钥,以便能够用它来验证文件签名。

我已经生成了一个根密钥和另一个密钥,我用根密钥对其进行了签名(我们称之为第二个密钥已签名)。我将已签名密钥的公共部分导出到一个文本文件中,以便于分发:

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()

    // 读取密钥环
    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)

    // 读取公共的加密密钥
    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)

    // signed上只有一个签名,由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的代码(尤其是这个注释),我觉得它只能用于验证子密钥上的签名,而不是其他密钥。

因此,问题是,给定两个由另一个密钥签名的公共PGP密钥,如何使用openpgp库验证该签名?

英文:

I am working on a go project that will need to verify an OpenPGP public key, to be able to use it to verify file signatures.

I've generated a root key, and another key, which I've signed with the root key (let's call the second key signed). I've exported the public part of the signed key to an armored text file, for easy distribution:

gpg --export -a signed > signed.asc

I've written this go code which illustrates what I want to do, in the end:

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)
    }
}

When I run it, I give keyring my public keyring (~/.gnupg/pubring.gpg) and signedkey my exported signed key (signed.asc).

In production, the idea is to also export the root public key from pubring.gpg into armored text, and embed that in the code.

The signature fails to verify with the following error:

panic: openpgp: invalid signature: hash tag doesn't match

Looking at the code of VerifyKeySignature (and especially this comment), I get the feeling that it's meant to only be used to verify signatures on subkeys, rather than other keys.

So, the question is, given two public PGP keys, one signed by the other, how do I verify that signature using the openpgp library?

答案1

得分: 1

我不确定是否应该关闭这个问题:我找到了答案。在文档中并不是很清楚,但是VerifyKeySignature可能只用于子密钥。要验证其他用户公钥上的签名,请使用VerifyUserIdSignature,像这样:

err = rootidentity.PrimaryKey.VerifyUserIdSignature("signed", signed.PrimaryKey, signature)
if err != nil {
        panic(err)
}
英文:

Not sure whether I should close this question or not: I found the answer. It isn't very clear in the docs, but VerifyKeySignature is indeed probably only used for subkeys. For verifying the signatures on other users' public keys, use VerifyUserIdSignature, like so:

err = rootidentity.PrimaryKey.VerifyUserIdSignature("signed", signed.PrimaryKey, signature)
if err != nil {
        panic(err)
}

huangapple
  • 本文由 发表于 2016年2月19日 18:48:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/35503435.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定