内容简介:在项目开发中遇到AES加密解密的问题,因为一个参数问题卡了比较久,做个记录。并给出AES加密解密分别用Java、Python和C++的实现代码。AES加密算法即密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。AES加密算法涉及4种操作:字节替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(
在项目开发中遇到AES加密解密的问题,因为一个参数问题卡了比较久,做个记录。并给出AES加密解密分别用 Java 、 Python 和C++的实现代码。
一、AES简介
AES加密算法即密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。
AES加密算法涉及4种操作:字节替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(AddRoundKey)。数据块分组长度必须为128比特,密钥长度可以是128比特、192比特、256比特中的任意一个(如果数据块及密钥长度不足时,会补齐)。
解密算法的每一步分别对应加密算法的逆操作,加解密所有操作的顺序正好是相反的。
二、AES加密解密-Java实现
/**
* PAD模式
* NoPadding
* PKCS7Padding
* PKCS5Padding
* PKCS1Padding
*/
private final String AES_PATTERN = "AES/CBC/NoPadding";
/**
* AES加密KEY参数值,16个字符
*/
private final String AES_KEY = "aaaaaaaaaaaaaaaa";
/**
* AES加密向量参数值,16个字符
*/
private final String AES_IV = "bbbbbbbbbbbbbbbb";
/**
* 字符编码
*/
private final String CHARSET_ISO ="ISO8859-1";
/**
* 解密
*
* @param content 要解密的文本内容,也可以直接替换成byte[]数组
* @param pattern 模式参数
* @param key 解密KEY值
* @param iv 解密向量值
* @param charSet 字符编码
* @return
*/
public String decrypt(String content, String pattern, String key,
String iv, String charSet) {
try {
Cipher cipher = Cipher.getInstance(pattern);
Key sKeySpec = new SecretKeySpec(key.getBytes(charSet), "AES");
cipher.init(Cipher.DECRYPT_MODE, sKeySpec,
generateIV(iv.getBytes(charSet)));
byte[] result = cipher.doFinal(content.getBytes(charSet));
return new String(result, charSet);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 加密
*
* @param content 要加密的文本内容,也可以直接替换成byte[]数组
* @param pattern 模式参数
* @param key 解密KEY值
* @param iv 解密向量值
* @param charSet 字符编码
* @return
*/
public String encrypt(String content, String pattern, String key,
String iv, String charSet) {
try {
Cipher cipher = Cipher.getInstance(pattern);
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(charSet), "AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec,
new IvParameterSpec(iv.getBytes(charSet)));
byte[] encrypted = cipher.doFinal(content.getBytes(charSet));
return new String(encrypted, charSet);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 初始化向量参数
*
* @param iv
* @return
* @throws Exception
*/
public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(iv));
return params;
}
1)关于为何用”ISO8859-1″的编码方式,见 Android AES加密报错处理 :
javax.crypto.IllegalBlockSizeException: error:1e00007b: Cipher functions:OPENSSL_internal:WRONG_FINAL_BLOCK_LENGTH
2)Padding参数要特别注意下
如果项目中配置文件用Python脚本加密了,解密要使用Java代码来实现,需要注意下Python脚本使用的Padding模式,就是因为在Python脚本的实现中,没有设置Padding参数,Java代码中设置了PKCS5Padding,使得解密一直出异常。如果是输出下面的异常,查下Padding参数是否设置正确。
java.lang.RuntimeException: javax.crypto.BadPaddingException: error:1e000065: Cipher functions:OPENSSL_internal:BAD_DECRYPT java.lang.RuntimeException: javax.crypto.BadPaddingException: error:1e000065: Cipher functions:OPENSSL_internal:BAD_DECRYPT at java.lang.Thread.run(Thread.java:776) Caused by: javax.crypto.BadPaddingException: error:1e000065: Cipher functions:OPENSSL_internal:BAD_DECRYPT at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method) at com.android.org.conscrypt.OpenSSLCipher$EVP_CIPHER.doFinalInternal(OpenSSLCipher.java:568) at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:350) at javax.crypto.Cipher.doFinal(Cipher.java:2056) ... 4 more
三、AES加密解密-Python实现
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from binascii import b2a_hex, a2b_hex
from Crypto.Cipher import AES
import struct
import os
MODE = AES.MODE_CBC
KEY = ‘aaaaaaaaaaaaaaaa’
IV = ‘bbbbbbbbbbbbbbbb’
def aes_encrypt(content):
cryptor = AES.new(KEY, MODE, IV)
# 密钥key,长度:16(AES-128)、24(AES-192)、32(AES-256)
length = 16
count = len(content)
if count < length:
add = (length – count)
content = content + (‘\0’ * add)
elif count > length:
add = (length – (count % length))
content = content + (‘\0’ * add)
encrypted = cryptor.encrypt(content)
return encrypted
def aes_decrypt(content):
cryptor = AES.new(KEY, MODE, IV)
decrypt = cryptor.decrypt(content)
return decrypt
def encrypt_file(input, output):
if not os.path.exists(input):
print(‘encrypt_file: input file %s not exits.’ % input)
return
print(“encrypt_file file %s to %s” % (input, output))
with open(input, ‘r’) as origin:
data = origin.read()
encrypt_content = aes_encrypt(data)
with open(output, ‘w’) as encrypt:
encrypt.write(encrypt_content)
def decrypt_file(input, output):
if not os.path.exists(input):
print(‘decrypt_file: input file %s not exits.’ % input)
return
print(“decrypt_file file %s to %s” % (input, output))
with open(input, ‘r’) as origin:
data = origin.read()
decrypt_content = aes_decrypt(data)
with open(output, ‘w’) as decrypt:
decrypt.write(decrypt_content)
四、AES加密解密-C++实现
/**
* 加密
*/
gbool ConfigEncrypt(char *pData, int nLen, char **ppOutData, int *pnOutLen,
char *KEY, char *VEC) {
if (pData == NULL) {
return gfalse;
}
char ivec[16] ={0} ;
AES_KEY aes_ks1;
int nRet = 0;
char *pInData = NULL;
int nBlock = 0;
char *pOutData = NULL;
int nOutLen = 0;
if (pData <= 0) {
return (gfalse);
}
int nTmpLen = 16 - nLen % 16;
pInData = (char*)malloc(nLen + 64);
memset(pInData, 0, nLen + 64);
memcpy(pInData, pData, nLen);
pOutData = (char*)malloc(nLen + 64);
memset(pOutData, 0, nLen + 64);
memcpy(ivec, VEC, 16u);
nLen += nTmpLen;
nRet = AES_set_encrypt_key((const unsigned char *)KEY, 128, &aes_ks1);
AES_cbc_encrypt((const unsigned char *)pInData, (unsigned char *)pOutData,
nLen + 16, &aes_ks1, (unsigned char *)ivec, AES_ENCRYPT);
free(pInData);
nOutLen = nLen + 16;
*ppOutData = pOutData;
*pnOutLen = nOutLen;
return (gtrue);
}
/**
* 解密
*/
gbool ConfigDecrypt(char *pData, int nLen, char **ppOutData, int *pnOutLen,
char *KEY, char *VEC) {
if (pData == NULL || nLen == 0) {
return gfalse;
}
gbool bRet = gfalse;
char ivec[16] ={0} ;
AES_KEY aes_ks1 = {0};
int nRet = 0;
char *pTemp = NULL;
if (pData <= 0) {
return gfalse;
}
memcpy(ivec, VEC, sizeof(ivec));
nRet = AES_set_decrypt_key((const unsigned char *)KEY, 128, &aes_ks1);
pData = pData + 16;
char *pDstData = (char*)calloc(nLen + 16, 1);
if (pDstData) {
AES_cbc_encrypt((const unsigned char *)pData, (unsigned char *)pDstData,
nLen - 16, &aes_ks1, (unsigned char *)ivec, AES_DECRYPT);
memcpy(pnOutLen, pDstData, 4);
char *pOutData = (char *)calloc((*pnOutLen) + 1, 1);
if (pOutData && *pnOutLen > 0)
{
memcpy(pOutData, pDstData + 4, *pnOutLen);
*ppOutData = pOutData;
bRet = gtrue;
}
free(pDstData);
pDstData = NULL;
}
return bRet;
}
五、参考资料
以上所述就是小编给大家介绍的《AES加密解密》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。