Go AES Encryption Code Example (Online Runner)
Go AES examples with mode, padding, key size, and encoding controls to mirror the AES tool.
Online calculator: use the site AES tool.
Calculation method
The AES tool supports ECB/CBC/CFB/OFB/CTR modes, PKCS7 or zero padding (for block modes), key size selection, and hex or base64 ciphertext encodings. This helper mirrors those fields using Go's standard crypto packages.
Implementation notes
- Package: built-in
crypto/aesandcrypto/cipher. - Implementation: keys and IVs are normalized to the selected size to match the tool behavior.
- Notes: padding applies only to ECB/CBC. For real use, generate a random IV per message.
Text encryption example
go
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"fmt"
)
func aesCBCEncryptHex(plaintext string, keyHex string, ivHex string) (string, error) {
key, err := hex.DecodeString(keyHex)
if err != nil {
return "", err
}
iv, err := hex.DecodeString(ivHex)
if err != nil {
return "", err
}
block, err := aes.NewCipher(key)
if err != nil {
return "", err
}
padded := pkcs7Pad([]byte(plaintext), block.BlockSize())
out := make([]byte, len(padded))
cipher.NewCBCEncrypter(block, iv).CryptBlocks(out, padded)
return hex.EncodeToString(out), nil
}
func pkcs7Pad(data []byte, blockSize int) []byte {
padLen := blockSize - (len(data) % blockSize)
out := make([]byte, len(data)+padLen)
copy(out, data)
for i := len(data); i < len(out); i++ {
out[i] = byte(padLen)
}
return out
}
func main() {
keyHex := "00112233445566778899aabbccddeeff"
ivHex := "0102030405060708090a0b0c0d0e0f10"
value, err := aesCBCEncryptHex("hello", keyHex, ivHex)
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 Mode string
type Padding string
type KeyEncoding string
type CipherEncoding string
const (
ModeECB Mode = "ECB"
ModeCBC Mode = "CBC"
ModeCFB Mode = "CFB"
ModeOFB Mode = "OFB"
ModeCTR Mode = "CTR"
)
const (
PaddingPKCS7 Padding = "PKCS7"
PaddingZero Padding = "Zero"
)
const (
EncUTF8 KeyEncoding = "utf8"
EncHex KeyEncoding = "hex"
)
const (
CipherHex CipherEncoding = "hex"
CipherBase64 CipherEncoding = "base64"
)
func normalizeKey(key []byte, keySize int) []byte {
if len(key) >= keySize {
return key[:keySize]
}
out := make([]byte, keySize)
copy(out, key)
return out
}
func normalizeIV(iv []byte, blockSize int) []byte {
out := make([]byte, blockSize)
copy(out, iv)
return out
}
func decodeValue(value string, encoding KeyEncoding) ([]byte, error) {
if encoding == EncHex {
return hex.DecodeString(value)
}
return []byte(value), nil
}
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 pkcs7Pad(data []byte, blockSize int) []byte {
padLen := blockSize - (len(data) % blockSize)
out := make([]byte, len(data)+padLen)
copy(out, data)
for i := len(data); i < len(out); i++ {
out[i] = byte(padLen)
}
return out
}
func pkcs7Unpad(data []byte, blockSize int) ([]byte, error) {
if len(data) == 0 || len(data)%blockSize != 0 {
return nil, errors.New("invalid PKCS7 padding")
}
padLen := int(data[len(data)-1])
if padLen == 0 || padLen > blockSize {
return nil, errors.New("invalid PKCS7 padding")
}
for i := 0; i < padLen; i++ {
if data[len(data)-1-i] != byte(padLen) {
return nil, errors.New("invalid PKCS7 padding")
}
}
return data[:len(data)-padLen], nil
}
func zeroPad(data []byte, blockSize int) []byte {
if len(data)%blockSize == 0 {
return data
}
padLen := blockSize - (len(data) % blockSize)
out := make([]byte, len(data)+padLen)
copy(out, data)
return out
}
func zeroUnpad(data []byte) []byte {
end := len(data)
for end > 0 && data[end-1] == 0 {
end--
}
return data[:end]
}
func encryptECB(block cipher.Block, data []byte) []byte {
out := make([]byte, len(data))
for i := 0; i < len(data); i += block.BlockSize() {
block.Encrypt(out[i:], data[i:])
}
return out
}
func decryptECB(block cipher.Block, data []byte) []byte {
out := make([]byte, len(data))
for i := 0; i < len(data); i += block.BlockSize() {
block.Decrypt(out[i:], data[i:])
}
return out
}
func aesEncrypt(plaintext, key string, mode Mode, padding Padding, keyEncoding KeyEncoding, iv string, ivEncoding KeyEncoding, keySize int, outEncoding CipherEncoding) (string, error) {
keyBytes, err := decodeValue(key, keyEncoding)
if err != nil {
return "", err
}
ivBytes, err := decodeValue(iv, ivEncoding)
if err != nil {
return "", err
}
keyBytes = normalizeKey(keyBytes, keySize)
block, err := aes.NewCipher(keyBytes)
if err != nil {
return "", err
}
data := []byte(plaintext)
blockSize := block.BlockSize()
if mode == ModeECB || mode == ModeCBC {
if padding == PaddingPKCS7 {
data = pkcs7Pad(data, blockSize)
} else {
data = zeroPad(data, blockSize)
}
}
ivBytes = normalizeIV(ivBytes, blockSize)
var encrypted []byte
switch mode {
case ModeECB:
encrypted = encryptECB(block, data)
case ModeCBC:
encrypted = make([]byte, len(data))
cipher.NewCBCEncrypter(block, ivBytes).CryptBlocks(encrypted, data)
case ModeCFB:
encrypted = make([]byte, len(data))
cipher.NewCFBEncrypter(block, ivBytes).XORKeyStream(encrypted, data)
case ModeOFB:
encrypted = make([]byte, len(data))
cipher.NewOFB(block, ivBytes).XORKeyStream(encrypted, data)
case ModeCTR:
encrypted = make([]byte, len(data))
cipher.NewCTR(block, ivBytes).XORKeyStream(encrypted, data)
default:
return "", errors.New("unsupported mode")
}
return encodeCiphertext(encrypted, outEncoding), nil
}
func aesDecrypt(ciphertext, key string, mode Mode, padding Padding, keyEncoding KeyEncoding, iv string, ivEncoding KeyEncoding, keySize int, inEncoding CipherEncoding) (string, error) {
keyBytes, err := decodeValue(key, keyEncoding)
if err != nil {
return "", err
}
ivBytes, err := decodeValue(iv, ivEncoding)
if err != nil {
return "", err
}
keyBytes = normalizeKey(keyBytes, keySize)
block, err := aes.NewCipher(keyBytes)
if err != nil {
return "", err
}
data, err := decodeCiphertext(ciphertext, inEncoding)
if err != nil {
return "", err
}
blockSize := block.BlockSize()
ivBytes = normalizeIV(ivBytes, blockSize)
var decrypted []byte
switch mode {
case ModeECB:
decrypted = decryptECB(block, data)
case ModeCBC:
decrypted = make([]byte, len(data))
cipher.NewCBCDecrypter(block, ivBytes).CryptBlocks(decrypted, data)
case ModeCFB:
decrypted = make([]byte, len(data))
cipher.NewCFBDecrypter(block, ivBytes).XORKeyStream(decrypted, data)
case ModeOFB:
decrypted = make([]byte, len(data))
cipher.NewOFB(block, ivBytes).XORKeyStream(decrypted, data)
case ModeCTR:
decrypted = make([]byte, len(data))
cipher.NewCTR(block, ivBytes).XORKeyStream(decrypted, data)
default:
return "", errors.New("unsupported mode")
}
if mode == ModeECB || mode == ModeCBC {
if padding == PaddingPKCS7 {
decrypted, err = pkcs7Unpad(decrypted, blockSize)
if err != nil {
return "", err
}
} else {
decrypted = zeroUnpad(decrypted)
}
}
return string(decrypted), nil
}
func main() {
keyHex := "00112233445566778899aabbccddeeff"
ivHex := "0102030405060708090a0b0c0d0e0f10"
ciphertext, err := aesEncrypt("hello", keyHex, ModeCBC, PaddingPKCS7, EncHex, ivHex, EncHex, 16, CipherHex)
if err != nil {
panic(err)
}
fmt.Println("cipher=", ciphertext)
plain, err := aesDecrypt(ciphertext, keyHex, ModeCBC, PaddingPKCS7, EncHex, ivHex, EncHex, 16, CipherHex)
if err != nil {
panic(err)
}
fmt.Println("plain=", plain)
}