在Java中调用AES的加解密方法很简单,因为系统提供了很好的函数支持;但在C/C++中需要用户自己实现,因此需要学习AES加密的不同实现方式,以便正确的实现。
Java中的代码实现:
public class Aes {
public static String encrypt(String content, String password) throws Exception {
return parseByte2HexStr(encrypt(content.getBytes(),
parseHexStr2Byte(password)));
}
// 解密
public static String decrypt(String content, String password) throws Exception {
return decrypt(parseHexStr2Byte(content), parseHexStr2Byte(password));
}
private static byte[] encrypt(byte[] content, byte[] password) {
try {
byte[] enCodeFormat = new byte[16];
for (int i = 0; i < 16; i++) {
if (i < password.length)
enCodeFormat[i] = password[i];
else
enCodeFormat[i] = 0;
}
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 创建密码器
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(content);
return result; // 加密
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String decrypt(byte[] content, byte[] password) {
try {
byte[] enCodeFormat = new byte[16];
for (int i = 0; i < 16; i++) {
if (i < password.length)
enCodeFormat[i] = password[i];
else
enCodeFormat[i] = 0;
}
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 创建密码器
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(content);
return (new String(result)).replace("\0", ""); // 加密
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将二进制转换成16进制
*
* @param buf
* @return
*/
private static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/**
* 将16进制转换为二进制
*
* @param hexStr
* @return
*/
private static byte[] parseHexStr2Byte(String hexStr)
throws DataFormatException {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
}
在Android开发过程中,为了增加安全性,往往将加解密过程放在JNI中实现,基于C/C++的代码实现(下载地址),JNI中调用如下:
extern "C"
{
#define AES_KEY "85FD4614740ECDF6F9A6B0B066156232"
void Hex2Bin(char* in, char* out){
int len = strlen(in);
for (size_t i = 0; i < len; i++)
{
uint8_t cTemp = 0;
for (size_t j = 0; j < 2; j++)
{
char cCur = in[2 * i + j];
if (cCur >= '0' && cCur <= '9')
{
cTemp = (cTemp << 4) + (cCur - '0');
}
else if (cCur >= 'a' && cCur <= 'f')
{
cTemp = (cTemp << 4) + (cCur - 'a' + 10);
}
else if (cCur >= 'A' && cCur <= 'F')
{
cTemp = (cTemp << 4) + (cCur - 'A' + 10);
}
else
{
return ;
}
}
out[i] = cTemp;
}
}
JNIEXPORT jstring JNICALL
Java_com_test_ctr_CtrNdk_encrypt(JNIEnv *env, jclass type, jstring inData_) {
const char *inData = env->GetStringUTFChars(inData_, 0);
if(!inData){
return env->NewStringUTF("");
}
char* aesKeyBin = "";
if(strlen(AES_KEY)%2 == 0){
aesKeyBin = new char[strlen(AES_KEY)/2];
Hex2Bin(AES_KEY, aesKeyBin);
}
aes_text aess;
aess.content = (char *)inData;
aess.len = strlen(inData);
aes_text out;
aes_encrypt_Hex(aesKeyBin,&aess,&out);
env->ReleaseStringUTFChars(inData_, inData);
delete[] aesKeyBin;
return env->NewStringUTF(out.content);
}
JNIEXPORT jstring JNICALL
Java_com_test_ctr_CtrNdk_decrypt(JNIEnv *env, jclass cls, jstring inData_) {
const char *inData = env->GetStringUTFChars(inData_, 0);
if(!inData){
return env->NewStringUTF("");
}
char* aesKeyBin = "";
if(strlen(AES_KEY)%2 == 0){
aesKeyBin = new char[strlen(AES_KEY)/2];
Hex2Bin(AES_KEY, aesKeyBin);
}
aes_text in;
in.content = (char *) inData;
in.len = strlen(in.content);
aes_text out;
aes_decrypt_Hex(aesKeyBin,&in,&out);
env->ReleaseStringUTFChars(inData_, inData);
delete[] aesKeyBin;
return env->NewStringUTF(out.content);
}
}
参考文档:
1、http://blog.sina.com.cn/s/blog_60cf051301015orf.html
2、http://blog.csdn.net/chuachua66/article/details/50583352
3、http://blog.csdn.net/lisonglisonglisong/article/details/41909813