Working with RSA Keys in Go

2 min read .

In this post, we’ll see how to work with RSA keys in Go for encryption, decryption, and digital signatures. RSA is a widely used asymmetric encryption algorithm. We will cover generating RSA keys, encrypting and decrypting messages, signing and verifying signatures, and provide instructions on how to generate RSA keys using OpenSSL.

Generating RSA Keys Using OpenSSL

Before diving into the Go code, let’s generate RSA keys using OpenSSL. This is useful if you need to create your own key pairs for use in the Go program.

  1. Generate a Private Key

    Use the following command to generate a 2048-bit RSA private key and save it to a file named private.pem:

    openssl genpkey -algorithm RSA -out private.pem -aes256

    This command generates a private key and encrypts it with AES-256. You will be prompted to enter a passphrase to protect the private key.

  2. Extract the Public Key

    Extract the public key from the private key file and save it to a file named public.pem:

    openssl rsa -pubout -in private.pem -out public.pem

    This command reads the private key and outputs the corresponding public key.

RSA Encryption and Decryption in Go

Here’s a Go program that demonstrates how to read RSA keys from files, encrypt and decrypt data, and sign and verify messages:

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io/ioutil"
)

func main() {
	// Read private key from file
	privateKeyBytes, err := ioutil.ReadFile("private.pem")
	if err != nil {
		panic(err)
	}

	// Decode private key from PEM format
	privateKeyBlock, _ := pem.Decode(privateKeyBytes)
	if privateKeyBlock == nil {
		panic("failed to parse private key")
	}

	// Parse the private key
	privateKey, err := x509.ParsePKCS8PrivateKey(privateKeyBlock.Bytes)
	if err != nil {
		panic(err)
	}

	// Convert private key to RSA type
	rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey)
	if !ok {
		panic("failed to convert private key to RSA")
	}

	// Example usage of the private key
	message := []byte("This is a message to be encrypted!")

	// Encrypt using the public key derived from the private key
	ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, &rsaPrivateKey.PublicKey, message)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Ciphertext: %x\n", ciphertext)

	// Decrypt using the private key
	plaintext, err := rsaPrivateKey.Decrypt(nil, ciphertext, &rsa.PKCS1v15DecryptOptions{})
	if err != nil {
		panic(err)
	}
	fmt.Printf("Plaintext: %s\n", plaintext)

	// Sign the message using the private key
	signature, err := rsa.SignPKCS1v15(rand.Reader, rsaPrivateKey, 0, message)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Signature: %x\n", signature)

	// Verify the signature using the public key
	err = rsa.VerifyPKCS1v15(&rsaPrivateKey.PublicKey, 0, message, signature)
	if err != nil {
		fmt.Println("Signature verification failed:", err)
	} else {
		fmt.Println("Signature verification succeeded.")
	}
}

Explanation of the Code

  1. Reading and Parsing the Private Key:

    • The private key is read from the private.pem file and decoded from PEM format.
    • It is then parsed into an rsa.PrivateKey type.
  2. Encrypting and Decrypting Data:

    • Data is encrypted using the public key (derived from the private key) and decrypted using the private key.
  3. Signing and Verifying Signatures:

    • The private key is used to sign a message.
    • The public key (derived from the private key) is used to verify the signature.

By following these steps and using the provided Go code, you can securely encrypt, decrypt, sign, and verify messages with RSA. The OpenSSL commands help you generate and manage RSA keys for use in your Go programs.

Tags:
Golang

See Also

chevron-up