Skip to content

Instantly share code, notes, and snippets.

@raztud
Last active October 1, 2024 05:00
Show Gist options
  • Save raztud/0e9b3d15a32ec6a5840e446c8e81e308 to your computer and use it in GitHub Desktop.
Save raztud/0e9b3d15a32ec6a5840e446c8e81e308 to your computer and use it in GitHub Desktop.
Sign string with go and openssl
package main
/**
With openssl command:
# echo -n "string to sign" | openssl rsautl -inkey private.key -sign|base64
or with openssl + sha256 (if it is used SignSHA256 function)
# openssl dgst -sha256 -sign private.key -out sign.txt.sha256 <(echo -n "string to sign") ; cat sign.txt.sha256 | base64
With sign.go
# go run sign.go -word="string to sign"
Both commands should produce the same results.
*/
import (
"fmt"
"errors"
"flag"
"io/ioutil"
"crypto"
"crypto/sha256"
"crypto/x509"
"crypto/rand"
"crypto/rsa"
"encoding/base64"
"encoding/pem"
"encoding/base64"
)
// A Signer is can create signatures that verify against a public key.
type Signer interface {
// Sign returns raw signature for the given data. This method
// will apply the hash specified for the key type to the data.
Sign(data []byte) ([]byte, error)
SignSHA256(data []byte) ([]byte, error)
}
type rsaPrivateKey struct {
*rsa.PrivateKey
}
const (
PRIVATE_KEY = "keys/private.key"
)
func loadPrivateKey(path string) (Signer, error) {
data, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
return ParsePrivateKey(data)
}
// parsePublicKey parses a PEM encoded private key.
func ParsePrivateKey(pemBytes []byte) (Signer, error) {
block, _ := pem.Decode(pemBytes)
if block == nil {
return nil, errors.New("crypto: no key found")
}
var rawkey interface{}
switch block.Type {
case "RSA PRIVATE KEY":
rsa, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
rawkey = rsa
default:
return nil, fmt.Errorf("crypto: unsupported private key type %q", block.Type)
}
return newSignerFromKey(rawkey)
}
func newSignerFromKey(k interface{}) (Signer, error) {
var sshKey Signer
switch t := k.(type) {
case *rsa.PrivateKey:
sshKey = &rsaPrivateKey{t}
default:
return nil, fmt.Errorf("crypto: unsupported key type %T", k)
}
return sshKey, nil
}
// Signs directly the data
func (r *rsaPrivateKey) Sign(data []byte) ([]byte, error) {
return rsa.SignPKCS1v15(nil, r.PrivateKey, 0, data)
}
// Sign signs data with rsa-sha256
func (r *rsaPrivateKey) SignSHA256(data []byte) ([]byte, error) {
h := sha256.New()
h.Write(data)
d := h.Sum(nil)
return rsa.SignPKCS1v15(rand.Reader, r.PrivateKey, crypto.SHA256, d)
}
func main() {
word := flag.String("word", "foo", "a string to encrypt")
flag.Parse()
toSign := *word
fmt.Println("word:", toSign)
signer, err := loadPrivateKey(PRIVATE_KEY);
if err != nil {
fmt.Printf("The signer could not be build: %v", err)
}
signed, err := signer.Sign([]byte(toSign))
//signed, err := signer.SignSHA256([]byte(toSign))
if err != nil {
fmt.Printf("Could not sign the request: %v", err)
}
sig := base64.StdEncoding.EncodeToString(signed)
fmt.Println(sig)
}
@bldrdash
Copy link

Thanks for the great work!

Would you be able to add license text at the bottom (or top) of the file so we can use it freely?

Thank You --

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment