1. 程式人生 > 實用技巧 >go AES 加密 和解密

go AES 加密 和解密

其實網上關於aes加密和解密的文章很多,尤其是 https://cloud.tencent.com/developer/section/1140748, 只是我個人喜歡用字串形式,所以整理了一下:

package utils

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

/*
    AES  CBC 加密
    key:加密key
    plaintext:加密明文
    ciphertext:解密返回位元組字串[ 整型以十六進位制方式顯示]

*/ func AESCBCEncrypt(key, plaintext string) (ciphertext string) { plainbyte := []byte(plaintext) keybyte := []byte(key) if len(plainbyte)%aes.BlockSize != 0 { panic("plaintext is not a multiple of the block size") } block, err := aes.NewCipher(keybyte) if err != nil { panic(err) } cipherbyte :
= make([]byte, aes.BlockSize+len(plainbyte)) iv := cipherbyte[:aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { panic(err) } mode := cipher.NewCBCEncrypter(block, iv) mode.CryptBlocks(cipherbyte[aes.BlockSize:], plainbyte) ciphertext = fmt.Sprintf("
%x\n", cipherbyte) return } /* AES CBC 解碼 key:解密key ciphertext:加密返回的串 plaintext:解密後的字串 */ func AESCBCDecrypter(key, ciphertext string) (plaintext string) { cipherbyte, _ := hex.DecodeString(ciphertext) keybyte := []byte(key) block, err := aes.NewCipher(keybyte) if err != nil { panic(err) } if len(cipherbyte) < aes.BlockSize { panic("ciphertext too short") } iv := cipherbyte[:aes.BlockSize] cipherbyte = cipherbyte[aes.BlockSize:] if len(cipherbyte)%aes.BlockSize != 0 { panic("ciphertext is not a multiple of the block size") } mode := cipher.NewCBCDecrypter(block, iv) mode.CryptBlocks(cipherbyte, cipherbyte) //fmt.Printf("%s\n", ciphertext) plaintext = string(cipherbyte[:]) return } /* AES GCM 加密 key:加密key plaintext:加密明文 ciphertext:解密返回位元組字串[ 整型以十六進位制方式顯示] */ func AESGCMEncrypt(key, plaintext string) (ciphertext, noncetext string) { plainbyte := []byte(plaintext) keybyte := []byte(key) block, err := aes.NewCipher(keybyte) if err != nil { panic(err.Error()) } // 由於存在重複的風險,請勿使用給定金鑰使用超過2^32個隨機值。 nonce := make([]byte, 12) if _, err := io.ReadFull(rand.Reader, nonce); err != nil { panic(err.Error()) } aesgcm, err := cipher.NewGCM(block) if err != nil { panic(err.Error()) } cipherbyte := aesgcm.Seal(nil, nonce, plainbyte, nil) ciphertext = fmt.Sprintf("%x\n", cipherbyte) noncetext = fmt.Sprintf("%x\n", nonce) return } /* AES CBC 解碼 key:解密key ciphertext:加密返回的串 plaintext:解密後的字串 */ func AESGCMDecrypter(key, ciphertext, noncetext string) (plaintext string) { cipherbyte, _ := hex.DecodeString(ciphertext) nonce, _ := hex.DecodeString(noncetext) keybyte := []byte(key) block, err := aes.NewCipher(keybyte) if err != nil { panic(err.Error()) } aesgcm, err := cipher.NewGCM(block) if err != nil { panic(err.Error()) } plainbyte, err := aesgcm.Open(nil, nonce, cipherbyte, nil) if err != nil { panic(err.Error()) } //fmt.Printf("%s\n", ciphertext) plaintext = string(plainbyte[:]) return }

使用很簡單:

key := "example key 1234"
plaintext := "exampleplaintext"
ciphertext := utils.AESCBCEncrypt(key, plaintext)
fmt.Println(ciphertext)

plaintext = utils.AESCBCDecrypter(key, ciphertext)
fmt.Println(plaintext)
///GCM
noncetext := ""
ciphertext, noncetext = utils.AESGCMEncrypt(key, plaintext)
fmt.Println(ciphertext)

plaintext = utils.AESGCMDecrypter(key, ciphertext, noncetext)
fmt.Println(plaintext)