Created
December 18, 2021 06:10
-
-
Save idoop/eef1884cc04f1ff763822a3d9579dc54 to your computer and use it in GitHub Desktop.
golang use AES Encrypt & Decrypt include CBC/ECB/CFB mode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"crypto/aes" | |
"crypto/cipher" | |
"crypto/rand" | |
"encoding/base64" | |
"encoding/hex" | |
"io" | |
"io/ioutil" | |
"log" | |
) | |
func main() { | |
origData := []byte("jiamisuanface12345sdfasdfasdf1a1") // data to be encrypted | |
ioutil.WriteFile("aa", origData, 0600) | |
key := []byte{0xa0, 0xb0, 0x01, 0x02, 0xcc, 0xa1, 0x12, 0x31, 0x9a, 0x07, 0x1d, 0x48, 0x1c, 0xf4, 0x7d, 0x5c} // encrypted key | |
log.Println("Original:", string(origData)) | |
log.Println("------------------ CBC mode --------------------") | |
encrypted := AesEncryptCBC(origData, key) | |
log.Println("Ciphertext(hex):", hex.EncodeToString(encrypted)) | |
log.Println("Ciphertext(base64):", base64.StdEncoding.EncodeToString(encrypted)) | |
decrypted := AesDecryptCBC(encrypted, key) | |
log.Println("Decryption result:", string(decrypted)) | |
log.Println("------------------ ECB mode --------------------") | |
encrypted = AesEncryptECB(origData, key) | |
log.Println("Ciphertext(hex):", encrypted) | |
log.Println("Ciphertext(base64):", base64.StdEncoding.EncodeToString(encrypted)) | |
decrypted = AesDecryptECB(encrypted, key) | |
log.Println("Decryption result:", string(decrypted)) | |
log.Println("------------------ CFB mode --------------------") | |
encrypted = AesEncryptCFB(origData, key) | |
log.Println("Ciphertext(hex):", hex.EncodeToString(encrypted)) | |
log.Println("Ciphertext(base64):", base64.StdEncoding.EncodeToString(encrypted)) | |
decrypted = AesDecryptCFB(encrypted, key) | |
log.Println("Decryption result:", string(decrypted)) | |
} | |
// =================== CBC ====================== | |
func AesEncryptCBC(origData []byte, key []byte) (encrypted []byte) { | |
// // group key | |
// NewCipher This function limits the length of input k to 16, 24 or 32 | |
block, _ := aes.NewCipher(key) | |
blockSize := block.BlockSize() // Get the length of the key block | |
origData = pkcs5Padding(origData, blockSize) // Completion code | |
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) // encryption mode | |
encrypted = make([]byte, len(origData)) // create an array | |
blockMode.CryptBlocks(encrypted, origData) // Encrypted | |
return encrypted | |
} | |
func AesDecryptCBC(encrypted []byte, key []byte) (decrypted []byte) { | |
block, _ := aes.NewCipher(key) // grouping key | |
blockSize := block.BlockSize() // Get the length of the key block | |
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) // encryption mode | |
decrypted = make([]byte, len(encrypted)) // create an array | |
blockMode.CryptBlocks(decrypted, encrypted) | |
decrypted = pkcs5UnPadding(decrypted) | |
return decrypted | |
} | |
func pkcs5Padding(ciphertext []byte, blockSize int) []byte { | |
padding := blockSize - len(ciphertext)%blockSize | |
padtext := bytes.Repeat([]byte{byte(padding)}, padding) | |
return append(ciphertext, padtext...) | |
} | |
func pkcs5UnPadding(origData []byte) []byte { | |
length := len(origData) | |
unpadding := int(origData[length-1]) | |
return origData[:(length - unpadding)] | |
} | |
// =================== ECB ====================== | |
func AesEncryptECB(origData []byte, key []byte) (encrypted []byte) { | |
cipher, _ := aes.NewCipher(generateKey(key)) | |
length := (len(origData) + aes.BlockSize) / aes.BlockSize | |
plain := make([]byte, length*aes.BlockSize) | |
copy(plain, origData) | |
pad := byte(len(plain) - len(origData)) | |
for i := len(origData); i < len(plain); i++ { | |
plain[i] = pad | |
} | |
encrypted = make([]byte, len(plain)) | |
// Block encryption | |
for bs, be := 0, cipher.BlockSize(); bs <= len(origData); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() { | |
cipher.Encrypt(encrypted[bs:be], plain[bs:be]) | |
} | |
return encrypted | |
} | |
func AesDecryptECB(encrypted []byte, key []byte) (decrypted []byte) { | |
cipher, _ := aes.NewCipher(generateKey(key)) | |
decrypted = make([]byte, len(encrypted)) | |
// | |
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() { | |
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be]) | |
} | |
trim := 0 | |
if len(decrypted) > 0 { | |
trim = len(decrypted) - int(decrypted[len(decrypted)-1]) | |
} | |
return decrypted[:trim] | |
} | |
func generateKey(key []byte) (genKey []byte) { | |
genKey = make([]byte, 16) | |
copy(genKey, key) | |
for i := 16; i < len(key); { | |
for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 { | |
genKey[j] ^= key[i] | |
} | |
} | |
return genKey | |
} | |
// =================== CFB ====================== | |
func AesEncryptCFB(origData []byte, key []byte) (encrypted []byte) { | |
block, err := aes.NewCipher(key) | |
if err != nil { | |
panic(err) | |
} | |
encrypted = make([]byte, aes.BlockSize+len(origData)) | |
iv := encrypted[:aes.BlockSize] | |
if _, err := io.ReadFull(rand.Reader, iv); err != nil { | |
panic(err) | |
} | |
stream := cipher.NewCFBEncrypter(block, iv) | |
stream.XORKeyStream(encrypted[aes.BlockSize:], origData) | |
return encrypted | |
} | |
func AesDecryptCFB(encrypted []byte, key []byte) (decrypted []byte) { | |
block, _ := aes.NewCipher(key) | |
if len(encrypted) < aes.BlockSize { | |
panic("ciphertext too short") | |
} | |
iv := encrypted[:aes.BlockSize] | |
encrypted = encrypted[aes.BlockSize:] | |
stream := cipher.NewCFBDecrypter(block, iv) | |
stream.XORKeyStream(encrypted, encrypted) | |
return encrypted | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment