CBC
package main
import (
"bytes"
"crypto/cipher"
"crypto/aes"
"encoding/base64"
"fmt"
)
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext) % blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
func PKCS7UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
func AesEncrypt(origData, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
origData = PKCS7Padding(origData, blockSize)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
crypted := make([]byte, len(origData))
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}
func AesDecrypt(crypted, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
origData := make([]byte, len(crypted))
blockMode.CryptBlocks(origData, crypted)
origData = PKCS7UnPadding(origData)
return origData, nil
}
func main() {
key := []byte("0123456789abcdef")
result, err := AesEncrypt([]byte("hello world"), key)
if err != nil {
panic(err)
}
fmt.Println(base64.StdEncoding.EncodeToString(result))
origData, err := AesDecrypt(result, key)
if err != nil {
panic(err)
}
fmt.Println(string(origData))
}
CFB 模式
package main
import (
"io"
"crypto/cipher"
"crypto/aes"
"crypto/rand"
"encoding/base64"
"fmt"
)
func AesEncrypt(plaintext, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
return ciphertext, nil
}
func AesDecrypt(ciphertext, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
if len(ciphertext) < aes.BlockSize {
panic("ciphertext too short")
}
iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(ciphertext, ciphertext)
return ciphertext, nil
}
func main() {
key := []byte("0123456789abcdef")
result, err := AesEncrypt([]byte("hello world"), key)
if err != nil {
panic(err)
}
fmt.Println(base64.StdEncoding.EncodeToString(result))
origData, err := AesDecrypt(result, key)
if err != nil {
panic(err)
}
fmt.Println(string(origData))
}
OFB 模式
package main
import (
"io"
"crypto/cipher"
"crypto/aes"
"crypto/rand"
"encoding/base64"
"fmt"
)
func AesEncrypt(plaintext, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
return ciphertext, nil
}
func AesDecrypt(ciphertext, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
iv := ciphertext[:aes.BlockSize]
if len(ciphertext) < aes.BlockSize {
panic("ciphertext too short")
}
plaintext2 := make([]byte, len(ciphertext))
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
return plaintext2, nil
}
func main() {
key := []byte("6368616e676520746869732070617374")
result, err := AesEncrypt([]byte("hello world"), key)
if err != nil {
panic(err)
}
fmt.Println(base64.StdEncoding.EncodeToString(result))
origData, err := AesDecrypt(result, key)
if err != nil {
panic(err)
}
fmt.Println(string(origData))
}
CTR模式
package main
import (
"io"
"crypto/cipher"
"crypto/aes"
"crypto/rand"
"encoding/base64"
"fmt"
)
func AesEncrypt(plaintext, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
return ciphertext, nil
}
func AesDecrypt(ciphertext, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
iv := ciphertext[:aes.BlockSize]
if len(ciphertext) < aes.BlockSize {
panic("ciphertext too short")
}
plaintext2 := make([]byte, len(ciphertext))
stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
return plaintext2, nil
}
func main() {
key := []byte("6368616e676520746869732070617374")
result, err := AesEncrypt([]byte("hello world"), key)
if err != nil {
panic(err)
}
fmt.Println(base64.StdEncoding.EncodeToString(result))
origData, err := AesDecrypt(result, key)
if err != nil {
panic(err)
}
fmt.Println(string(origData))
}