Android development uses jni to realize analysis of string encryption and decryption

A recent project has a requirement to encrypt sensitive user information, such as user account password, mobile phone number and other private information. In Java , we can use the AES algorithm to encrypt and decrypt strings. Needless to say the benefits of using it, but we also know that the source code of android can be decompiled, so we use pure Java . The AES encryption is not secure, so I thought of using jni in android to encrypt and decrypt strings. It will generate a .so file. More importantly, it is implemented by C/C++ code, so the security line is relatively high. It can be decompiled into machine code, but it can hardly be restored and decompiled, so the following describes the encryption process in detail.

In view of the full use of C/C++ code for string encryption and decryption, we need to consider the differences in data types on different system platforms. Here is another easy-to-implement method, that is, using the AES encryption and decryption logic in Java , and the AES The core secret key required for encryption and decryption is put into C , and the required secret key is read from the static class library by calling jni . The specific implementation is as follows:

 

Project code structure diagram:

 

Java in the AES algorithm logic:

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 {

// Initialize this cipher with a key and a set of algorithm parameters

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

// encrypted and converted into 16 hexadecimal string

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

you;

for (i = 0;i <buf.length;i++)p="" <="" {=""></buf.length;i++)>

if (((int)buf[i] & 0xff)< 0x10)// Padded zero before less than ten

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

}

}

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

加解密的对照效果图:

 

Guess you like

Origin blog.csdn.net/xhf_123/article/details/50188081