相当于gpg - 在golang中签名?

问题描述 投票:1回答:1

我目前有一个Perl脚本,它在电子邮件地址上执行PGP签名以生成混淆的令牌。 Perl脚本使用命令行实用程序GPG 2.2.8版(在MacOS上)。我想将此功能转换为Go。

Perl中的相关行:

my $token = `printf $emailaddress | gpg --sign -u myprivatekeyname | base64`;

我在Go的尝试:

import (
    "golang.org/x/crypto/openpgp"
    "log"
    "fmt"
    "strings"
    "bytes"
    )


const privateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
<the same private key as is used by the GPG tool>
-----END PGP PRIVATE KEY BLOCK-----`

func main() {
    email := "[email protected]"
    token := makeToken(email)
    fmt.Println(token)
}

func getPrivateKey() *openpgp.Entity {
    pp := "mypassphrase"
    ppb := []byte(pp)

    entitylist, err := openpgp.ReadArmoredKeyRing(strings.NewReader(privateKey))
    if err != nil {
        log.Fatal(err)
    }

    entity := entitylist[0]

    if entity.PrivateKey != nil && entity.PrivateKey.Encrypted {
        err := entity.PrivateKey.Decrypt(ppb)
        if err != nil {
            fmt.Println("Failed to decrypt key")
        }
    }

    for _, subkey := range entity.Subkeys {
        if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted {
            err := subkey.PrivateKey.Decrypt(ppb)
            if err != nil {
                fmt.Println("Failed to decrypt subkey")
            }
        }
    }
    return entity
}

func makeToken(email string) string {
    pk := getPrivateKey()
    out := new(bytes.Buffer)
    in, err := openpgp.Sign(out, pk, nil, nil)
    if err != nil {
        log.Fatal(err)
    }
    in.Write([]byte(email))
    in.Close()
    return base64.StdEncoding.EncodeToString(out.Bytes())
}

不幸的是,给定电子邮件地址(如'[email protected]')的结果并不相同。

我使用相同的私钥:我从GPG导出它并将其粘贴到我的go代码中(显然这只是用于测试,我不会这样做)。

知道我做错了什么吗?

go gnupg pgp openpgp
1个回答
2
投票

您无法比较基于二进制差异的签名;他们include timestamps。此外,您可以应用不同的压缩和签名算法。比较gpg --list-packetspgpdump的输出。

看着一个相当随意的签名:

$ echo foo | gpg --sign | gpg --list-packets

在这里,您可能正在使用不同的压缩算法(或者根本没有,在这里:1):

# off=0 ctb=a3 tag=8 hlen=1 plen=0 indeterminate
:compressed packet: algo=1

签名包可能使用不同的摘要算法(此处:10):

# off=2 ctb=90 tag=4 hlen=2 plen=13
:onepass_sig packet: keyid 8E78E44DFB1B55E9
    version 3, sigclass 0x00, digest 10, pubkey 1, last=1

这里我们有一个时间戳:

# off=17 ctb=cb tag=11 hlen=2 plen=10 new-ctb
:literal data packet:
    mode b (62), created 1536744536, name="",
    raw data: 4 bytes

另一个时间戳(签名算法对于同一个键应该是相同的):

# off=29 ctb=89 tag=2 hlen=3 plen=563
:signature packet: algo 1, keyid 8E78E44DFB1B55E9
    version 4, created 1536744536, md5len 0, sigclass 0x00
    digest algo 10, begin of digest f4 03
    hashed subpkt 33 len 21 (issuer fpr v4 292F04A99AA52EC6F3088C608E78E44DFB1B55E9)
    hashed subpkt 2 len 4 (sig created 2018-09-12)
    subpkt 16 len 8 (issuer key ID 8E78E44DFB1B55E9)
    data: [4096 bits]

通过区分gpg --list-packets的输出,您应该能够理解输出中是否存在任何值得注意的差异。如果您使用相同的算法并伪造时间,您应该能够获得相同的输出。

上面提到的常数/幻数也在RFC 4880, OpenPGP中定义。

© www.soinside.com 2019 - 2024. All rights reserved.