經過Jni實現AES的CBC模式加密解密

       AES加密方式基本實現,出現一個問題就是代碼的安全性。咱們知道java層代碼很容易被反編譯,頗有可能泄漏咱們加密方式與密鑰 內容,那咱們該怎麼辦呢?咱們能夠使用c/c++實現加密,編譯成So庫的形式,可供java實現調用,這樣就大大加強程序安全性,由於so反編譯結果是 arm指令,沒有java中smali那麼易懂。徹底使用c/c++實現可能會比較麻煩,其實咱們也能夠簡化一部分,只將密鑰使用jni實現,其它仍是用java實現,這樣會簡單一些,下面是具體操做;java

(1)新建項目aesandroid

  在java類中添加native接口,注意寫好native接口和System.loadLibrary()便可。代碼以下:c++

public synchronized static native String getFromNativeIv();

public synchronized static native String getStringFromNative();

 (2)根據class文件生成相應的.h頭文件,執行以下命令便可算法

javah -d jni -classpath c:\Users\sodinochen\AppData\Local\Android\sdk\platforms
\android-16\android.jar;..\..\build\intermediates\classes\debug 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代碼,添加以下:app

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

 

  (5)加密解密類AesUtil: gradle

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

}
相關文章
相關標籤/搜索