AES-GCM对称加密算法的使用

package main

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

// GetGCM
// @description 获取GCM密码器
// @return gcm cipher.AEAD GCM密码器
func GetGCM() (gcm cipher.AEAD) {
   // 加解或解密所需的密钥
   // 密钥有长度限制,使用不同长度密钥会选择不同算法,对应关系如下:
   // 密钥长度为16个字节:使用“AES-128”算法
   // 密钥长度为24个字节:使用“AES-192”算法
   // 密钥长度为32个字节:使用“AES-256”算法
   // 如果密钥长度不是16、24、32就会报错
   key := "12345678901234567890123456789012"

   block, err := aes.NewCipher([]byte(key))
   if err != nil {
      panic(err)
   }

   gcm, err = cipher.NewGCM(block)
   if err != nil {
      panic(err)
   }

   return
}

// Encrypt
// @description 加密
// @param msg string 要加密的消息
// @return ciphertext string 密文(重要提醒:密文包括消息和随机数两部分,解密时需要先将它们提取出来)
func Encrypt(msg string) (ciphertext string) {
   gcm := GetGCM() // 获取GCM密码器

   // 生成随机数用于加密,这样相同消息每次加密都会产生不同密文,注意解密也必须使用该随机数
   nonce := make([]byte, gcm.NonceSize())
   _, err := io.ReadFull(rand.Reader, nonce)
   if err != nil {
      panic(err)
   }

   // 加密
   encrypt := gcm.Seal(nil, nonce, []byte(msg), nil)

   // 原始密文和随机数都是一串乱码,将其编码方便传输和保存,这里采用十六进制编
   // 码,也可以根据需求选择其它编码方式(如base64编码),注意解密时需要先解码。
   ciphertext = hex.EncodeToString(encrypt) + hex.EncodeToString(nonce) // 消息+随机数

   return
}

// Decrypt
// @description 解密
// @param ciphertext string 密文(重要提醒:密文包括消息和随机数两部分,解密时需要先将它们提取出来)
// @return plaintext string 明文
func Decrypt(ciphertext string) (plaintext string) {
   gcm := GetGCM() // 获取GCM密码器

   // 提取出随机数和密文
   nonce := ciphertext[len(ciphertext)-gcm.NonceSize()*2:]     // 随机数
   ciphertext = ciphertext[:len(ciphertext)-gcm.NonceSize()*2] // 密文

   // 解码密文
   ciphertextByte, err := hex.DecodeString(ciphertext)
   if err != nil {
      panic(err)
   }

   // 解码随机数
   nonceByte, err := hex.DecodeString(nonce)
   if err != nil {
      panic(err)
   }

   // 解密
   decrypt, err := gcm.Open(nil, nonceByte, ciphertextByte, nil)
   if err != nil {
      panic(err)
   }

   plaintext = string(decrypt)

   return
}

func main() {
   // ========== 要加密的消息 ========== //
   msg := "PHP是世界上最好の语言"

   // ========== 加密 ========== //
   ciphertext := Encrypt(msg) // 每次产生的密文均不相同
   fmt.Printf("密文:%+v \n", ciphertext)
   // 密文:9bb9b9cf197d077bdf835d97ad3f54ca28caf54……

   // ========== 解密 ========== //
   plaintext := Decrypt(ciphertext)
   fmt.Printf("明文:%+v \n", plaintext)
   // 明文:PHP是世界上最好の语言
}

Copyright © 2024 码农人生. All Rights Reserved