簽名驗證,就是在APP中寫入自己私鑰的hash值,和一個獲取當前簽名中的私鑰hash值的函式兩個值相一致,那麼就說明APP沒有被改動允許APP執行。如果兩值不一致那麼說明APP是被二次打包的,APP就自我銷燬程序。
簽名驗證又可以在兩個地方做,一個是在MainActivity.java的OnCreate函式中做,一個是在原生程式碼檔案的JNI_OnLoad函式中做。
在OnCreate函式中做,短處是反編譯者只要找到在OnCreate中定位到驗證函式,然後將其註釋,重新打包APP就可以成功執行;好處就是程式碼簡單。
為了最大限度地提高安全性,可以考濾兩種驗證都使用。
最後為了避免爭議,在此要做一下統一宣告,以下程式碼基本我個人都不是原作者,個人在本節的作用是將幾個方案整合成了一個比較合理的方案,並驗證這些程式碼和整合出來的方案是可行的。
2.1 在MainActivity.java的OnCreate函式中進行簽名驗證
OnCreate函式內、setContentView後加入以下程式碼:
在MainActivity類內,OnCreate函式外加入以下程式碼:
2.2 原生程式碼檔案的JNI_OnLoad函式中進行簽名驗證
開始看到這位小哥哥的文章,就喜歡這種有圖有真相的文章,說明其程式碼應該是真的可以獲取到APP當前的sha1值的。
但後來理清他的做法是:從java中把context傳過去,在c++中完成比較返回true或false;也就是說決定程式退不退出的if語句還是在java中的,這種做法和2.1中全在java中做除了顯示技術比較強之外安全效果完全一樣並沒有提升啊。if應當在c++中實現,context也需要c++自己獲取。
後來找到另一位小哥哥的文章,其指出判斷需要在c++中做而且是在JNI_OnLoad函式中做並給出了方法,但是他獲取context時實現的NoProGuard我沒搞清楚在哪匯入。
最後找到了又一位小哥哥的文章,其給出了JNI獲取context的方案,驗證也確實是可行的。
所以整合的方案就是:第二位小哥哥在JNI_OnLoad函式中做的思想+第三位小哥哥獲取context的方法+第一位小哥哥獲取sha1的方法。
(其實第二位小哥哥還有一個思想就是debug時不需要驗證release才要驗證,這也是可取的,我這裡也採用了。但debug時要做驗證也不是不可以的,只是要注意debug時執行在avd中的app使用的是Android Studio自己生成的keystore而不是我們釋出apk時自己的keystore,所以此時填的sha1的值應當是Android Studio自己生成的keystore的sha1,
當然第二位小哥哥獲取md5的方法改一下好像也是能獲取正確的sha1值的)
2.2.1 C++中驗證簽名程式碼
最終C++中驗證簽名的程式碼如下,自己使用時要注意將其中的app_sha1賦值成自己keystore中的sha1值
2.2.2 配置build_gradle
由於程式碼中使用了以下預編譯語句,所以如果只是使用上邊的程式碼,驗證是沒有生效的。說明如下:
build_gradle中未配置RELEASE_MODE=1----release/debug都不進行簽名驗證
build_gradle中配置RELEASE_MODE=1----release模式驗證/debug模式不驗證
註釋掉ifdef和endif兩條預編譯語句----release/debug都進行簽名驗證
所以為了啟用驗證,還需要開啟app目錄下的build_gradle檔案,在如下圖所示位置加入以下程式碼:
2.2.3 MainActivity.java中載入so檔案
當然最還得要在java檔案中,載入so檔案才能起來作用。netive-test是我這裡so的庫名改成自己的
簽名驗證,就是在APP中寫入自己私鑰的hash值,和一個獲取當前簽名中的私鑰hash值的函式兩個值相一致,那麼就說明APP沒有被改動允許APP執行。如果兩值不一致那麼說明APP是被二次打包的,APP就自我銷燬程序。
簽名驗證又可以在兩個地方做,一個是在MainActivity.java的OnCreate函式中做,一個是在原生程式碼檔案的JNI_OnLoad函式中做。
在OnCreate函式中做,短處是反編譯者只要找到在OnCreate中定位到驗證函式,然後將其註釋,重新打包APP就可以成功執行;好處就是程式碼簡單。
為了最大限度地提高安全性,可以考濾兩種驗證都使用。
最後為了避免爭議,在此要做一下統一宣告,以下程式碼基本我個人都不是原作者,個人在本節的作用是將幾個方案整合成了一個比較合理的方案,並驗證這些程式碼和整合出來的方案是可行的。
2.1 在MainActivity.java的OnCreate函式中進行簽名驗證
OnCreate函式內、setContentView後加入以下程式碼:
在MainActivity類內,OnCreate函式外加入以下程式碼:
2.2 原生程式碼檔案的JNI_OnLoad函式中進行簽名驗證
開始看到這位小哥哥的文章,就喜歡這種有圖有真相的文章,說明其程式碼應該是真的可以獲取到APP當前的sha1值的。
但後來理清他的做法是:從java中把context傳過去,在c++中完成比較返回true或false;也就是說決定程式退不退出的if語句還是在java中的,這種做法和2.1中全在java中做除了顯示技術比較強之外安全效果完全一樣並沒有提升啊。if應當在c++中實現,context也需要c++自己獲取。
後來找到另一位小哥哥的文章,其指出判斷需要在c++中做而且是在JNI_OnLoad函式中做並給出了方法,但是他獲取context時實現的NoProGuard我沒搞清楚在哪匯入。
最後找到了又一位小哥哥的文章,其給出了JNI獲取context的方案,驗證也確實是可行的。
所以整合的方案就是:第二位小哥哥在JNI_OnLoad函式中做的思想+第三位小哥哥獲取context的方法+第一位小哥哥獲取sha1的方法。
(其實第二位小哥哥還有一個思想就是debug時不需要驗證release才要驗證,這也是可取的,我這裡也採用了。但debug時要做驗證也不是不可以的,只是要注意debug時執行在avd中的app使用的是Android Studio自己生成的keystore而不是我們釋出apk時自己的keystore,所以此時填的sha1的值應當是Android Studio自己生成的keystore的sha1,
當然第二位小哥哥獲取md5的方法改一下好像也是能獲取正確的sha1值的)
2.2.1 C++中驗證簽名程式碼
最終C++中驗證簽名的程式碼如下,自己使用時要注意將其中的app_sha1賦值成自己keystore中的sha1值
2.2.2 配置build_gradle
由於程式碼中使用了以下預編譯語句,所以如果只是使用上邊的程式碼,驗證是沒有生效的。說明如下:
build_gradle中未配置RELEASE_MODE=1----release/debug都不進行簽名驗證
build_gradle中配置RELEASE_MODE=1----release模式驗證/debug模式不驗證
註釋掉ifdef和endif兩條預編譯語句----release/debug都進行簽名驗證
所以為了啟用驗證,還需要開啟app目錄下的build_gradle檔案,在如下圖所示位置加入以下程式碼:
2.2.3 MainActivity.java中載入so檔案
當然最還得要在java檔案中,載入so檔案才能起來作用。netive-test是我這裡so的庫名改成自己的