Jay Taylor's notes

back to listing index

Implementing RSA encryption in golang - Giorgis.io

[web search]
Original source (blog.giorgis.io)
Tags: encryption golang go cryptography rsa blog.giorgis.io
Clipped on: 2015-07-08

Image (Asset 1/1) alt=

Implementing RSA encryption in golang

RSA is the most widely used Public-key Cryptosystems. The encryption and decryption keys are different from each other, one of which is secret (or private) and one of which is public.

Data is encrypted with a recipient's public key.

AES on the other hand requires same encryption and decryption key. Implementing Golang AES Encryption)

The following example shows how to RSA encrypt, and decrypt data:

Also on Github

package main

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

func main() {

    var private_key *rsa.PrivateKey
    var public_key *rsa.PublicKey
    var plain_text, encrypted, decrypted, label []byte
    var err error

    plain_text = []byte("Plain text message to be encrypted")

    //Generate Private Key
    if private_key, err = rsa.GenerateKey(rand.Reader, 1024); err != nil {
        log.Fatal(err)
    }
    fmt.Println(private_key)

    // Precompute some calculations -- Calculations that speed up private key operations in the future
    private_key.Precompute()

    //Validate Private Key -- Sanity checks on the key
    if err = private_key.Validate(); err != nil {
        log.Fatal(err)
    }

    //Public key address (of an RSA key)
    public_key = &private_key.PublicKey

    encrypted = encrypt_oaep(public_key, plain_text, label)
    decrypted = decrypt_oaep(private_key, encrypted, label)

    fmt.Printf("OAEP Encrypted [%s] to \n[%x]\n", string(plain_text), encrypted)
    fmt.Printf("OAEP Decrypted [%x] to \n[%s]\n", encrypted, decrypted)

    // To use existing private key (Skipping the GenerateKey, Precompute, Validation steps shown above)
    // This reads pem file and retrieves the public, private key needed to encrypt data
    use_exsiting_keys()

}

func use_exsiting_keys() {

    var pem_file_path string
    var err error
    var block *pem.Block
    var private_key *rsa.PrivateKey
    var public_key *rsa.PublicKey
    var pem_data, plain_text, encrypted, decrypted, label []byte

    plain_text = []byte("Plain text message to be encrypted")

    // A PEM file can contain a Private key among others (Public certificate, Intermidiate Certificate, Root certificate, ...)
    pem_file_path = "/path/to/pem/file"
    if pem_data, err = ioutil.ReadFile(pem_file_path); err != nil {
        log.Fatalf("Error reading pem file: %s", err)
    }

    //Package pem implements the PEM data encoding, most commonly used in TLS keys and certificates.
    //Decode will find the next PEM formatted block (certificate, private key etc) in the input.
    //Expected Block type "RSA PRIVATE KEY"
    //http://golang.org/pkg/encoding/pem/
    if block, _ = pem.Decode(pem_data); block == nil || block.Type != "RSA PRIVATE KEY" {
        log.Fatal("No valid PEM data found")
    }

    //x509 parses X.509-encoded keys and certificates.
    //ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form.
    if private_key, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {
        log.Fatalf("Private key can't be decoded: %s", err)
    }

    public_key = &private_key.PublicKey

    encrypted = encrypt_oaep(public_key, plain_text, label)
    decrypted = decrypt_oaep(private_key, encrypted, label)

    fmt.Printf("OAEP Encrypted [%s] to \n[%x]\n", string(plain_text), encrypted)
    fmt.Printf("OAEP Decrypted [%x] to \n[%s]\n", encrypted, decrypted)

    return
}

//OAEP Encrypt
func encrypt_oaep(public_key *rsa.PublicKey, plain_text, label []byte) (encrypted []byte) {
    var err error
    var md5_hash hash.Hash

    md5_hash = md5.New()

    if encrypted, err = rsa.EncryptOAEP(md5_hash, rand.Reader, public_key, plain_text, label); err != nil {
        log.Fatal(err)
    }
    return
}

func decrypt_oaep(private_key *rsa.PrivateKey, encrypted, label []byte) (decrypted []byte) {
    var err error
    var md5_hash hash.Hash

    md5_hash = md5.New()
    if decrypted, err = rsa.DecryptOAEP(md5_hash, rand.Reader, private_key, encrypted, label); err != nil {
        log.Fatal(err)
    }
    return
}

By H.G. Giorgis

2 May 2015

Blog's server code borrowed from Go Blog server code.
All Copyrights Reserved