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;

privatestaticAlgorithmParameterSpecparamSpec;

privatestatic Cipherecipher;

static {

System.loadLibrary("cwtlib");

keyValue = getKeyValue();

iv = getIv();

if(null != keyValue &&

null !=iv) {

KeyGeneratorkgen;

try {

kgen =KeyGenerator.getInstance("AES");

kgen.init(128,newSecureRandom(keyValue));

key =kgen.generateKey();

paramSpec =newIvParameterSpec(iv);

ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

} catch(NoSuchAlgorithmExceptione) {

} catch(NoSuchPaddingExceptione) {

}

}

}

publicstaticnativebyte[]getKeyValue();

publicstaticnativebyte[]getIv();

publicstatic Stringencode(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 Stringdecode(Stringvalue) {

try {

ecipher.init(Cipher.DECRYPT_MODE,key,paramSpec);

returnnewString(ecipher.doFinal(asBin(value)));

} catch (BadPaddingExceptione){

} catch (InvalidKeyExceptione){

} catch(InvalidAlgorithmParameterExceptione) {

} catch(IllegalBlockSizeExceptione) {

}

return"";

}

privatestatic StringasHex(bytebuf[]) {

StringBuffer strbuf =newStringBuffer(buf.length * 2);

inti;

for (i = 0;i <buf.length;i++)p="" <="" {=""></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 <=""{="" 2;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 JNICALLJava_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++)< p=""></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 JNICALLJava_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 MainActivityextendsActivity {

privatestaticfinal StringTAG="MainActivity";

private StringencriptStr="18721002361";//加密的字符串

@Override

protectedvoidonCreate(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);

}

}

这里以一个手机号为例进行加解密处理,具体的效果图可以在日志中查看到,具体如下。

加解密的对照效果图:

 

猜你喜欢

转载自blog.csdn.net/xhf_123/article/details/50188081