Use the crypto/rsa package to generate a key pair, then encrypt data with the public key using PKCS#1 v1.5 or OAEP padding, and decrypt it with the private key. Always prefer OAEP padding for new applications as it provides stronger security guarantees against chosen-ciphertext attacks compared to the older PKCS#1 v1.5 standard.
Here is a complete, practical example generating a key pair and performing encryption/decryption with OAEP padding:
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
"log"
)
func main() {
// 1. Generate a new RSA key pair (2048 bits is standard)
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
log.Fatal(err)
}
publicKey := &privateKey.PublicKey
// 2. Prepare data to encrypt
// Note: RSA has a size limit based on key size and padding.
// For 2048-bit key with OAEP+SHA256, max plaintext is ~190 bytes.
plaintext := []byte("Secret message for encryption")
// 3. Encrypt using OAEP padding (more secure than PKCS1v15)
ciphertext, err := rsa.EncryptOAEP(
sha256.New(),
rand.Reader,
publicKey,
plaintext,
nil, // Optional label
)
if err != nil {
log.Fatal(err)
}
// 4. Decrypt using the private key
decrypted, err := rsa.DecryptOAEP(
sha256.New(),
rand.Reader,
privateKey,
ciphertext,
nil, // Must match the label used during encryption
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Original: %s\n", plaintext)
fmt.Printf("Decrypted: %s\n", decrypted)
}
If you need to encrypt data larger than the RSA block size limit (approx. 190 bytes for a 2048-bit key), do not use RSA directly on the large payload. Instead, implement a hybrid encryption scheme: generate a random symmetric key (e.g., AES), encrypt the large data with that key, and then encrypt the small symmetric key using RSA. This is the standard pattern used in TLS and PGP.
When persisting keys, use x509.MarshalPKCS1PrivateKey for the private key and x509.MarshalPKIXPublicKey for the public key to get standard binary formats, or use pem.EncodeToMemory to wrap them in PEM format for storage in files. Never hardcode private keys in your source code; load them securely from environment variables or a secrets manager at runtime.