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