Skip to content

Instantly share code, notes, and snippets.

@wongoo
Created August 1, 2019 03:19
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wongoo/2b974a9594627114bea3e53c794980cd to your computer and use it in GitHub Desktop.
Save wongoo/2b974a9594627114bea3e53c794980cd to your computer and use it in GitHub Desktop.
golang RSA utility, include encrypt/decrypt/signature
//author: http://github.com/wongoo
//date: 20190717
package rsautil
import (
"bytes"
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/x509"
"encoding/base64"
"errors"
)
const (
rsaKeySize = 2048
)
func hash(data []byte) []byte {
s := sha1.Sum(data)
return s[:]
}
func GenerateKey() (*rsa.PrivateKey, *rsa.PublicKey, error) {
pri, err := rsa.GenerateKey(rand.Reader, rsaKeySize)
if err != nil {
return nil, nil, err
}
return pri, &pri.PublicKey, nil
}
func GenerateKeyBytes() (privateBytes, publicBytes []byte, err error) {
pri, pub, err := GenerateKey()
if err != nil {
return nil, nil, err
}
priBytes, err := x509.MarshalPKCS8PrivateKey(pri)
if err != nil {
return nil, nil, err
}
pubBytes := x509.MarshalPKCS1PublicKey(pub)
return priBytes, pubBytes, nil
}
func GenerateKey64() (pri64, pub64 string, err error) {
pri, pub, err := GenerateKeyBytes()
if err != nil {
return "", "", nil
}
return base64.StdEncoding.EncodeToString(pri),
base64.StdEncoding.EncodeToString(pub),
nil
}
func PublicKeyFrom(key []byte) (*rsa.PublicKey, error) {
pubInterface, err := x509.ParsePKIXPublicKey(key)
if err != nil {
return nil, err
}
pub, ok := pubInterface.(*rsa.PublicKey)
if !ok {
return nil, errors.New("invalid public key")
}
return pub, nil
}
func PublicKeyFrom64(key string) (*rsa.PublicKey, error) {
b, err := base64.StdEncoding.DecodeString(key)
if err != nil {
return nil, err
}
return PublicKeyFrom(b)
}
func PrivateKeyFrom(key []byte) (*rsa.PrivateKey, error) {
pri, err := x509.ParsePKCS8PrivateKey(key)
if err != nil {
return nil, err
}
p, ok := pri.(*rsa.PrivateKey)
if !ok {
return nil, errors.New("invalid private key")
}
return p, nil
}
func PrivateKeyFrom64(key string) (*rsa.PrivateKey, error) {
b, err := base64.StdEncoding.DecodeString(key)
if err != nil {
return nil, err
}
return PrivateKeyFrom(b)
}
func PublicEncrypt(key *rsa.PublicKey, data []byte) ([]byte, error) {
return rsa.EncryptPKCS1v15(rand.Reader, key, data)
}
func PublicSign(key *rsa.PublicKey, data []byte) ([]byte, error) {
return PublicEncrypt(key, hash(data))
}
func PublicVerify(key *rsa.PublicKey, sign, data []byte) error {
return rsa.VerifyPKCS1v15(key, crypto.SHA1, hash(data), sign)
}
func PrivateDecrypt(key *rsa.PrivateKey, data []byte) ([]byte, error) {
return rsa.DecryptPKCS1v15(rand.Reader, key, data)
}
func PrivateSign(key *rsa.PrivateKey, data []byte) ([]byte, error) {
return rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA1, hash(data))
}
func PrivateVerify(key *rsa.PrivateKey, sign, data []byte) error {
h, err := PrivateDecrypt(key, sign)
if err != nil {
return err
}
if !bytes.Equal(h, hash(data)) {
return rsa.ErrVerification
}
return nil
}
@Sulejman
Copy link

Sulejman commented Jan 7, 2020

This generates always same encryption keypair.

@wongoo
Copy link
Author

wongoo commented Jan 8, 2020

This generates always same encryption keypair.

are u sure? do u compare all the content of the generated key?

@RajaSrinivasan
Copy link

Just tried to replicate. On my Mac yes running it back to back appears to generate the same bytes.

@RajaSrinivasan
Copy link

Sorry spoke too soon. I think it just appears so. but they are different. Since the Private key bytes is long, just compared initial segment. Comparing all the bytes reveals differences.

@nexus166
Copy link

SHA1? Are you in some parallel dimension two decades behind?

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