Master Go Encryption: AES, GCM, RSA & Hashing with Real Code Examples

This guide explains how to implement symmetric (AES‑CBC, AES‑GCM) and asymmetric (RSA) encryption as well as hashing in Go, providing clear explanations and complete, runnable code samples for each technique.

FunTester
FunTester
FunTester
Master Go Encryption: AES, GCM, RSA & Hashing with Real Code Examples

Why Encryption Matters in Go

Encryption turns sensitive data such as credentials or payment information into unreadable ciphertext, while decryption restores it for authorized users; Go's crypto packages provide powerful yet easy‑to‑use tools for protecting API payloads, configuration files, and more.

Understanding Symmetric Encryption with AES

Symmetric encryption uses a single secret key for both encryption and decryption. AES is the dominant algorithm because of its efficiency and security. Go's crypto/aes package implements AES‑CBC and other modes, using 128‑, 192‑ or 256‑bit keys and a random initialization vector (IV) for each operation.

package main

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

// 主函数入口
func main() {
    plaintext := []byte("Hello, FunTester encryption!") // 明文内容
    key := []byte("32-byte-key-for-AES-256-!!!!!!!!")  // 32 字节密钥,用于 AES-256

    // 加密
    ciphertext, err := encryptAES(plaintext, key)
    if err != nil {
        fmt.Println("加密错误:", err)
        return
    }
    fmt.Printf("密文 (base64): %s
", base64.StdEncoding.EncodeToString(ciphertext))

    // 解密
    decrypted, err := decryptAES(ciphertext, key)
    if err != nil {
        fmt.Println("解密错误:", err)
        return
    }
    fmt.Printf("解密结果: %s
", decrypted)
}

// AES 加密函数,使用 CBC 模式
func encryptAES(plaintext, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key) // 创建 AES 密码块
    if err != nil {
        return nil, err
    }

    // 填充明文,保证长度为块大小的整数倍
    padding := aes.BlockSize - len(plaintext)%aes.BlockSize
    padtext := append(plaintext, bytes.Repeat([]byte{byte(padding)}, padding)...)

    ciphertext := make([]byte, aes.BlockSize+len(padtext)) // 分配密文空间
    iv := ciphertext[:aes.BlockSize] // 生成初始化向量 IV
    if _, err := io.ReadFull(rand.Reader, iv); err != nil {
        return nil, err
    }

    mode := cipher.NewCBCEncrypter(block, iv) // 创建 CBC 加密器
    mode.CryptBlocks(ciphertext[aes.BlockSize:], padtext) // 加密数据

    return ciphertext, nil
}

// AES 解密函数,使用 CBC 模式
func decryptAES(ciphertext, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key) // 创建 AES 密码块
    if err != nil {
        return nil, err
    }
    if len(ciphertext) < aes.BlockSize {
        return nil, fmt.Errorf("密文长度不足")
    }
    iv := ciphertext[:aes.BlockSize] // 取出初始化向量 IV
    ciphertext = ciphertext[aes.BlockSize:] // 取出实际密文

    mode := cipher.NewCBCDecrypter(block, iv) // 创建 CBC 解密器
    mode.CryptBlocks(ciphertext, ciphertext) // 解密数据

    // 去除填充,恢复原始明文
    padding := int(ciphertext[len(ciphertext)-1])
    return ciphertext[:len(ciphertext)-padding], nil
}

// 输出示例:
// 密文 (base64): [随机生成的 base64 字符串]
// 解密结果: Hello, FunTester encryption!

Exploring Authenticated Encryption with AES‑GCM

AES‑GCM provides confidentiality, integrity, and authenticity without manual padding, using a built‑in authentication tag and a nonce to prevent replay attacks. Go's crypto/cipher package natively supports GCM, making it ideal for HTTPS and API token encryption.

package main

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

func main() {
    plaintext := []byte("Secure data with GCM!")
    key := []byte("32-byte-key-for-AES-256-!!!!!!!!") // 32 bytes for AES-256

    // Encrypt
    ciphertext, err := encryptGCM(plaintext, key)
    if err != nil {
        fmt.Println("加密错误:", err)
        return
    }
    fmt.Printf("密文 (base64): %s
", base64.StdEncoding.EncodeToString(ciphertext))

    // Decrypt
    decrypted, err := decryptGCM(ciphertext, key)
    if err != nil {
        fmt.Println("解密错误:", err)
        return
    }
    fmt.Printf("解密结果: %s
", decrypted)
}

func encryptGCM(plaintext, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    gcm, err := cipher.NewGCM(block)
    if err != nil {
        return nil, err
    }
    nonce := make([]byte, gcm.NonceSize())
    if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
        return nil, err
    }
    return gcm.Seal(nonce, nonce, plaintext, nil), nil
}

func decryptGCM(ciphertext, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    gcm, err := cipher.NewGCM(block)
    if err != nil {
        return nil, err
    }
    nonceSize := gcm.NonceSize()
    if len(ciphertext) < nonceSize {
        return nil, fmt.Errorf("密文长度不足")
    }
    nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
    return gcm.Open(nil, nonce, ciphertext, nil)
}

// 输出示例:
// 密文 (base64): [随机生成的 base64 字符串]
// 解密结果: Secure data with GCM!

RSA Asymmetric Encryption

Asymmetric encryption separates public‑key encryption from private‑key decryption, suitable for secure key exchange or encrypting small data. Go's crypto/rsa package implements RSA, which is often combined with symmetric encryption in a hybrid scheme to balance security and performance.

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/sha256"
    "encoding/base64"
    "fmt"
)

func main() {
    // 生成密钥对
    privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
    if err != nil {
        fmt.Println("密钥生成错误:", err)
        return
    }
    publicKey := &privateKey.PublicKey

    // 加密
    plaintext := []byte("RSA encryption in Go!")
    ciphertext, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, plaintext, nil)
    if err != nil {
        fmt.Println("加密错误:", err)
        return
    }
    fmt.Printf("密文 (base64): %s
", base64.StdEncoding.EncodeToString(ciphertext))

    // 解密
    decrypted, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, ciphertext, nil)
    if err != nil {
        fmt.Println("解密错误:", err)
        return
    }
    fmt.Printf("解密结果: %s
", decrypted)
}

// 输出示例:
// 密文 (base64): [随机生成的 base64 字符串]
// 解密结果: RSA encryption in Go!

Hash vs Encryption: What’s the Difference?

Hashing is a one‑way operation used for data integrity checks (e.g., passwords), whereas encryption is reversible and used for confidentiality. Go provides crypto/sha256 and other hash functions alongside its encryption libraries.

Example: SHA‑256 Hashing

package main

import (
    "crypto/sha256"
    "encoding/hex"
    "fmt"
)

func main() {
    data := []byte("Hash this string!")
    hash := sha256.Sum256(data)
    fmt.Printf("SHA-256 Hash: %s
", hex.EncodeToString(hash[:]))
    // 输出示例:
    // SHA-256 Hash: 2c7a6e66323c8f7a0e205803c763eb8a4e8b6f8b0b2c3f8a7e8f9d0b1e2c3d4e
}

Example: Generating a Secure Key

package main

import (
    "crypto/rand"
    "encoding/hex"
    "fmt"
)

func main() {
    key := make([]byte, 32) // 32 bytes for AES-256
    _, err := rand.Read(key)
    if err != nil {
        fmt.Println("密钥生成错误:", err)
        return
    }
    fmt.Printf("生成的密钥: %s
", hex.EncodeToString(key))
    // 输出示例:
    // 生成的密钥: [随机生成的 64 字符十六进制字符串]
}
GosecurityRSAencryptionhashingAES
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.