Symmetric encryption algorithms, that is, encryption and decryption using the same cryptographic key encryption and decryption algorithm.
Block cipher is a class of encryption and decryption algorithms that can handle only a block of data of a specific length at a time.
At present, the symmetric encryption Algorithm DES, 3DES, AES belong to the block cipher.
Background
Golang does not provide a ready-made AES encryption function like PHP, but there are crypto in the standard library, using AES inside to encapsulate an encryption function, but understand the whole process and principle of decryption
AES Encryption detailed
1. Refer to AES encryption in article Golang
2. Here is the CBC mode in AES encryption, block encryption needs to be divided into integers equal to the length of the message block is continuously encrypted (serial), the packet length is fixed 128 bits, but the length of the key can use 128 bits, 192 bits or 256 bits (this refers to a bit), that is, the key 16, 24,32 length corresponds to AES-128, AES-192, AES-256.
3. The initial vector requires random, but does not require secrecy.
Code
Their own research code is clear, according to Golang Standard library AES Instance code, and then refer to the online PKCS7 fill, and finally base64 encoding (because some characters are not visible after encryption). Finally encrypt and Dncrypt two is AES plus decryption (CBC mode, PKCS7 fill) After the encapsulated function, the number of key Bits limited 16,24,32 (note that the key no matter how much, blocksize are fixed 16)
Package encrypt
Import (
"bytes"
"crypto/aes"
"io"
"crypto/rand"
"crypto/cipher"
"encoding/base64"
)
/*CBC encryption Follow the example code of the golang standard library
But there is no padding inside, so make up
*/
/ / Use PKCS7 to fill, IOS is also 7
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)]
}
//aes encryption, filling the 16 bits of the key key, 24, 32 respectively corresponding to AES-128, AES-192, or AES-256.
Func AesCBCEncrypt(rawData,key []byte) ([]byte, error) {
Block, err := aes.NewCipher(key)
If err != nil {
Panic(err)
}
//fill the original
blockSize := block.BlockSize()
rawData = PKCS7Padding(rawData, blockSize)
/ / Initial vector IV must be unique, but does not need to be kept secret
cipherText := make([]byte,blockSize+len(rawData))
//block size 16
Iv := cipherText[:blockSize]
If _, err := io.ReadFull(rand.Reader,iv); err != nil {
Panic(err)
}
//block size and initial vector size must be the same
Mode := cipher.NewCBCEncrypter(block,iv)
mode.CryptBlocks(cipherText[blockSize:], rawData)
Return cipherText, nil
}
Func AesCBCDncrypt(encryptData, key []byte) ([]byte,error) {
Block, err := aes.NewCipher(key)
If err != nil {
Panic(err)
}
blockSize := block.BlockSize()
If len(encryptData) < blockSize {
Panic("ciphertext too short")
}
Iv := encryptData[:blockSize]
encryptData = encryptData[blockSize:]
// CBC mode always works in whole blocks.
If len(encryptData)%blockSize != 0 {
Panic("ciphertext is not a multiple of the block size")
}
Mode := cipher.NewCBCDecrypter(block, iv)
// CryptBlocks can work in-place if the two arguments are the same.
mode.CryptBlocks(encryptData, encryptData)
/ / Unfill
encryptData = PKCS7UnPadding(encryptData)
Return encryptData,nil
}
Func Encrypt(rawData,key []byte) (string,error) {
Data, err:= AesCBCEncrypt(rawData,key)
If err != nil {
Return "", err
}
Return base64.StdEncoding.EncodeToString(data),nil
}
Func Dncrypt(rawData string,key []byte) (string,error) {
Data,err := base64.StdEncoding.DecodeString(rawData)
If err != nil {
Return "", err
}
dnData,err := AesCBCDncrypt(data,key)
If err != nil {
Return "", err
}
Return string(dnData),nil
}
Reference:
- AES Encryption in Golang