AES 加解密(前后端)
加密
前端加密:
aesEncrypt(plainText: string, key: string) {
const key = CryptoJS.enc.Latin1.parse(key);
const iv = CryptoJS.enc.Latin1.parse('1234567890123456');
const encrypted = CryptoJS.AES.encrypt(plainText, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding // CryptoJS.pad.ZeroPadding, CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}
调用时的打印结果:
// padding = CryptoJS.pad.ZeroPadding
aesEncrypt("123456", "ABCDEFGHIJKLMNOP"); // 83MCLn7rL5/P2eXEyBzPDQ==
aesEncrypt("123456", "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"); // ebUKt3ZWeU78On/hns7W1w==
// padding = CryptoJS.pad.Pkcs7
aesEncrypt("123456", "ABCDEFGHIJKLMNOP"); // d1R21TsRewTG3mRIeYnIWw==
aesEncrypt("123456", "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"); // uCvloRIqYLLJauF5EpIuGA==
//
aesEncrypt("123456"); // padding = CryptoJS.pad.NoPadding -> 83MCLn7r
后端PHP加密,OPENSSL_ZERO_PADDING 方式(0补位,不推荐这种方式,所以补位的逻辑需要自行实现):
$key = 'ABCDEFGHIJKLMNOP';
$iv = '1234567890123456';
$blockSize = 16;
$planText = "123456";
if (strlen($planText) % $blockSize) {
$planText = str_pad($planText, strlen($planText) + $blockSize - strlen($planText) % $blockSize, "\0");
}
// key 是 16 位,对应 AES-128-CBC
$encrypted = openssl_encrypt($planText, "AES-128-CBC", $key, OPENSSL_ZERO_PADDING, $iv); // 83MCLn7rL5/P2eXEyBzPDQ==
// key 是 32 位,对应 AES-256-CBC
$key = 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP';
$encrypted = openssl_encrypt($planText, "AES-256-CBC", $key, OPENSSL_ZERO_PADDING, $iv); // ebUKt3ZWeU78On/hns7W1w==
// 如果 key 是 24 位的,对应的是 AES-192-CBC
后端PHP加密,OPENSSL_RAW_DATA 方式(PKCS7补位):
// https://www.php.net/manual/zh/openssl.constants.other.php#constant.openssl-raw-data
// openssl_encrypt 中如果设置了 OPENSSL_RAW_DATA 将原样返回,没有设置时返回的是 base64
$encrypted = openssl_encrypt($planText, "AES-128-CBC", $key, OPENSSL_RAW_DATA, $iv);
// 需要 base64_encode 一下
$encrypted = base64_encode($encrypted); // d1R21TsRewTG3mRIeYnIWw==
$key = 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP';
$encrypted = openssl_encrypt($planText, "AES-256-CBC", $key, OPENSSL_RAW_DATA, $iv);
$encrypted = base64_encode($encrypted); // uCvloRIqYLLJauF5EpIuGA==
后端 go 加密,PKCS7:
// AesEncrypt 加密
func AesEncrypt(plainText string, key string, iv string) (string, error) {
// 创建加密实例
keyBytes := []byte(key)
block, err := aes.NewCipher(keyBytes)
if err != nil {
return "", err
}
data := []byte(plainText)
ivBytes := []byte(iv) // 不使用手动指定的 iv 时,可以使用 key 的前 blockSize 位
// 加密快的大小
blockSize := block.BlockSize()
// 填充
encryptBytes := pkcs7Padding(data, blockSize)
// 初始化加密数据接收切片
crypted := make([]byte, len(encryptBytes))
// CBC 加密模式
blockMode := cipher.NewCBCEncrypter(block, ivBytes)
// 加密
blockMode.CryptBlocks(crypted, encryptBytes)
// 转为 base64 格式
return base64.StdEncoding.EncodeToString(crypted), nil
}
// pkcs7Padding 填充
func pkcs7Padding(data []byte, blockSize int) []byte {
// 补位长度,最少1,最多 blockSize
padding := blockSize - len(data)%blockSize
// 补位 padding 个 padding
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(data, padText...)
}
func main() {
key := "ABCDEFGHIJKLMNOP"
iv := "1234567890123456"
crypted, _ := AesEncrypt("123456", key, iv)
fmt.Println("crypted =", crypted) // crypted = d1R21TsRewTG3mRIeYnIWw==
key = "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
crypted, _ = aes.AesEncrypt("123456", key, iv)
fmt.Println("key = ", key, ", crypted =", crypted) // crypted = uCvloRIqYLLJauF5EpIuGA==
}
零补位时,padText := bytes.Repeat([]byte{byte(padding)}, padding)
-> padText := bytes.Repeat([]byte{0}, padding)
:
// 方法名 zeroPadding
func zeroPadding(data []byte, blockSize int) []byte {
// 补位长度,最少1,最多 blockSize
padding := blockSize - len(data)%blockSize
// 补位 padding 个 padding
padText := bytes.Repeat([]byte{0}, padding)
return append(data, padText...)
}
func main() {
key := "ABCDEFGHIJKLMNOP"
iv := "1234567890123456"
crypted, _ := AesEncrypt("123456", key, iv)
fmt.Println("crypted =", crypted) // crypted = 83MCLn7rL5/P2eXEyBzPDQ==
key = "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
crypted, _ = aes.AesEncrypt("123456", key, iv)
fmt.Println("key = ", key, ", crypted =", crypted) // crypted = ebUKt3ZWeU78On/hns7W1w==
}
解密
前端解密:
aesDecrypt(encrypted: string, key: string) {
const SECRET_KEY = CryptoJS.enc.Latin1.parse(key);
const SECRET_IV = CryptoJS.enc.Latin1.parse('1234567890123456');
const decrypted = CryptoJS.AES.decrypt(encrypted, SECRET_KEY, {
iv: SECRET_IV,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding // CryptoJS.pad.ZeroPadding, CryptoJS.pad.Pkcs7
});
return decrypted.toString(CryptoJS.enc.Utf8);
}
打印结果:
// padding = CryptoJS.pad.ZeroPadding
aesDecrypt("83MCLn7rL5/P2eXEyBzPDQ==", "ABCDEFGHIJKLMNOP")); // 123456
aesDecrypt("ebUKt3ZWeU78On/hns7W1w==", "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"); // 123456
// padding = CryptoJS.pad.Pkcs7
aesDecrypt("d1R21TsRewTG3mRIeYnIWw==", "ABCDEFGHIJKLMNOP"))
aesDecrypt("uCvloRIqYLLJauF5EpIuGA==", "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
后端PHP解密,OPENSSL_ZERO_PADDING 方式:
$key = 'ABCDEFGHIJKLMNOP';
$iv = '1234567890123456';
$encrypted = '83MCLn7rL5/P2eXEyBzPDQ==';
$decrypted = openssl_decrypt($encrypted, 'AES-128-CBC', $key, OPENSSL_ZERO_PADDING, $iv); // 123456\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
// 去除补位的 0
$decrypted = rtrim($decrypted, chr(0)); // 123456
$key = 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP';
$encrypted = 'ebUKt3ZWeU78On/hns7W1w==';
$decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', $key, OPENSSL_ZERO_PADDING, $iv); // 123456\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
$decrypted = rtrim($decrypted, chr(0)); // 123456
后端PHP解密,OPENSSL_RAW_DATA 方式:
$iv = '1234567890123456';
$key = 'ABCDEFGHIJKLMNOP';
$encrypted = 'd1R21TsRewTG3mRIeYnIWw==';
$decrypted = openssl_decrypt(base64_decode($encrypted), 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv); // 123456
$key = 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP';
$encrypted = 'uCvloRIqYLLJauF5EpIuGA==';
$decrypted = openssl_decrypt(base64_decode($encrypted), 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv); // 123456
后端 go 解密,PKCS7:
// AesDecrypt 解密
func AesDecrypt(cryptedText string, key string, iv string) (string, error) {
data, err := base64.StdEncoding.DecodeString(cryptedText)
if err != nil {
return "", err
}
keyBytes := []byte(key)
// 创建实例
block, err := aes.NewCipher(keyBytes)
if err != nil {
return "", err
}
ivBytes := []byte(iv)
blockMode := cipher.NewCBCDecrypter(block, ivBytes)
// 初始化解密数据接收切片
crypted := make([]byte, len(data))
// 解密
blockMode.CryptBlocks(crypted, data)
// 去除填充
crypted, err = pkcs7UnPadding(crypted)
if err != nil {
return "", err
}
return string(crypted), nil
}
// pkcs7UnPadding
func pkcs7UnPadding(data []byte) ([]byte, error) {
length := len(data)
if length == 0 {
return nil, errors.New("加密字符串错误!")
}
// 补位个数
unPadding := int(data[length-1])
return data[:(length - unPadding)], nil
}
func main() {
key := "ABCDEFGHIJKLMNOP"
iv := "1234567890123456"
decrypted, _ := AesDecrypt("d1R21TsRewTG3mRIeYnIWw==", key, iv)
fmt.Println("decrypted =", decrypted) // decrypted = 123456
key = "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
decrypted, _ = AesDecrypt("uCvloRIqYLLJauF5EpIuGA==", key, iv)
fmt.Println("decrypted =", decrypted) // decrypted = 123456
}
零补位时,补位的长度需要计算
// ZeroUnpadding
func ZeroUnPadding(data []byte) ([]byte, error) {
length := len(data)
if length == 0 {
return nil, errors.New("加密字符串错误!")
}
unPadding := 0
for i := length - 1; i >= 0; i-- {
if data[i] == 0 {
unPadding++
} else {
break
}
}
if unPadding == 0 {
return nil, errors.New("加密字符串错误,没有补位长度!")
}
return data[:length-unPadding], nil
}
func main() {
key := "ABCDEFGHIJKLMNOP"
iv := "1234567890123456"
decrypted, _ := AesDecrypt("83MCLn7rL5/P2eXEyBzPDQ==", key, iv)
fmt.Println("decrypted =", decrypted) // decrypted = 123456
key = "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
decrypted, _ = AesDecrypt("ebUKt3ZWeU78On/hns7W1w==", key, iv)
fmt.Println("decrypted =", decrypted) // decrypted = 123456
}
标签:crypted,decrypted,AES,前后,加解密,iv,key,byte,123456
From: https://www.cnblogs.com/zhpj/p/18076219/aes-decryption-front-and-back-1efs19