• 通过Jni实现AES的CBC模式加密解密


           AES加密方式基本实现,出现一个问题就是代码的安全性。我们知道java层代码很容易被反编译,很有可能泄漏我们加密方式与密钥 内容,那我们该怎么办呢?我们可以使用c/c++实现加密,编译成So库的形式,可供java实现调用,这样就大大增强程序安全性,因为so反编译结果是 arm指令,没有java中smali那么易懂。完全使用c/c++实现可能会比较麻烦,其实我们也可以简化一部分,只将密钥使用jni实现,其它还是用java实现,这样会简单一些,下面是具体操作;

    (1)新建项目aes

      在java类中添加native接口,注意写好native接口和System.loadLibrary()即可。代码如下:

    public synchronized static native String getFromNativeIv();
    
    public synchronized static native String getStringFromNative();

     (2)根据class文件生成相应的.h头文件,执行如下命令即可

    javah -d jni -classpath c:UserssodinochenAppDataLocalAndroidsdkplatforms
    android-16android.jar;....uildintermediatesclassesdebug com.aes.jniaes.MainActivity

     3)接下来在app module目录下的build.gradle中设置库文件名(生成的so文件名)。找到gradle文件的defaultConfig这项,在里面添加如下内容:

    defaultConfig {
            applicationId "com.aes.jniaes"
            minSdkVersion 15
            targetSdkVersion 22
            versionCode 1
            versionName "1.0"
    
            ndk {
                moduleName "aesjni"       //生成的so名字
                abiFilters "armeabi", "armeabi-v7a", "x86"   //输出指定三种abi体系结构下的so库。目前可有可无。
            }
        }

     (4)最后就是添加静态初始化loadLibrary代码,添加如下:

    static {
             System.loadLibrary("checkapp-jni");    //so文件的名字
           }

      (5)加密解密类AesUtil:

    public class AesUtils {
    
        // 加密
        public static String Encrypt(String sSrc, String sKey, String sIv) throws Exception {
            if (sKey == null) {
                System.out.print("Key为空null");
                return null;
            }
            // 判断Key是否为16位
            if (sKey.length() != 16) {
                System.out.print("Key长度不是16位");
                return null;
            }
            byte[] raw = sKey.getBytes();
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");// "算法/模式/补码方式"
            IvParameterSpec iv = new IvParameterSpec(sIv.getBytes());// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(sSrc.getBytes());
    
            String mm = new String(Base64.encode(encrypted, Base64.DEFAULT));
    
            return mm;// 此处使用BASE64做转码功能,同时能起到2次加密的作用。
        }
    
    
        // 解密
        public static String Decrypt(String sSrc, String sKey, String sIv) throws Exception {
            try {
                // 判断Key是否正确
                if (sKey == null) {
                    System.out.print("Key为空null");
                    return null;
                }
                // 判断Key是否为16位
                if (sKey.length() != 16) {
                    System.out.print("Key长度不是16位");
                    return null;
                }
                byte[] raw = sKey.getBytes("UTF-8");
                SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                IvParameterSpec iv = new IvParameterSpec(
                        sIv.getBytes());
                cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
                byte[] encrypted1 = Base64.decode(sSrc, Base64.DEFAULT);
                try {
                    byte[] original = cipher.doFinal(encrypted1);
                    String originalString = new String(original);
                    return originalString;
                } catch (Exception e) {
                    System.out.println(e.toString());
                    return null;
                }
            } catch (Exception ex) {
                System.out.println(ex.toString());
                return null;
            }
        }
    
    }
  • 相关阅读:
    ibatis插入正确但查询不出数据的问题
    Java 动态代理机制分析及扩展--转
    java实现插入排序算法 附单元测试源码
    unix基础知识
    作为大数据和云计算学习的一个序吧
    Understanding JVM Internals---不得不转载呀
    回文推理
    java 正则表达式提取html纯文本
    OpenCV功能界面和示例
    【POJ3268】Silver Cow Party 最短
  • 原文地址:https://www.cnblogs.com/summers/p/4466209.html
Copyright © 2020-2023  润新知