core/crypt/rsa.go

122 lines
2.8 KiB
Go

package crypt
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"log"
"golang.org/x/crypto/ssh"
)
type RsaEncrypt struct {
pub *rsa.PublicKey
}
func NewRsaEncrypt(key []byte) *RsaEncrypt {
pkey, _, _, _, err := ssh.ParseAuthorizedKey(key)
if err != nil {
log.Fatal("unable to parse authorized key")
}
// upgrade first to ssh.CryptoPublicKey interface
// then call CryptoPublicKey() to get actual crypto.PublicKey
// Finally, convert back to an *rsa.PublicKey
pubCrypto := pkey.(ssh.CryptoPublicKey).CryptoPublicKey()
return &RsaEncrypt{pubCrypto.(*rsa.PublicKey)}
}
func (re *RsaEncrypt) Encrypt(data []byte) (string, error) {
encryptedBytes, err := rsa.EncryptOAEP(
sha256.New(),
rand.Reader,
re.pub,
data,
nil)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(encryptedBytes), nil
}
type RsaKey struct {
priv *rsa.PrivateKey
}
func NewRsaKey(size int) *RsaKey {
key, err := rsa.GenerateKey(rand.Reader, size)
if err != nil {
log.Fatalf("unable to generate key with size %d", size)
}
return &RsaKey{key}
}
func LoadRsaKey(privKey []byte) *RsaKey {
block, _ := pem.Decode(privKey)
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
key.Size()
if err != nil {
log.Fatal("unable to parse pkcs1 priv key")
}
return &RsaKey{priv: key}
}
func (rk *RsaKey) GetBytes() []byte {
return pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(rk.priv),
})
}
func (rk *RsaKey) GetPubKeyBytes() []byte {
pub, err := ssh.NewPublicKey(rk.priv.Public())
if err != nil {
log.Fatal("unable to retriew public key")
}
return ssh.MarshalAuthorizedKey(pub)
}
func (rk *RsaKey) GetRsaEncrypt() *RsaEncrypt {
return &RsaEncrypt{&rk.priv.PublicKey}
}
func (rk *RsaKey) Decrypt(b64data []byte) ([]byte, error) {
data, err := base64.StdEncoding.DecodeString(string(b64data))
if err != nil {
log.Fatal("unable to decode base64 data")
}
decrypted, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, rk.priv, data, nil)
if err != nil {
log.Fatal("unable to decrypt data")
}
return decrypted, nil
}
func mainSshCrypt() {
rk := NewRsaKey(4096)
pubKey := rk.GetPubKeyBytes()
fmt.Println("== PUB KEY ==")
fmt.Println(string(pubKey))
fmt.Println("== PRIV KEY ==")
fmt.Println(string(rk.GetBytes()))
rk2 := LoadRsaKey(rk.GetBytes())
fmt.Println("== LOADED KEY ==")
fmt.Println(string(rk2.GetBytes()))
// fmt.Println("== GET RsaEncrypt ==")
// re := rk.GetRsaEncrypt()
fmt.Println("== NewRsaEncrypt ==")
re := NewRsaEncrypt(pubKey)
fmt.Println("== ENCRYPT data ==")
encryptedData, _ := re.Encrypt([]byte("hello world"))
fmt.Println(encryptedData)
decryptedData, _ := rk.Decrypt([]byte(encryptedData))
fmt.Println("== DECRYPT data ==")
fmt.Println(string(decryptedData))
}