数据加解密

> 加密采用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); ```