Last active
October 1, 2024 05:00
-
-
Save raztud/0e9b3d15a32ec6a5840e446c8e81e308 to your computer and use it in GitHub Desktop.
Sign string with go and openssl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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 --