• android中使用jni对字符串加解密实现分析


    android中使用jni对字符串加解密实现分析

    近期项目有个需求。就是要对用户的敏感信息进行加密处理,比方用户的账户password,手机号等私密信息。在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");  

    // 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 {             

                //用密钥和一组算法參数初始化此 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 <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);//取高位字节  

                intlow = Integer.parseInt(src.substring(i * 2 + 1, i * 2 + 2), 16);//取低位字节  

                encrypted[i] = (byte) (high * 16 +low);  

            }  

            returnencrypted;  

        }


    C中的读取秘钥的实现:

    #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中怎样调用:

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

    }

    }

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

    加解密的对比效果图:





    好了,到这里我已经罗列出了全部主要文件实现,假设有问题能够在评论或是群(179914858)中进行讨论。另外,原创作品来自不易,转载请注明出处,谢谢。

    最后附上原代码供參考,下载地址:请点这里



  • 相关阅读:
    delphi datetimepicker 修改时间无效问题
    C#写入文件
    C# winform中listview排序
    C/C++,python,java,C#月经贴问题
    Redis Sentinel 原理简单介绍
    JVM垃圾收集 知识汇总
    Java HotSpot VM Options
    Spring三级缓存解决循环依赖
    Markdown基础用法
    join示例分析
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5230771.html
Copyright © 2020-2023  润新知