This guide shows golang encrypt decrypt flows for small payloads using AES-256-GCM: a random nonce per message, Seal to produce ciphertext, Open to verify and recover plaintext, and base64 when you need a string transport. The same pattern applies to files by reading and writing []byte instead of string literals. Use keys from a secret manager or KDF in real systems—never hard-code production keys.
Tested with Go 1.24 on Linux.
Encrypt and decrypt a string
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
)
func encrypt(plaintext, key []byte) (string, error) {
block, err := aes.NewCipher(key)
if err != nil {
return "", err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", err
}
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return "", err
}
ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)
return base64.StdEncoding.EncodeToString(ciphertext), nil
}
func decrypt(enc string, key []byte) ([]byte, error) {
data, err := base64.StdEncoding.DecodeString(enc)
if err != nil {
return nil, err
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
ns := gcm.NonceSize()
if len(data) < ns {
return nil, fmt.Errorf("ciphertext too short")
}
return gcm.Open(nil, data[:ns], data[ns:], nil)
}
func main() {
key := make([]byte, 32)
if _, err := rand.Read(key); err != nil {
panic(err)
}
msg := []byte("secret data")
s, err := encrypt(msg, key)
if err != nil {
panic(err)
}
out, err := decrypt(s, key)
if err != nil {
panic(err)
}
fmt.Println(string(out))
}You should see secret data. The base64 string changes every run because the nonce is random.
Files and JSON
For files, os.ReadFile / os.WriteFile swap in place of string conversion; for JSON APIs, store ciphertext as base64 in a string field and parse after transport. Combine with JSON patterns when wrapping wire formats.
Summary
Modern golang encrypt decrypt code should use AES-GCM with 32-byte keys, random nonces, and authenticated Open on decrypt. Treat keys and KDF choice as part of your threat model; this article only demonstrates the crypto primitive shape.

