Go AES-GCM Code Example (Online Runner)

Go AES-GCM examples with tag length, AAD, and encoding controls matching the AES-GCM tool.

Online calculator: use the site AES-GCM tool.

Calculation method

AES-GCM combines encryption and authentication. The tool concatenates ciphertext + tag; this helper matches that output.

Implementation notes

  • Package: built-in crypto/aes and crypto/cipher.
  • Implementation: Seal returns ciphertext+tag, which matches the UI output.
  • Notes: nonces must be unique per key; AAD must match during decryption.

Text encryption example

go
package main

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

func aesGCMEncryptHex(plaintext string, keyHex string, nonceHex string) (string, error) {
	key, err := hex.DecodeString(keyHex)
	if err != nil {
		return "", err
	}
	nonce, err := hex.DecodeString(nonceHex)
	if err != nil {
		return "", err
	}
	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}
	aead, err := cipher.NewGCM(block)
	if err != nil {
		return "", err
	}
	out := aead.Seal(nil, nonce, []byte(plaintext), nil)
	return hex.EncodeToString(out), nil
}

func main() {
	keyHex := "00112233445566778899aabbccddeeff"
	nonceHex := "0102030405060708090a0b0c"
	value, err := aesGCMEncryptHex("hello", keyHex, nonceHex)
	if err != nil {
		panic(err)
	}
	fmt.Println(value)
}

Complete script (implementation + tests)

go
package main

import (
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"fmt"
)

type KeyEncoding string

type CipherEncoding string

const (
	EncUTF8 KeyEncoding = "utf8"
	EncHex  KeyEncoding = "hex"
)

const (
	CipherHex    CipherEncoding = "hex"
	CipherBase64 CipherEncoding = "base64"
)

func decodeValue(value string, encoding KeyEncoding) ([]byte, error) {
	if encoding == EncHex {
		return hex.DecodeString(value)
	}
	return []byte(value), nil
}

func normalizeKey(key []byte, keySize int) []byte {
	if len(key) >= keySize {
		return key[:keySize]
	}
	out := make([]byte, keySize)
	copy(out, key)
	return out
}

func encodeCiphertext(data []byte, encoding CipherEncoding) string {
	if encoding == CipherHex {
		return hex.EncodeToString(data)
	}
	return base64.StdEncoding.EncodeToString(data)
}

func decodeCiphertext(value string, encoding CipherEncoding) ([]byte, error) {
	if encoding == CipherHex {
		return hex.DecodeString(value)
	}
	return base64.StdEncoding.DecodeString(value)
}

func aesGCMEncrypt(plaintext, key, nonce string, keyEnc, nonceEnc KeyEncoding, aad string, aadEnc KeyEncoding, tagLen, keySize int, outEnc CipherEncoding) (string, error) {
	keyBytes, err := decodeValue(key, keyEnc)
	if err != nil {
		return "", err
	}
	nonceBytes, err := decodeValue(nonce, nonceEnc)
	if err != nil {
		return "", err
	}
	keyBytes = normalizeKey(keyBytes, keySize)
	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return "", err
	}
	aead, err := cipher.NewGCMWithTagSize(block, tagLen)
	if err != nil {
		return "", err
	}
	var aadBytes []byte
	if aad != "" {
		aadBytes, err = decodeValue(aad, aadEnc)
		if err != nil {
			return "", err
		}
	}
	ciphertext := aead.Seal(nil, nonceBytes, []byte(plaintext), aadBytes)
	return encodeCiphertext(ciphertext, outEnc), nil
}

func aesGCMDecrypt(combined, key, nonce string, keyEnc, nonceEnc KeyEncoding, aad string, aadEnc KeyEncoding, tagLen, keySize int, inEnc CipherEncoding) (string, error) {
	keyBytes, err := decodeValue(key, keyEnc)
	if err != nil {
		return "", err
	}
	nonceBytes, err := decodeValue(nonce, nonceEnc)
	if err != nil {
		return "", err
	}
	keyBytes = normalizeKey(keyBytes, keySize)
	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return "", err
	}
	aead, err := cipher.NewGCMWithTagSize(block, tagLen)
	if err != nil {
		return "", err
	}
	data, err := decodeCiphertext(combined, inEnc)
	if err != nil {
		return "", err
	}
	if len(data) < tagLen {
		return "", errors.New("ciphertext must include tag")
	}
	var aadBytes []byte
	if aad != "" {
		aadBytes, err = decodeValue(aad, aadEnc)
		if err != nil {
			return "", err
		}
	}
	plaintext, err := aead.Open(nil, nonceBytes, data, aadBytes)
	if err != nil {
		return "", err
	}
	return string(plaintext), nil
}

func main() {
	key := "00112233445566778899aabbccddeeff"
	nonce := "0102030405060708090a0b0c"

	ciphertext, err := aesGCMEncrypt("hello", key, nonce, EncHex, EncHex, "context", EncUTF8, 16, 16, CipherHex)
	if err != nil {
		panic(err)
	}
	fmt.Println("cipher=", ciphertext)

	plain, err := aesGCMDecrypt(ciphertext, key, nonce, EncHex, EncHex, "context", EncUTF8, 16, 16, CipherHex)
	if err != nil {
		panic(err)
	}
	fmt.Println("plain=", plain)
}