OpenPGP - 尝试加密失败
OpenPGP - attempted encryption fails
我正在尝试获取要加密的存储库 (https://github.com/jchavannes/go-pgp)。
当运行我得到的代码
EOF @ File: main.go Function: main.main Line: 21
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x52cdc2]
合并后的代码如下所示:
package main
import (
"bytes"
"compress/gzip"
"crypto"
"errors"
"fmt"
"io"
"github.com/jimlawless/whereami"
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/armor"
"golang.org/x/crypto/openpgp/packet"
)
func main() {
// Create public key entity
publicKeyPacket, err := getPublicKeyPacket([]byte(TestPublicKey))
if err != nil {
fmt.Println(err.Error() + " @ " + whereami.WhereAmI())
}
pubEntity, err := createEntityFromKeys(publicKeyPacket, nil)
if err != nil {
fmt.Println(err.Error() + " @ " + whereami.WhereAmI())
}
// Encrypt message
encrypted, _ := encrypt(pubEntity, []byte(TestMessage))
fmt.Println(encrypted)
}
func getPublicKeyPacket(publicKey []byte) (*packet.PublicKey, error) {
publicKeyReader := bytes.NewReader(publicKey)
block, err := armor.Decode(publicKeyReader)
if err != nil {
return nil, err
}
if block.Type != openpgp.PublicKeyType {
return nil, errors.New("Invalid public key data")
}
packetReader := packet.NewReader(block.Body)
pkt, err := packetReader.Next()
if err != nil {
return nil, err
}
key, ok := pkt.(*packet.PublicKey)
if !ok {
return nil, err
}
return key, nil
}
func createEntityFromKeys(pubKey *packet.PublicKey, privKey *packet.PrivateKey) (*openpgp.Entity, error) {
config := packet.Config{
DefaultHash: crypto.SHA256,
DefaultCipher: packet.CipherAES256,
DefaultCompressionAlgo: packet.CompressionZLIB,
CompressionConfig: &packet.CompressionConfig{
Level: 9,
},
RSABits: 4096,
}
currentTime := config.Now()
uid := packet.NewUserId("", "", "")
e := openpgp.Entity{
PrimaryKey: pubKey,
PrivateKey: privKey,
Identities: make(map[string]*openpgp.Identity),
}
isPrimaryId := false
e.Identities[uid.Id] = &openpgp.Identity{
Name: uid.Name,
UserId: uid,
SelfSignature: &packet.Signature{
CreationTime: currentTime,
SigType: packet.SigTypePositiveCert,
PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: config.Hash(),
IsPrimaryId: &isPrimaryId,
FlagsValid: true,
FlagSign: true,
FlagCertify: true,
IssuerKeyId: &e.PrimaryKey.KeyId,
},
}
keyLifetimeSecs := uint32(86400 * 365)
e.Subkeys = make([]openpgp.Subkey, 1)
e.Subkeys[0] = openpgp.Subkey{
PublicKey: pubKey,
PrivateKey: privKey,
Sig: &packet.Signature{
CreationTime: currentTime,
SigType: packet.SigTypeSubkeyBinding,
PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: config.Hash(),
PreferredHash: []uint8{8}, // SHA-256
FlagsValid: true,
FlagEncryptStorage: true,
FlagEncryptCommunications: true,
IssuerKeyId: &e.PrimaryKey.KeyId,
KeyLifetimeSecs: &keyLifetimeSecs,
},
}
return &e, nil
}
func encrypt(entity *openpgp.Entity, message []byte) ([]byte, error) {
// Create buffer to write output to
buf := new(bytes.Buffer)
// Create encoder
encoderWriter, err := armor.Encode(buf, "Message", make(map[string]string))
if err != nil {
return []byte{}, fmt.Errorf("Error creating OpenPGP armor: %v", err)
}
// Create encryptor with encoder
encryptorWriter, err := openpgp.Encrypt(encoderWriter, []*openpgp.Entity{entity}, nil, nil, nil)
if err != nil {
return []byte{}, fmt.Errorf("Error creating entity for encryption: %v", err)
}
// Create compressor with encryptor
compressorWriter, err := gzip.NewWriterLevel(encryptorWriter, gzip.BestCompression)
if err != nil {
return []byte{}, fmt.Errorf("Invalid compression level: %v", err)
}
// Write message to compressor
messageReader := bytes.NewReader(message)
_, err = io.Copy(compressorWriter, messageReader)
if err != nil {
return []byte{}, fmt.Errorf("Error writing data to compressor: %v", err)
}
compressorWriter.Close()
encryptorWriter.Close()
encoderWriter.Close()
// Return buffer output - an encoded, encrypted, and compressed message
return buf.Bytes(), nil
}
const TestMessage = "hello world"
const TestPrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
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
=5NT7
-----END PGP PRIVATE KEY BLOCK-----`
const TestPublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
xsFNBFkNK+ABEADUpjJ/kz3j+iz9qnzUb6ONw+WHSLp8umnd1z06SBVkWFjYReqf
oPCOq67XDseK71ZSevrIt7EdTLAzl0xN8kB+8iedAGM5OCakDe3R8L83OGy1Em26
PbrrYs3TYKGDXW65TsGYCoETROGgU2zPvuBDU1RvVvd9vAlWHQis43BOWaaakCEc
00V3sdNcfV+lz7fNUXEgtmTCCr9NWX4gO3YeenIIxep4WD27VwscW5Q2B1cnxcFL
+TZzE2oVjtXljGSO94XsekuNU47zwJZNGyU6SSlSZ+KVXuSdkRRfNYHlgDWg5b8C
xVmdVUfsx3bmNlOlXoyETj83xvRlLxn3PYIgOz6OlYGba5oDogK2QLXGTXK1o9OE
kgoghmCNQqxocvb1hQXT8cEynIbAdc6/JknYaoic6ka1iTTz3uN8FEPw5gRlidcQ
3wkbmqIS0LJs3JmVbD7/BxMY1dwqMyvulfnLiTsWSPvk41o7dHf077t23V9w78Jg
h4Xq4HRvt37PtuO6eWW3c5aUIWmvvDqMbMEqp2y23noYoVNqEpVoHolDdoCSurv/
XxbNBnj46XwaIs6OlrO2htV0al2/WVTNnSLxCyoHXoJEDXyaOyNKn1jM/FczgYQJ
069uC804ohOfjLmbtUEYE7Hjeo5utPm2ryjnakgV5AStKgL0SyFZUwN/DwARAQAB
=gO1a
-----END PGP PUBLIC KEY BLOCK-----`
有什么解决办法吗?
tl;博士
- 始终检查错误。
x/crypto/openpgp
包是 deprecated,你不应该使用它。
所以这是你的错误:
EOF @ File: main.go Function: main.main Line: 21
那是从 getPublicKeyPacket([]byte(TestPublicKey))
回来的,我们在那里看到:
publicKeyReader := bytes.NewReader(publicKey)
block, err := armor.Decode(publicKeyReader)
if err != nil {
return nil, err
}
查看 the documentation for armor.Decode
,我们看到(强调我的):
Decode reads a PGP armored block from the given Reader. It will ignore leading garbage. If it doesn't find a block, it will return nil, io.EOF.
所以,您的 public 密钥块似乎无效。让我们来检验这个理论!
如果我们从 TestPublicKey
中获取数据并将其写入文件...
-----BEGIN PGP PUBLIC KEY BLOCK-----
xsFNBFkNK+ABEADUpjJ/kz3j+iz9qnzUb6ONw+WHSLp8umnd1z06SBVkWFjYReqf
oPCOq67XDseK71ZSevrIt7EdTLAzl0xN8kB+8iedAGM5OCakDe3R8L83OGy1Em26
PbrrYs3TYKGDXW65TsGYCoETROGgU2zPvuBDU1RvVvd9vAlWHQis43BOWaaakCEc
00V3sdNcfV+lz7fNUXEgtmTCCr9NWX4gO3YeenIIxep4WD27VwscW5Q2B1cnxcFL
+TZzE2oVjtXljGSO94XsekuNU47zwJZNGyU6SSlSZ+KVXuSdkRRfNYHlgDWg5b8C
xVmdVUfsx3bmNlOlXoyETj83xvRlLxn3PYIgOz6OlYGba5oDogK2QLXGTXK1o9OE
kgoghmCNQqxocvb1hQXT8cEynIbAdc6/JknYaoic6ka1iTTz3uN8FEPw5gRlidcQ
3wkbmqIS0LJs3JmVbD7/BxMY1dwqMyvulfnLiTsWSPvk41o7dHf077t23V9w78Jg
h4Xq4HRvt37PtuO6eWW3c5aUIWmvvDqMbMEqp2y23noYoVNqEpVoHolDdoCSurv/
XxbNBnj46XwaIs6OlrO2htV0al2/WVTNnSLxCyoHXoJEDXyaOyNKn1jM/FczgYQJ
069uC804ohOfjLmbtUEYE7Hjeo5utPm2ryjnakgV5AStKgL0SyFZUwN/DwARAQAB
=gO1a
-----END PGP PUBLIC KEY BLOCK-----
...然后尝试使用 gpg
导入它,我们看到:
$ gpg --import testpublickey.asc
gpg: invalid armor header: xsFNBFkNK+ABEADUpjJ/kz3j+iz9qnzUb6ONw+WHSLp8umnd1z06SBVkWFjYReqf\n
gpg: key 39078898F94F4667: new key but contains no user ID - skipped
看来gpg
同意。让我们生成一个正确的 public 密钥,看看问题是否消失:
$ gpg --full-generate-key
[...]
pub rsa3072 2022-06-04 [SC]
92F9D24D5428E3D2B5FE5774A7F5A28D78317D17
uid Test Key <test@example.com>
sub rsa3072 2022-06-04 [E]
$ gpg --export -a test@example.com > testpublickey.asc
$ gpg --export-secret-key -a test@example.com > testsecretkey.asc
如果我们将 testpublickey.asc
的内容嵌入到您的代码中并编译,它现在可以正常运行...
$ go build
$ ./gpgtest
[]
...虽然它似乎没有生成有用的输出。但那是因为您忽略了来自 encrypt
的错误。如果我们处理错误响应:
encrypted, err := encrypt(pubEntity, []byte(TestMessage))
if err != nil {
panic(err)
}
fmt.Println(encrypted)
然后我们看到:
panic: Error creating entity for encryption: openpgp: invalid argument: cannot encrypt because no candidate hash functions are compiled in. (Wanted RIPEMD160 in this case.)
goroutine 1 [running]:
main.main()
/home/lars/tmp/go/main.go:31 +0xe9
并且该错误似乎已得到解决 ,这告诉我们解决方案是通过添加以下内容来导入适当的哈希值:
import (
...
_ "golang.org/x/crypto/ripemd160"
)
通过此更改和重新编译,我们现在看到输出:
[45 45 45 45 45 66 69 71 73 78 32 77 101 115 115 97 103 101 45 45 45 45 45 10 10 119 99 68 77 65 54 102 49 111 111 49 52 77 88 48 88 65 81 119 65 87 70 43 115 72 119 89 121 117 106 83 70 76 57 100 73 101 113 115 107 81 103 117 106 99 118 97 69 57 52 47 57 51 105 57 118 118 98 67 82 111 113 57 98 10 99 54 66 85 108 103 116 50 111 72 97 122 86 110 105 50 49 121 68 122 112 119 82 115 81 109 105 48 43 100 90 103 81 99 52 54 112 65 89 77 106 116 48 81 117 66 116 50 65 77 100 86 71 118 56 79 121 66 47 70 115 87 89 116 10 49 100 83 80 90 115 121 73 116 113 118 50 65 114 122 102 100 114 68 84 54 75 116 99 110 76 70 85 114 72 67 55 102 66 112 74 115 88 51 86 75 53 111 106 75 82 117 115 54 70 72 56 52 83 101 54 55 98 66 70 113 81 90 107 10 113 80 66 68 57 108 49 66 84 88 80 83 57 73 100 56 111 74 114 115 119 82 87 88 119 117 90 80 75 121 49 101 107 71 53 53 69 73 73 71 78 49 84 69 70 90 100 103 54 110 72 83 119 83 100 53 84 112 120 107 71 68 80 48 10 104 67 110 122 121 109 111 97 53 55 78 84 71 97 82 110 65 47 119 88 71 86 104 104 110 87 68 55 85 120 107 116 53 90 100 52 84 88 43 107 109 119 102 48 50 108 80 115 66 122 114 122 118 50 87 50 56 51 97 85 79 109 70 118 10 71 113 55 71 69 80 119 83 116 74 100 47 49 90 81 113 110 109 48 65 80 86 72 69 69 108 114 98 120 67 122 83 66 82 80 103 51 78 73 79 112 106 100 121 83 48 112 116 57 82 107 114 111 82 87 43 57 99 50 76 98 100 54 83 10 112 119 88 110 76 56 78 100 114 49 70 43 105 122 101 84 109 112 76 99 82 101 119 89 88 57 107 113 113 69 106 78 117 103 90 54 65 117 85 83 77 73 121 104 102 101 99 121 108 69 78 99 47 103 87 98 103 103 51 54 65 81 101 116 10 86 52 65 48 122 88 122 82 121 102 122 121 76 53 56 67 101 54 112 65 71 85 54 118 115 66 114 73 83 122 86 107 108 105 118 108 69 115 114 99 83 75 119 98 67 79 111 78 112 112 118 117 105 53 108 89 77 57 77 65 110 110 111 79 10 98 56 109 78 50 72 110 110 117 85 102 48 43 43 76 67 90 48 98 105 48 117 89 66 102 43 120 68 87 70 108 122 115 87 69 73 81 66 111 114 78 70 82 100 117 97 85 77 76 73 104 47 89 108 116 65 104 108 90 81 111 47 122 120 10 90 86 55 98 102 108 53 103 88 74 117 89 83 83 86 43 113 100 72 75 43 106 109 103 83 121 89 90 75 100 89 110 80 78 112 49 53 71 48 55 50 74 85 73 52 52 82 119 56 66 113 97 81 80 75 54 52 105 101 76 67 65 106 104 10 43 43 110 103 80 103 65 61 10 61 121 72 81 117 10 45 45 45 45 45 69 78 68 32 77 101 115 115 97 103 101 45 45 45 45 45]
打印出字节缓冲区并没有多大帮助,所以让我们用 string
:
包装一下
fmt.Println(string(encrypted))
这给了我们:
-----BEGIN Message-----
wcDMA6f1oo14MX0XAQwABlLztwGC16in9i0kHm4M7FETC+1xgJDllBEGKqZWvPIb
FruPomy+jBPMROuVpZl9qxBTJwkTvhXxMZsSZz+mWOzrsAanhffZtCRbZ5BC+f8U
1iAkt35Sk73tN7w62+G7Unza0KlE8l3eqEb947wZSYAufdVnDESRd6ScTFuj/pxp
0pnfpaOAjjZPp9DOpExpU+yIij94t0UrAwndsSE3D3Bi1DfJ1Q9GPgYQbplwio3u
wfzFZOonIH2TG0AUwiY9lLVTu+u9rj5PovGdXuaIGTw26IAn05Xo3DRPdgee+W+2
qMHEDE6PoZFcL3eTJ8ed0IbvRAHZ3oovJpo/nJ2Pf7RfJcsujYYfsAv7Y2jmFWDd
cwo4NStRBCEZBhTfkZTJUI4kSpOtiXK2kqyQYuzKhQB3UnoMi4vbge9aOoT6x27f
u/UuvdRAuZ4CjD0ptyauFZKPwQxkYZ3R3LeUrPXbOQ1KPLWtnECseeqSqGVWpmVs
1DgjgF+cVXovuUFcWHhl0uYB/Q0NJCQV59t7QMtHalBIOv/KSOQUlOjGpRaZB5GL
NXRSSTLYZOUXqUpFMC8em+uoT3KFLxeYVG/5wB5YXyK/47CZvEvK32g54rS5dlHh
JergyAA=
=iYGx
-----END Message-----
但同样的答案也告诉我们 crypto/openpgp
包是 deprecated,您不应该使用它。链接的问题对替代方案有一些建议。
我正在尝试获取要加密的存储库 (https://github.com/jchavannes/go-pgp)。 当运行我得到的代码
EOF @ File: main.go Function: main.main Line: 21
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x52cdc2]
合并后的代码如下所示:
package main
import (
"bytes"
"compress/gzip"
"crypto"
"errors"
"fmt"
"io"
"github.com/jimlawless/whereami"
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/armor"
"golang.org/x/crypto/openpgp/packet"
)
func main() {
// Create public key entity
publicKeyPacket, err := getPublicKeyPacket([]byte(TestPublicKey))
if err != nil {
fmt.Println(err.Error() + " @ " + whereami.WhereAmI())
}
pubEntity, err := createEntityFromKeys(publicKeyPacket, nil)
if err != nil {
fmt.Println(err.Error() + " @ " + whereami.WhereAmI())
}
// Encrypt message
encrypted, _ := encrypt(pubEntity, []byte(TestMessage))
fmt.Println(encrypted)
}
func getPublicKeyPacket(publicKey []byte) (*packet.PublicKey, error) {
publicKeyReader := bytes.NewReader(publicKey)
block, err := armor.Decode(publicKeyReader)
if err != nil {
return nil, err
}
if block.Type != openpgp.PublicKeyType {
return nil, errors.New("Invalid public key data")
}
packetReader := packet.NewReader(block.Body)
pkt, err := packetReader.Next()
if err != nil {
return nil, err
}
key, ok := pkt.(*packet.PublicKey)
if !ok {
return nil, err
}
return key, nil
}
func createEntityFromKeys(pubKey *packet.PublicKey, privKey *packet.PrivateKey) (*openpgp.Entity, error) {
config := packet.Config{
DefaultHash: crypto.SHA256,
DefaultCipher: packet.CipherAES256,
DefaultCompressionAlgo: packet.CompressionZLIB,
CompressionConfig: &packet.CompressionConfig{
Level: 9,
},
RSABits: 4096,
}
currentTime := config.Now()
uid := packet.NewUserId("", "", "")
e := openpgp.Entity{
PrimaryKey: pubKey,
PrivateKey: privKey,
Identities: make(map[string]*openpgp.Identity),
}
isPrimaryId := false
e.Identities[uid.Id] = &openpgp.Identity{
Name: uid.Name,
UserId: uid,
SelfSignature: &packet.Signature{
CreationTime: currentTime,
SigType: packet.SigTypePositiveCert,
PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: config.Hash(),
IsPrimaryId: &isPrimaryId,
FlagsValid: true,
FlagSign: true,
FlagCertify: true,
IssuerKeyId: &e.PrimaryKey.KeyId,
},
}
keyLifetimeSecs := uint32(86400 * 365)
e.Subkeys = make([]openpgp.Subkey, 1)
e.Subkeys[0] = openpgp.Subkey{
PublicKey: pubKey,
PrivateKey: privKey,
Sig: &packet.Signature{
CreationTime: currentTime,
SigType: packet.SigTypeSubkeyBinding,
PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: config.Hash(),
PreferredHash: []uint8{8}, // SHA-256
FlagsValid: true,
FlagEncryptStorage: true,
FlagEncryptCommunications: true,
IssuerKeyId: &e.PrimaryKey.KeyId,
KeyLifetimeSecs: &keyLifetimeSecs,
},
}
return &e, nil
}
func encrypt(entity *openpgp.Entity, message []byte) ([]byte, error) {
// Create buffer to write output to
buf := new(bytes.Buffer)
// Create encoder
encoderWriter, err := armor.Encode(buf, "Message", make(map[string]string))
if err != nil {
return []byte{}, fmt.Errorf("Error creating OpenPGP armor: %v", err)
}
// Create encryptor with encoder
encryptorWriter, err := openpgp.Encrypt(encoderWriter, []*openpgp.Entity{entity}, nil, nil, nil)
if err != nil {
return []byte{}, fmt.Errorf("Error creating entity for encryption: %v", err)
}
// Create compressor with encryptor
compressorWriter, err := gzip.NewWriterLevel(encryptorWriter, gzip.BestCompression)
if err != nil {
return []byte{}, fmt.Errorf("Invalid compression level: %v", err)
}
// Write message to compressor
messageReader := bytes.NewReader(message)
_, err = io.Copy(compressorWriter, messageReader)
if err != nil {
return []byte{}, fmt.Errorf("Error writing data to compressor: %v", err)
}
compressorWriter.Close()
encryptorWriter.Close()
encoderWriter.Close()
// Return buffer output - an encoded, encrypted, and compressed message
return buf.Bytes(), nil
}
const TestMessage = "hello world"
const TestPrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
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
=5NT7
-----END PGP PRIVATE KEY BLOCK-----`
const TestPublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
xsFNBFkNK+ABEADUpjJ/kz3j+iz9qnzUb6ONw+WHSLp8umnd1z06SBVkWFjYReqf
oPCOq67XDseK71ZSevrIt7EdTLAzl0xN8kB+8iedAGM5OCakDe3R8L83OGy1Em26
PbrrYs3TYKGDXW65TsGYCoETROGgU2zPvuBDU1RvVvd9vAlWHQis43BOWaaakCEc
00V3sdNcfV+lz7fNUXEgtmTCCr9NWX4gO3YeenIIxep4WD27VwscW5Q2B1cnxcFL
+TZzE2oVjtXljGSO94XsekuNU47zwJZNGyU6SSlSZ+KVXuSdkRRfNYHlgDWg5b8C
xVmdVUfsx3bmNlOlXoyETj83xvRlLxn3PYIgOz6OlYGba5oDogK2QLXGTXK1o9OE
kgoghmCNQqxocvb1hQXT8cEynIbAdc6/JknYaoic6ka1iTTz3uN8FEPw5gRlidcQ
3wkbmqIS0LJs3JmVbD7/BxMY1dwqMyvulfnLiTsWSPvk41o7dHf077t23V9w78Jg
h4Xq4HRvt37PtuO6eWW3c5aUIWmvvDqMbMEqp2y23noYoVNqEpVoHolDdoCSurv/
XxbNBnj46XwaIs6OlrO2htV0al2/WVTNnSLxCyoHXoJEDXyaOyNKn1jM/FczgYQJ
069uC804ohOfjLmbtUEYE7Hjeo5utPm2ryjnakgV5AStKgL0SyFZUwN/DwARAQAB
=gO1a
-----END PGP PUBLIC KEY BLOCK-----`
有什么解决办法吗?
tl;博士
- 始终检查错误。
x/crypto/openpgp
包是 deprecated,你不应该使用它。
所以这是你的错误:
EOF @ File: main.go Function: main.main Line: 21
那是从 getPublicKeyPacket([]byte(TestPublicKey))
回来的,我们在那里看到:
publicKeyReader := bytes.NewReader(publicKey)
block, err := armor.Decode(publicKeyReader)
if err != nil {
return nil, err
}
查看 the documentation for armor.Decode
,我们看到(强调我的):
Decode reads a PGP armored block from the given Reader. It will ignore leading garbage. If it doesn't find a block, it will return nil, io.EOF.
所以,您的 public 密钥块似乎无效。让我们来检验这个理论!
如果我们从 TestPublicKey
中获取数据并将其写入文件...
-----BEGIN PGP PUBLIC KEY BLOCK-----
xsFNBFkNK+ABEADUpjJ/kz3j+iz9qnzUb6ONw+WHSLp8umnd1z06SBVkWFjYReqf
oPCOq67XDseK71ZSevrIt7EdTLAzl0xN8kB+8iedAGM5OCakDe3R8L83OGy1Em26
PbrrYs3TYKGDXW65TsGYCoETROGgU2zPvuBDU1RvVvd9vAlWHQis43BOWaaakCEc
00V3sdNcfV+lz7fNUXEgtmTCCr9NWX4gO3YeenIIxep4WD27VwscW5Q2B1cnxcFL
+TZzE2oVjtXljGSO94XsekuNU47zwJZNGyU6SSlSZ+KVXuSdkRRfNYHlgDWg5b8C
xVmdVUfsx3bmNlOlXoyETj83xvRlLxn3PYIgOz6OlYGba5oDogK2QLXGTXK1o9OE
kgoghmCNQqxocvb1hQXT8cEynIbAdc6/JknYaoic6ka1iTTz3uN8FEPw5gRlidcQ
3wkbmqIS0LJs3JmVbD7/BxMY1dwqMyvulfnLiTsWSPvk41o7dHf077t23V9w78Jg
h4Xq4HRvt37PtuO6eWW3c5aUIWmvvDqMbMEqp2y23noYoVNqEpVoHolDdoCSurv/
XxbNBnj46XwaIs6OlrO2htV0al2/WVTNnSLxCyoHXoJEDXyaOyNKn1jM/FczgYQJ
069uC804ohOfjLmbtUEYE7Hjeo5utPm2ryjnakgV5AStKgL0SyFZUwN/DwARAQAB
=gO1a
-----END PGP PUBLIC KEY BLOCK-----
...然后尝试使用 gpg
导入它,我们看到:
$ gpg --import testpublickey.asc
gpg: invalid armor header: xsFNBFkNK+ABEADUpjJ/kz3j+iz9qnzUb6ONw+WHSLp8umnd1z06SBVkWFjYReqf\n
gpg: key 39078898F94F4667: new key but contains no user ID - skipped
看来gpg
同意。让我们生成一个正确的 public 密钥,看看问题是否消失:
$ gpg --full-generate-key
[...]
pub rsa3072 2022-06-04 [SC]
92F9D24D5428E3D2B5FE5774A7F5A28D78317D17
uid Test Key <test@example.com>
sub rsa3072 2022-06-04 [E]
$ gpg --export -a test@example.com > testpublickey.asc
$ gpg --export-secret-key -a test@example.com > testsecretkey.asc
如果我们将 testpublickey.asc
的内容嵌入到您的代码中并编译,它现在可以正常运行...
$ go build
$ ./gpgtest
[]
...虽然它似乎没有生成有用的输出。但那是因为您忽略了来自 encrypt
的错误。如果我们处理错误响应:
encrypted, err := encrypt(pubEntity, []byte(TestMessage))
if err != nil {
panic(err)
}
fmt.Println(encrypted)
然后我们看到:
panic: Error creating entity for encryption: openpgp: invalid argument: cannot encrypt because no candidate hash functions are compiled in. (Wanted RIPEMD160 in this case.)
goroutine 1 [running]:
main.main()
/home/lars/tmp/go/main.go:31 +0xe9
并且该错误似乎已得到解决
import (
...
_ "golang.org/x/crypto/ripemd160"
)
通过此更改和重新编译,我们现在看到输出:
[45 45 45 45 45 66 69 71 73 78 32 77 101 115 115 97 103 101 45 45 45 45 45 10 10 119 99 68 77 65 54 102 49 111 111 49 52 77 88 48 88 65 81 119 65 87 70 43 115 72 119 89 121 117 106 83 70 76 57 100 73 101 113 115 107 81 103 117 106 99 118 97 69 57 52 47 57 51 105 57 118 118 98 67 82 111 113 57 98 10 99 54 66 85 108 103 116 50 111 72 97 122 86 110 105 50 49 121 68 122 112 119 82 115 81 109 105 48 43 100 90 103 81 99 52 54 112 65 89 77 106 116 48 81 117 66 116 50 65 77 100 86 71 118 56 79 121 66 47 70 115 87 89 116 10 49 100 83 80 90 115 121 73 116 113 118 50 65 114 122 102 100 114 68 84 54 75 116 99 110 76 70 85 114 72 67 55 102 66 112 74 115 88 51 86 75 53 111 106 75 82 117 115 54 70 72 56 52 83 101 54 55 98 66 70 113 81 90 107 10 113 80 66 68 57 108 49 66 84 88 80 83 57 73 100 56 111 74 114 115 119 82 87 88 119 117 90 80 75 121 49 101 107 71 53 53 69 73 73 71 78 49 84 69 70 90 100 103 54 110 72 83 119 83 100 53 84 112 120 107 71 68 80 48 10 104 67 110 122 121 109 111 97 53 55 78 84 71 97 82 110 65 47 119 88 71 86 104 104 110 87 68 55 85 120 107 116 53 90 100 52 84 88 43 107 109 119 102 48 50 108 80 115 66 122 114 122 118 50 87 50 56 51 97 85 79 109 70 118 10 71 113 55 71 69 80 119 83 116 74 100 47 49 90 81 113 110 109 48 65 80 86 72 69 69 108 114 98 120 67 122 83 66 82 80 103 51 78 73 79 112 106 100 121 83 48 112 116 57 82 107 114 111 82 87 43 57 99 50 76 98 100 54 83 10 112 119 88 110 76 56 78 100 114 49 70 43 105 122 101 84 109 112 76 99 82 101 119 89 88 57 107 113 113 69 106 78 117 103 90 54 65 117 85 83 77 73 121 104 102 101 99 121 108 69 78 99 47 103 87 98 103 103 51 54 65 81 101 116 10 86 52 65 48 122 88 122 82 121 102 122 121 76 53 56 67 101 54 112 65 71 85 54 118 115 66 114 73 83 122 86 107 108 105 118 108 69 115 114 99 83 75 119 98 67 79 111 78 112 112 118 117 105 53 108 89 77 57 77 65 110 110 111 79 10 98 56 109 78 50 72 110 110 117 85 102 48 43 43 76 67 90 48 98 105 48 117 89 66 102 43 120 68 87 70 108 122 115 87 69 73 81 66 111 114 78 70 82 100 117 97 85 77 76 73 104 47 89 108 116 65 104 108 90 81 111 47 122 120 10 90 86 55 98 102 108 53 103 88 74 117 89 83 83 86 43 113 100 72 75 43 106 109 103 83 121 89 90 75 100 89 110 80 78 112 49 53 71 48 55 50 74 85 73 52 52 82 119 56 66 113 97 81 80 75 54 52 105 101 76 67 65 106 104 10 43 43 110 103 80 103 65 61 10 61 121 72 81 117 10 45 45 45 45 45 69 78 68 32 77 101 115 115 97 103 101 45 45 45 45 45]
打印出字节缓冲区并没有多大帮助,所以让我们用 string
:
fmt.Println(string(encrypted))
这给了我们:
-----BEGIN Message-----
wcDMA6f1oo14MX0XAQwABlLztwGC16in9i0kHm4M7FETC+1xgJDllBEGKqZWvPIb
FruPomy+jBPMROuVpZl9qxBTJwkTvhXxMZsSZz+mWOzrsAanhffZtCRbZ5BC+f8U
1iAkt35Sk73tN7w62+G7Unza0KlE8l3eqEb947wZSYAufdVnDESRd6ScTFuj/pxp
0pnfpaOAjjZPp9DOpExpU+yIij94t0UrAwndsSE3D3Bi1DfJ1Q9GPgYQbplwio3u
wfzFZOonIH2TG0AUwiY9lLVTu+u9rj5PovGdXuaIGTw26IAn05Xo3DRPdgee+W+2
qMHEDE6PoZFcL3eTJ8ed0IbvRAHZ3oovJpo/nJ2Pf7RfJcsujYYfsAv7Y2jmFWDd
cwo4NStRBCEZBhTfkZTJUI4kSpOtiXK2kqyQYuzKhQB3UnoMi4vbge9aOoT6x27f
u/UuvdRAuZ4CjD0ptyauFZKPwQxkYZ3R3LeUrPXbOQ1KPLWtnECseeqSqGVWpmVs
1DgjgF+cVXovuUFcWHhl0uYB/Q0NJCQV59t7QMtHalBIOv/KSOQUlOjGpRaZB5GL
NXRSSTLYZOUXqUpFMC8em+uoT3KFLxeYVG/5wB5YXyK/47CZvEvK32g54rS5dlHh
JergyAA=
=iYGx
-----END Message-----
但同样的答案也告诉我们 crypto/openpgp
包是 deprecated,您不应该使用它。链接的问题对替代方案有一些建议。