package expose import ( "crypto/rand" "crypto/rsa" "crypto/sha512" "crypto/x509" "encoding/pem" "errors" "log" ) // GenerateKeyPair generates a new key pair func GenerateKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) { privkey, err := rsa.GenerateKey(rand.Reader, bits) if err != nil { return nil, nil, err } return privkey, &privkey.PublicKey, nil } // PrivateKeyToBytes private key to bytes func PrivateKeyToBytes(priv *rsa.PrivateKey) []byte { privBytes := pem.EncodeToMemory( &pem.Block{ Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv), }, ) return privBytes } // PublicKeyToBytes public key to bytes func PublicKeyToBytes(pub *rsa.PublicKey) ([]byte, error) { pubASN1, err := x509.MarshalPKIXPublicKey(pub) if err != nil { return []byte(""), err } pubBytes := pem.EncodeToMemory(&pem.Block{ Type: "RSA PUBLIC KEY", Bytes: pubASN1, }) return pubBytes, nil } // BytesToPrivateKey bytes to private key func BytesToPrivateKey(priv []byte) (*rsa.PrivateKey, error) { block, _ := pem.Decode(priv) enc := x509.IsEncryptedPEMBlock(block) b := block.Bytes var err error if enc { log.Println("is encrypted pem block") b, err = x509.DecryptPEMBlock(block, nil) if err != nil { return nil, err } } key, err := x509.ParsePKCS1PrivateKey(b) if err != nil { return nil, err } return key, nil } // BytesToPublicKey bytes to public key func BytesToPublicKey(pub []byte) (*rsa.PublicKey, error) { block, _ := pem.Decode(pub) enc := x509.IsEncryptedPEMBlock(block) b := block.Bytes var err error if enc { log.Println("is encrypted pem block") b, err = x509.DecryptPEMBlock(block, nil) if err != nil { return nil, err } } ifc, err := x509.ParsePKIXPublicKey(b) if err != nil { return nil, err } key, ok := ifc.(*rsa.PublicKey) if !ok { return nil, errors.New("key not valid") } return key, nil } // EncryptWithPublicKey encrypts data with public key func EncryptWithPublicKey(msg []byte, pub *rsa.PublicKey) ([]byte, error) { hash := sha512.New() ciphertext, err := rsa.EncryptOAEP(hash, rand.Reader, pub, msg, nil) if err != nil { return []byte(""), err } return ciphertext, nil } // DecryptWithPrivateKey decrypts data with private key func DecryptWithPrivateKey(ciphertext []byte, priv *rsa.PrivateKey) ([]byte, error) { hash := sha512.New() plaintext, err := rsa.DecryptOAEP(hash, rand.Reader, priv, ciphertext, nil) if err != nil { return []byte(""), err } return plaintext, nil }