Skip to content

Instantly share code, notes, and snippets.

@a-h
Created May 29, 2016 21:13
Show Gist options
  • Select an option

  • Save a-h/ba32279974ce76c26e206905dc8e435e to your computer and use it in GitHub Desktop.

Select an option

Save a-h/ba32279974ce76c26e206905dc8e435e to your computer and use it in GitHub Desktop.
Sign and Verify Data With PEM Files
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
"log"
)
func main() {
// Create keys.
pk := createPrivateKey()
createPublicKey(pk)
publicKey, err := loadPublicKey()
// Create some data to sign.
data := []byte("hello")
fmt.Printf("Test data: %v\n", string(data))
// Generate a signature.
signature, err := Sign(data, pk)
if err != nil {
log.Printf("Failed to sign data. %v", err)
}
fmt.Printf("Signature: %v\n", signature)
// Verify the signature by rehashing it and passing it to the verify function.
hash := sha256.Sum256(data)
verification := Verify(publicKey, hash[:], signature)
log.Printf("Verification result: %v\n", verification)
// If the signature is modified, then the verification fails.
verification = Verify(publicKey, hash[:], append(signature, 1))
log.Printf("Verification should have failed due to an invalid signature: %v\n", verification)
// If the checksum doesn't match, then the verification fails.
data = []byte("hello1")
hash = sha256.Sum256(data)
verification = Verify(publicKey, hash[:], signature)
log.Printf("Verification should have failed due to a mismatched checksum and signature: %v\n", verification)
}
func createPrivateKey() (priv *rsa.PrivateKey) {
privateKey, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
log.Printf("Failed to create private key, with err %v", err)
}
pem := pem.EncodeToMemory(
&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
})
ioutil.WriteFile("private.pem", pem, 0666)
return privateKey
}
func createPublicKey(priv *rsa.PrivateKey) {
der, err := x509.MarshalPKIXPublicKey(&priv.PublicKey)
if err != nil {
log.Print("Failed to marshal the public key.")
}
pem := pem.EncodeToMemory(&pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: der,
})
ioutil.WriteFile("public.pem", pem, 0666)
}
// Sign data with a private key.
func Sign(data []byte, priv *rsa.PrivateKey) (signature []byte, err error) {
hashed := sha256.Sum256(data)
hashSlice := hashed[:]
return rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA256, hashSlice)
}
func loadPublicKey() (*rsa.PublicKey, error) {
pemBytes, err := ioutil.ReadFile("public.pem")
block, _ := pem.Decode(pemBytes)
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
rsaPub, ok := pub.(*rsa.PublicKey)
if !ok {
log.Print("Failed to load the public key.")
}
return rsaPub, err
}
// Verify the hash. hashed is created by hashing the input message. The sig
// parameter is the signature of the hash to verify.
func Verify(pub *rsa.PublicKey, hashed []byte, sig []byte) error {
return rsa.VerifyPKCS1v15(pub, crypto.SHA256, hashed, sig)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment