RSA Encryption/Decryption in GoLang

RSA is a widely used cryptographical algorithm that uses public-key cryptography. It is one of the most important algorithms out there. This post will provide ways to generate RSA keys in GoLang.

How public-key encryption works?

Public key encryption uses two different keys named as the public key and private key. The sender encrypts the data using the public key of the receiver. The receiver receives the data and decrypts using the private key they have.

Let’s start creating encrypting data using RSA.

Required imports

Here are the required imports used in this code.

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
)

Observe that other than RSA package, there are other packages as such sha256, rand, base64. These packages will also be used.

Generating RSA keys

The generation of RSA keys is pretty simple. Here is the way it’s done.

privateKey, err := rsa.GenerateKey(rand.Reader, 2048)      // here 2048 is the number of bits for RSA
                                        // 1024 - 4096 supported

Now, just using the default encryption is not the standard. Hence, we use a padding algorithm like OAEP to make it more secure.

Now, the function below encrypts plaintext to 2048-bit RSA.

func RSA_OAEP_Encrypt(secretMessage string, key rsa.PublicKey) string {
	label := []byte("OAEP Encrypted")
	rng := rand.Reader
	ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, &key, []byte(secretMessage), label)
	CheckError(err)
	return base64.StdEncoding.EncodeToString(ciphertext)
}

The encrypt function from RSA package uses a hash. Here we use sha256, which is very reliable.

The public key can be obtained from the private key.

publicKey := privateKey.PublicKey

// encrypt data
encryptedMessage := RSA_OAEP_Encrypt(secretMessage, publicKey)

Now, we will see how to decrypt the message.

RSA decryption

The function below decrypts the RSA encrypted message. It takes in the private key and returns a string.

func RSA_OAEP_Decrypt(cipherText string, privKey rsa.PrivateKey) string {
	ct, _ := base64.StdEncoding.DecodeString(cipherText)
	label := []byte("OAEP Encrypted")
	rng := rand.Reader
	plaintext, err := rsa.DecryptOAEP(sha256.New(), rng, &privKey, ct, label)
	CheckError(err)
	fmt.Println("Plaintext:", string(plaintext))
	return string(plaintext)
}

Now we can call this function:

RSA_OAEP_Decrypt(encryptedMessage, *privateKey)

The output will be as follows:

Go Rsa
Go Rsa encrypt

The full source

Here is the full source of the program shown above.

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
)

func main() {
	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
	CheckError(err)

	publicKey := privateKey.PublicKey
	secretMessage := "This is super secret message!"

	encryptedMessage := RSA_OAEP_Encrypt(secretMessage, publicKey)

	fmt.Println("Cipher Text:", encryptedMessage)

	RSA_OAEP_Decrypt(encryptedMessage, *privateKey)
}

func CheckError(e error) {
	if e != nil {
		fmt.Println(e.Error)
	}
}

func RSA_OAEP_Encrypt(secretMessage string, key rsa.PublicKey) string {
	label := []byte("OAEP Encrypted")
	rng := rand.Reader
	ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, &key, []byte(secretMessage), label)
	CheckError(err)
	return base64.StdEncoding.EncodeToString(ciphertext)
}

func RSA_OAEP_Decrypt(cipherText string, privKey rsa.PrivateKey) string {
	ct, _ := base64.StdEncoding.DecodeString(cipherText)
	label := []byte("OAEP Encrypted")
	rng := rand.Reader
	plaintext, err := rsa.DecryptOAEP(sha256.New(), rng, &privKey, ct, label)
	CheckError(err)
	fmt.Println("Plaintext:", string(plaintext))
	return string(plaintext)
}