数据加解密
> 加密采用AES-256-CBC对称加密算法实现,将加密后的字节通过base64转为字符串
>
> 密钥由乐陪方提供,在对接时分配测试密钥,上线时分配正式密钥。初始化向量IV,使用密钥的**++**前16位**++**。
>
> 密钥分配后不允许调整,如被遗忘,需联系乐陪方重新提供。
## 示例
```java
String context = "O1b2qJxHbOTXModS23iTxTJm4TV+WPVjdHH2brUVxTukikfXlQFGrfPKj4JG4YlKbGg8gqyEcYfGesNDUvkojf4acagZuxx5pXBiPv88ZsERazCTi759v6O6ml/IJlRA0Y5OD0Ri6+n2f0xdvDh9bT9sre5wA/drOBHraqe1IIy9oFzN/WhSaRSx6dQDKWUxNx5nyVWr1muA09C6Xel2zqng4Bf1NpCWxtCmNTgzzlVUsG8o5IP3AJ3gVGjTEOl18UOv/zKkfcq87QWeJ4ahvV3F6Ih7bVw7EEFprQ5J3cY="
String secretKey = "JU57Vi4xUNNPqGsz44HNq9gSJX9JQYf7"
String iv = "JU57Vi4xUNNPqGsz"
```
### Java版
```java
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class AES {
// 加密算法
private static final String ALG = "AES";
// 字符编码
private static final String ENC = "UTF-8";
/**
* 算法/模式/填充
**/
private static final String CIPHER_CBC_ALGORITHM = "AES/CBC/PKCS5Padding";
/**
* AES加密CBC模式PKCS5Padding填充方式
*
* @param str 字符串
* @param key 密钥
* @param iv 偏移量
* @return 加密字符串
* @throws Exception 异常信息
*/
public static String aes256CBCPkcs5Encrypt(String str, String key, String iv) throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_CBC_ALGORITHM);
byte[] keyBytes = key.getBytes(ENC);
byte[] initParam = iv.getBytes(ENC);
IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, ALG), ivParameterSpec);
byte[] doFinal = cipher.doFinal(str.getBytes(ENC));
return new String(Base64.getEncoder().encode(doFinal));
}
/**
* AES解密CBC模式PKCS5Padding填充方式
*
* @param str 字符串
* @param key 密钥
* @param iv 偏移量
* @return 解密字符串
* @throws Exception 异常信息
*/
public static String aes256CBCPkcs5Decrypt(String str, String key, String iv) throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_CBC_ALGORITHM);
byte[] keyBytes = key.getBytes(ENC);
byte[] initParam = iv.getBytes(ENC);
IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, ALG), ivParameterSpec);
byte[] doFinal = cipher.doFinal(Base64.getDecoder().decode(str));
return new String(doFinal);
}
}
```
### Go版
```go
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"errors"
"fmt"
)
func main() {
var (
content = ""
secretKey = ""
iv = ""
)
// 解密
decodeString, _ := base64.StdEncoding.DecodeString(content)
if decryptCBC, err := DecryptCBC([]byte(decodeString), []byte(secretKey), []byte(iv)); err != nil {
panic(err)
} else {
fmt.Println(string(decryptCBC))
}
// 加密
encryptCBC, _ :=EncryptCBC([]byte(decodeString), []byte(secretKey), []byte(iv));
encodeToString := base64.StdEncoding.EncodeToString(encryptCBC)
}
func DecryptCBC(cipherText []byte, key []byte, iv ...[]byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
if len(cipherText) < blockSize {
return nil, errors.New("cipherText too short")
}
ivValue := iv[0]
if len(cipherText)%blockSize != 0 {
return nil, errors.New("cipherText is not a multiple of the block size")
}
blockModel := cipher.NewCBCDecrypter(block, ivValue)
plainText := make([]byte, len(cipherText))
blockModel.CryptBlocks(plainText, cipherText)
plainText, e := PKCS5UnPadding(plainText, blockSize)
if e != nil {
return nil, e
}
return plainText, nil
}
func PKCS5UnPadding(src []byte, blockSize int) ([]byte, error) {
length := len(src)
if blockSize <= 0 {
return nil, errors.New("invalid blocklen")
}
if length%blockSize != 0 || length == 0 {
return nil, errors.New("invalid data len")
}
unpadding := int(src[length-1])
if unpadding > blockSize || unpadding == 0 {
return nil, errors.New("invalid padding")
}
padding := src[length-unpadding:]
for i := 0; i < unpadding; i++ {
if padding[i] != byte(unpadding) {
return nil, errors.New("invalid padding")
}
}
return src[:(length - unpadding)], nil
}
func PKCS5Padding(src []byte, blockSize int) []byte {
padding := blockSize - len(src)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(src, padtext...)
}
func EncryptCBC(plainText []byte, key []byte, iv ...[]byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
plainText = PKCS5Padding(plainText, blockSize)
//ivValue := ([]byte)(nil)
ivValue := iv[0]
blockMode := cipher.NewCBCEncrypter(block, ivValue)
cipherText := make([]byte, len(plainText))
blockMode.CryptBlocks(cipherText, plainText)
return cipherText, nil
}
```
### PHP版
```php
$context = "";
$secretKey = "";
$iv = "";
$_str = base64_decode($context);
// 加密
$openssl_encrypt = openssl_encrypt($decrypted, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
// 解密
$decrypted = openssl_decrypt($context, 'AES-256-CBC', $secretKey, OPENSSL_RAW_DATA, $iv);
```