Java与C/C++通用的“AES/ECB/PKCS5Padding”实现

在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


你可能感兴趣的:(Android,Java,C++)