我有一个二进制文件:
foo.bin
此文件已使用gpg密钥签名以创建:
foo.bin.sig
我有一个包含用于签署二进制文件的公钥的文件。
我想做的是能够使用Go验证此签名。
我正在阅读go.crypto / openpgp文档,但它们对此用例并没有特别的帮助。
验证将在远程计算机上完成。理想情况下,我想避免在运行此代码的计算机上使用密钥环。公钥本身可以简单地存储在可执行文件中......如果我能弄清楚如何完成这个验证。
我认为我需要做的步骤如下:
问题主要是:如何仅使用公钥编写此验证功能?
答案 0 :(得分:4)
openpgp API并不是最直接使用的,但我给它一个去(双关语),这就是我想出来的:
package main
import (
"bytes"
"code.google.com/p/go.crypto/openpgp/packet"
"encoding/hex"
"errors"
"fmt"
"io/ioutil"
"os"
)
// gpg --export YOURKEYID --export-options export-minimal,no-export-attributes | hexdump /dev/stdin -v -e '/1 "%02X"'
var publicKeyHex string = "99[VERY LONG HEX STRING]B6"
func main() {
if len(os.Args) != 3 {
fmt.Println("Usage: " + os.Args[0] + " <file> <signature file>")
return
}
err := checkSig(os.Args[1], os.Args[2])
if err != nil {
fmt.Println("Invalid signature : ")
fmt.Println(err)
} else {
fmt.Println("Valid signature")
}
}
func checkSig(fileName string, sigFileName string) error {
// First, get the content of the file we have signed
fileContent, err := ioutil.ReadFile(fileName)
if err != nil {
return err
}
// Get a Reader for the signature file
sigFile, err := os.Open(sigFileName)
if err != nil {
return err
}
defer func() {
if err := sigFile.Close(); err != nil {
panic(err)
}
}()
// Read the signature file
pack, err := packet.Read(sigFile)
if err != nil {
return err
}
// Was it really a signature file ? If yes, get the Signature
signature, ok := pack.(*packet.Signature)
if !ok {
return errors.New(os.Args[2] + " is not a valid signature file.")
}
// For convenience, we have the key in hexadecimal, convert it to binary
publicKeyBin, err := hex.DecodeString(publicKeyHex)
if err != nil {
return err
}
// Read the key
pack, err = packet.Read(bytes.NewReader(publicKeyBin))
if err != nil {
return err
}
// Was it really a public key file ? If yes, get the PublicKey
publicKey, ok := pack.(*packet.PublicKey)
if !ok {
return errors.New("Invalid public key.")
}
// Get the hash method used for the signature
hash := signature.Hash.New()
// Hash the content of the file (if the file is big, that's where you have to change the code to avoid getting the whole file in memory, by reading and writting in small chunks)
_, err = hash.Write(fileContent)
if err != nil {
return err
}
// Check the signature
err = publicKey.VerifySignature(hash, signature)
if err != nil {
return err
}
return nil
}
根据要求,我将公钥放在代码中。 你可以这样测试:
$ go run testpgp.go foo.bin foo.bin.sig
如果您签名的文件非常大,您可能需要稍微更改一下代码以避免将其加载到内存中。