AES encryption in Go

Here is a program I wrote to learn how to use the Go libraries for AES encryption.

package main

import (
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"log"
)

// AESCipher encrypts and decrypts data using the AES specification.
type AESCipher struct {
	stream cipher.Stream
}

// AESDecipher encrypts and decrypts data using the AES specification.
type AESDecipher struct {
	stream cipher.Stream
}

// Encrypt encrypts the specified plaintext and returns the ciphertext in base64 format.
func (t *AESCipher) Encrypt(plaintext string) string {
	plaintextBytes := []byte(plaintext)
	t.stream.XORKeyStream(plaintextBytes, plaintextBytes)
	return base64.StdEncoding.EncodeToString(plaintextBytes)
}

// Decrypt decrypts the specified ciphertext (in base64 format) and returns the plaintext.
func (t *AESDecipher) Decrypt(ciphertext string) (string, error) {
	ciphertextBytes, err := base64.StdEncoding.DecodeString(ciphertext)
	if err != nil {
		return "", err
	}

	t.stream.XORKeyStream(ciphertextBytes, ciphertextBytes)
	return string(ciphertextBytes), nil
}

// NewAESCipher creates a new AESCipher with the specified key and initialization vector.
// The key must be 16, 24, or 32 bytes long
// The IV must be 16 bytes long.
func NewAESCipher(key, iv []byte) *AESCipher {
	c, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}
	return &AESCipher{stream: cipher.NewCTR(c, iv)}
}

// NewAESCipher creates a new AESCipher with the specified key and initialization vector.
// The key must be 16, 24, or 32 bytes long
// The IV must be 16 bytes long.
func NewAESDecipher(key, iv []byte) *AESDecipher {
	c, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}
	return &AESDecipher{stream: cipher.NewCTR(c, iv)}
}

func main() {
	log.SetFlags(0)
	key :=[]byte("hNmicW5oHRgc8ZlWFS0ketaBxke6Eu7O") // 32-byte random string
	iv :=[]byte( "0zIZD3VTHnbsv5Mp") // 16-byte random string

	enc := NewAESCipher(key, iv)
	plaintext := "{\"message\": \"Hello, there!\"}"
	ciphertext := enc.Encrypt(plaintext)
	log.Printf("Plaintext: %s", plaintext)
	log.Printf("Ciphertext: %s", ciphertext)

	dec := NewAESDecipher(key, iv)
	plaintext2, err := dec.Decrypt(ciphertext)
	if err != nil {
		log.Fatalf("Unable to decrypt ciphertext: %s", err)
	}
	log.Printf("Decrypted ciphertext: %s", plaintext2)
}

Build & run

$ go build -o main
$ ./main
Plaintext: {"message": "Hello, there!"}
Ciphertext: t7N5/VgaacwUM6t90hyVkGm0nlEhOeLBf49m+Q==
Decrypted ciphertext: {"message": "Hello, there!"}

I hope it helps.

References

This entry was posted in Posts, SoftwareEngineering. Bookmark the permalink.