How to Encrypt and Decrypt a String Using AES GCM 256 in Go

Created
Modified

In cryptography, Galois/Counter Mode (GCM) is a mode of operation for symmetric-key cryptographic block ciphers which is widely adopted for its performance.

Using NewGCM Function

The cipher.NewGCM(cipher Block) function returns the given 128-bit, block cipher wrapped in Galois Counter Mode with the standard nonce length.

The following example should cover whatever you are trying to do:

package main

import (
  "crypto/aes"
  "crypto/cipher"
  "crypto/rand"
  "encoding/hex"
  "fmt"
  "io"
)

func AesGCMIv() ([]byte, error) {
  // Never use more than 2^32 random nonces with a given key because of the risk of a repeat.
  nonce := make([]byte, 12)
  if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
    return nil, err
  }

  return nonce, nil
}

func AesGCMEncrypt(key string, text string) (string, error) {

  // When decoded the key should be 16 bytes (AES-128) or 32 (AES-256).
  block, err := aes.NewCipher([]byte(key))
  if err != nil {
    return "", err
  }
  plaintext := []byte(text)

  nonce, err := AesGCMIv()
  if err != nil {
    return "", err
  }

  aesgcm, err := cipher.NewGCM(block)
  if err != nil {
    return "", err
  }

  ciphertext := aesgcm.Seal(nonce, nonce, plaintext, nil)
  return fmt.Sprintf("%x", ciphertext), nil
}

func AesGCMDecrypt(key string, text string) (string, error) {

  // When decoded the key should be 16 bytes (AES-128) or 32 (AES-256).
  block, err := aes.NewCipher([]byte(key))
  if err != nil {
    return "", err
  }

  aesgcm, err := cipher.NewGCM(block)
  if err != nil {
    return "", err
  }

  in, _ := hex.DecodeString(text)
  ns := aesgcm.NonceSize()
  nonce, ciphertext := in[:ns], in[ns:]

  plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
  if err != nil {
    return "", err
  }

  return string(plaintext[:]), nil
}

func main() {
  s := "Hello"
  key := "zb0SLh88rdSHswjcgcC6949ZUuopGXTt"

  ciphertext, _ := AesGCMEncrypt(key, s)
  fmt.Println(ciphertext)

  plaintext, _ := AesGCMDecrypt(key, ciphertext)
  fmt.Printf("Decrypt:: %s\n", plaintext)
}
0680f8fef173fd969bb073d614e7059b62147b0e8eb6a7fdbe3040a8cd3a0d05c5
Decrypt:: Hello