android中使用jni對字串加解密實現分析
android中使用jni對字串加解密實現分析
最近項目有個需求,就是要對使用者的敏感資訊進行加密處理,比如使用者的賬戶密碼,手機號等私密資訊。在java中,就對字串的加解密我們可以使用AES演算法加密字串,使用它的好處就不必多說了,但我們又知道android的原始碼是可以被反編譯的,所以使用純Java方式的AES加密是不安全的,所以想到了使用android中的jni來對字串加解密處理,它會產生一個.so檔案,更重要的是它通過C/C++代碼實現,所以安全行比較高,它可以被反編譯成機器碼,但幾乎不能被還原反編譯,那麼下面就詳細介紹下這種的加密處理。
鑒於完全使用C/C++代碼進行字串的加解密,我們需要考慮不同系統平台上資料類型的差異問題,這裡推薦另一種易於實現的方法,即使用Java中的AES加解密邏輯,而將AES加解密所需要的核心秘鑰放入到C中,通過調用jni來從靜態類庫中讀取需要的秘鑰,具體實現如下:
項目代碼結構圖:
Java中的AES演算法邏輯:
publicclass SecurityUtil {
privatestaticbyte[]keyValue;
privatestaticbyte[]iv;
privatestatic SecretKeykey;
privatestatic AlgorithmParameterSpecparamSpec;
privatestatic Cipherecipher;
static {
System.loadLibrary("cwtlib");
keyValue = getKeyValue();
iv = getIv();
if(null != keyValue &&
null !=iv) {
KeyGeneratorkgen;
try {
kgen = KeyGenerator.getInstance("AES");
kgen.init(128,new SecureRandom(keyValue));
key =kgen.generateKey();
paramSpec =new IvParameterSpec(iv);
ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (NoSuchAlgorithmExceptione) {
} catch (NoSuchPaddingExceptione) {
}
}
}
publicstaticnativebyte[] getKeyValue();
publicstaticnativebyte[] getIv();
publicstatic String encode(Stringmsg) {
String str ="";
try {
//用密鑰和一組演算法參數初始化此 cipher
ecipher.init(Cipher.ENCRYPT_MODE,key,paramSpec);
//加密並轉換成16進位字串
str = asHex(ecipher.doFinal(msg.getBytes()));
} catch (BadPaddingExceptione) {
} catch (InvalidKeyExceptione) {
} catch (InvalidAlgorithmParameterExceptione) {
} catch (IllegalBlockSizeExceptione) {
}
returnstr;
}
publicstatic String decode(Stringvalue) {
try {
ecipher.init(Cipher.DECRYPT_MODE,key,paramSpec);
returnnew String(ecipher.doFinal(asBin(value)));
} catch (BadPaddingExceptione) {
} catch (InvalidKeyExceptione) {
} catch (InvalidAlgorithmParameterExceptione) {
} catch (IllegalBlockSizeExceptione) {
}
return"";
}
privatestatic String asHex(bytebuf[]) {
StringBuffer strbuf =new StringBuffer(buf.length * 2);
inti;
for (i = 0;i
if (((int)buf[i] & 0xff) < 0x10)//小於十前面補零
strbuf.append("0");
strbuf.append(Long.toString((int)buf[i] & 0xff, 16));
}
returnstrbuf.toString();
}
privatestaticbyte[] asBin(Stringsrc) {
if (src.length() < 1)
returnnull;
byte[]encrypted =newbyte[src.length() / 2];
for (inti = 0;i
inthigh = Integer.parseInt(src.substring(i * 2, i * 2 + 1), 16);//取高位位元組
intlow = Integer.parseInt(src.substring(i * 2 + 1, i * 2 + 2), 16);//取低位位元組
encrypted[i] = (byte) (high * 16 +low);
}
returnencrypted;
}
C中的讀取秘鑰的實現:
#include
#include"cwtlib.h"
constchar keyValue[] = {
21, 25, 21, -45, 25, 98, -55, -45, 10, 35, -45, 35,
26, -5, 25, -65, -78, -99, 85, 45, -5, 10, -0, 11,
-35, -48, -98, 65, -32, 14, -67, 25, 36, -56, -45, -5,
12, 15, 35, -15, 25, -14, 62, -25, 33, -45, 55, 12, -8
};
constchar iv[] = {
-33, 32, -25, 25, 35, -27, 55, -12, -15, 23, 45, -26, 32, 5 - 2, 74, 54
};
JNIEXPORT jbyteArray JNICALL Java_com_cwtlib_aesencript_SecurityUtil_getKeyValue
(JNIEnv *env, jclass obj)
{
jbyteArray kvArray = (*env)->NewByteArray(env,sizeof(keyValue));
jbyte *bytes = (*env)->GetByteArrayElements(env,kvArray,0);
int i;
for (i = 0; i
{
bytes[i] = (jbyte)keyValue[i];
}
(*env)->SetByteArrayRegion(env,kvArray, 0,sizeof(keyValue),bytes);
(*env)->ReleaseByteArrayElements(env,kvArray,bytes,0);
return kvArray;
}
JNIEXPORT jbyteArray JNICALL Java_com_cwtlib_aesencript_SecurityUtil_getIv
(JNIEnv *env, jclass obj)
{
jbyteArray ivArray = (*env)->NewByteArray(env,sizeof(iv));
jbyte *bytes = (*env)->GetByteArrayElements(env,ivArray, 0);
int i;
for (i = 0; i
{
bytes[i] = (jbyte)iv[i];
}
(*env)->SetByteArrayRegion(env,ivArray, 0,sizeof(iv), bytes);
(*env)->ReleaseByteArrayElements(env,ivArray,bytes,0);
return ivArray;
}
在android中如何調用:
publicclass MainActivityextends Activity {
privatestaticfinal StringTAG ="MainActivity";
private StringencriptStr ="18721002361";//加密的字串
@Override
protectedvoid onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//加密後
String enstr = SecurityUtil.encode(encriptStr);
Log.d(TAG,"加密後:" +enstr);
//解密後
String destr = SecurityUtil.decode(enstr);
Log.d(TAG,"解密後:" +destr);
}
}
這裡以一個手機號為例進行加解密處理,具體的可以在日誌中查看到,具體如下。
加解密的對照:
:請點這裡