android中使用jni对字符串加解密实现分析
android中使用jni對字符串加解密實現(xiàn)分析
近期項目有個需求。就是要對用戶的敏感信息進行加密處理,比方用戶的賬戶password,手機號等私密信息。在java中,就對字符串的加解密我們能夠使用AES算法加密字符串。使用它的優(yōu)點就不必多說了,但我們又知道android的源碼是能夠被反編譯的,所以使用純Java方式的AES加密是不安全的,所以想到了使用android中的jni來對字符串加解密處理,它會產(chǎn)生一個.so文件,更重要的是它通過C/C++代碼實現(xiàn)。所以安全行比較高。它能夠被反編譯成機器碼,但差點兒不能被還原反編譯。那么以下就具體介紹下這樣的的加密處理。
鑒于全然使用C/C++代碼進行字符串的加解密,我們須要考慮不同系統(tǒng)平臺上數(shù)據(jù)類型的差異問題。這里推薦還有一種易于實現(xiàn)的方法。即使用Java中的AES加解密邏輯,而將AES加解密所須要的核心秘鑰放入到C中,通過調(diào)用jni來從靜態(tài)類庫中讀取須要的秘鑰,詳細實現(xiàn)例如以下:
項目代碼結(jié)構(gòu)圖:
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"); ?
// Java項目中的寫法
??????????????? SecureRandom?random = SecureRandom.getInstance("SHA1PRNG");
????????????????// Android項目中的寫法
????????????????SecureRandom?random = SecureRandom.getInstance("SHA1PRNG","Crypto");? ? ? ? ?
random.setSeed(keyValue);
??????????????? kgen.init(128,random);??
? ? ? ? ? ? ? ? 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 {? ? ? ? ? ? ?
? ? ? ? ? ? //用密鑰和一組算法參數(shù)初始化此 cipher ?
? ? ? ? ? ? ecipher.init(Cipher.ENCRYPT_MODE,key,paramSpec); ?
? ? ? ? ? ? //加密并轉(zhuǎn)換成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 <buf.length;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 <src.length() / 2;i++) { ?
? ? ? ? ? ? inthigh = Integer.parseInt(src.substring(i * 2, i * 2 + 1), 16);//取高位字節(jié) ?
? ? ? ? ? ? intlow = Integer.parseInt(src.substring(i * 2 + 1, i * 2 + 2), 16);//取低位字節(jié) ?
? ? ? ? ? ? encrypted[i] = (byte) (high * 16 +low); ?
? ? ? ? } ?
? ? ? ? returnencrypted; ?
? ? }
C中的讀取秘鑰的實現(xiàn):
#include<stdio.h>
#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 <sizeof(keyValue);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 <sizeof(iv); i++)
{
bytes[i] = (jbyte)iv[i];
}
?? ?
(*env)->SetByteArrayRegion(env,ivArray, 0,sizeof(iv), bytes);
(*env)->ReleaseByteArrayElements(env,ivArray,bytes,0);
return ivArray;
}
在android中怎樣調(diào)用:
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);
}
}
這里以一個手機號為例進行加解密處理,詳細的效果圖能夠在日志中查看到,詳細例如以下。
加解密的對比效果圖:
好了,到這里我已經(jīng)羅列出了全部主要文件實現(xiàn),假設(shè)有問題能夠在評論或是群(179914858)中進行討論。另外,原創(chuàng)作品來自不易,轉(zhuǎn)載請注明出處,謝謝。
最后附上原代碼供參考,下載地址:請點這里
轉(zhuǎn)載于:https://www.cnblogs.com/bhlsheji/p/5230771.html
總結(jié)
以上是生活随笔為你收集整理的android中使用jni对字符串加解密实现分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: telnet客户端模拟浏览器发送请求
- 下一篇: 日志处理--高效Linux命令整理