The openpgp API is not the most straightforward to use, but I gave it a go (pun intended), and here is what I came up with :
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
}
As requested, I put the public key in the code.
You can test it like that :
$ go run testpgp.go foo.bin foo.bin.sig
If the file you have signed is very big, you may want to change the code a little bit to avoid loading it in memory.
.sig
file to verify the signature. Then the crypto package should have all the methods you need. If you find the documentation about the definition of the .sig file (I did not find it), please place it here. I would like to see that too. – user983716