| 加密技術(shù)是最常用的安全保密手段,利用技術(shù)手段把明文變?yōu)槊芪模用埽﹤魉?,到達(dá)目的地后再用相同或不同的手段還原(解密)。常見(jiàn)的加密算法可以分成三類,對(duì)稱加密算法,非對(duì)稱加密算法和HASH算法。前兩類是可逆的,即加密后的密文仍然可以轉(zhuǎn)換成明文,但Hash算法是不可逆的,即使在有源碼及密文的情況下也無(wú)法將明文還原出來(lái),如MD5算法。 
 由于Java的語(yǔ)言特點(diǎn)及Android的開(kāi)放性質(zhì),出現(xiàn)了越來(lái)越多的惡意程序。谷歌Android市場(chǎng)在也曾多次遭惡意開(kāi)發(fā)者上傳基于正常應(yīng)用篡改后的惡意軟件,雖然這些軟件已經(jīng)被查出,但在將其下架前已經(jīng)造成了幾十萬(wàn)用戶被感染。這些惡意程序都是以已存在的成名的應(yīng)用為載體,經(jīng)過(guò)二次處理后植入惡意代碼,重新簽證后再次向市場(chǎng)發(fā)布,誘導(dǎo)用戶下載使用。為了避免這種情況的發(fā)生,保護(hù)自己的應(yīng)用在未經(jīng)自己允許的情況下慘遭篡改,保護(hù)自己的應(yīng)用不會(huì)被人利用做一些傷害用戶的行為,本章節(jié)中將介紹這樣一種保護(hù)機(jī)制。
 
 Android系統(tǒng)要求每一個(gè)安裝進(jìn)系統(tǒng)的應(yīng)用程序都是經(jīng)過(guò)數(shù)字證書(shū)簽名的,數(shù)字證書(shū)的私鑰(即.keystore簽證文件)則保存在程序開(kāi)發(fā)者的手中,簽證后的信息摘要保存在APK包中的.RSA文件中。數(shù)字證書(shū)用來(lái)標(biāo)識(shí)應(yīng)用程序的作者與應(yīng)用程序之間建立信任關(guān)系。一旦證書(shū)被篡改,則.RSA文件被替換了,即表明應(yīng)用程序的原作者不再為該應(yīng)用負(fù)責(zé)。依照這個(gè)原理,可以在第一次運(yùn)行程序時(shí)讀取APK中的.RSA摘要信息對(duì)其進(jìn)行判斷是否是與經(jīng)應(yīng)用原作者簽名后產(chǎn)生的信息一致。如果一致則讓程序正常運(yùn)行;如果不一致則表明應(yīng)用被篡改過(guò),提示用戶并終止運(yùn)行。
 
 可以通過(guò)以下方法獲取APK包中的.RSA信息:
 
 
 | 1 | Signature[] sigs = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES).signatures; | 
| 2 | byte[] data = sigs[0].toByteArray(); | 
在Android官方文檔中,對(duì)Signature類的定義是:在應(yīng)用程序包及對(duì)該包進(jìn)行簽名的證書(shū)間建立起不透明的、不可改變的代表關(guān)系。執(zhí)行Signature.toByteArray()將返回.RSA的字節(jié)信息。
 
 下面將把這些字節(jié)轉(zhuǎn)換成可閱讀的數(shù)字指紋信息:
 
 
 | 2 | MessageDigest algorithm = MessageDigest.getInstance(alg); | 
| 3 | // 將狀態(tài)重圍到初始化,準(zhǔn)備好進(jìn)行計(jì)算Hash值。 | 
| 7 | // 將Hash值轉(zhuǎn)為可讀的16進(jìn)制文本 | 
| 8 | byte[] dataHash = algorithm.digest(); | 
通過(guò)MessageDigest來(lái)計(jì)算數(shù)字指紋信息,其算法核心是HASH函數(shù)。哈希函數(shù)提供了這樣一種計(jì)算過(guò)程:輸入一個(gè)長(zhǎng)度不固定的字符串,返回一串定長(zhǎng)度的字符串,即HASH值。
 
 HASH函數(shù)主要可以解決以下兩個(gè)問(wèn)題:一是無(wú)法通過(guò)HASH值得到原報(bào)文;二是不存在不同報(bào)文經(jīng)HASH操作后生成相同HASH值。
 
 這樣在數(shù)字簽名中就可以解決驗(yàn)證簽名和用戶身份驗(yàn)證、不可抵賴性的問(wèn)題。在獲取MessageDigest時(shí)要指定所使用的算法名稱,常見(jiàn)的算法是專門(mén)用于加密處理的MD5和SHA1。這兩種算法產(chǎn)生一種128位信息摘要,除徹底地搜尋外,沒(méi)有更快的方法對(duì)其加以攻擊,而其搜索時(shí)間一般需要1025年之久,這樣即可保證信息在一段時(shí)間內(nèi)的有效性與安全性。
 
 使用MessageDigest時(shí),養(yǎng)成一個(gè)良好的習(xí)慣是在讀取數(shù)據(jù)前將其reset()置初始化狀態(tài),即使這個(gè)實(shí)例是剛實(shí)例化的,這樣盡量可以避免之前已讀的冗余數(shù)據(jù)對(duì)最后的結(jié)果產(chǎn)生負(fù)作用。接下來(lái)就是使用update()方法讀取待計(jì)算的數(shù)據(jù),完成后調(diào)用digest()將返回計(jì)算后的HASH值dataHash數(shù)組。最后為了可讀性,通過(guò)自己實(shí)現(xiàn)的toHexString()把HASH值由byte轉(zhuǎn)為16進(jìn)制文本。
 
 在得到dataHash時(shí),即可對(duì)應(yīng)用程序是否正版進(jìn)行判斷了,但一般為了簡(jiǎn)便,把提前寫(xiě)入的正版的指紋信息與最后HexString值進(jìn)行比較,從而得出應(yīng)用程序是否被篡改的結(jié)果。比較代碼如下:
 
 
 | 01 | txtVerify.setText(alg + '\n'); | 
| 03 | String result = 'This soft is a pirated software.'; | 
| 06 |         txtVerify.append('Original:'+ '\n'+ HASH_VALUE_MD5 + '\n'); | 
| 07 |         if(HASH_VALUE_MD5.equals(hexInfo)) { | 
| 08 |                 result = 'This soft is a genuine software'; | 
| 10 | } elseif(alg.equals(SHA1)) { | 
| 11 |         txtVerify.append('Original:'+ '\n'+ HASH_VALUE_SHA1 + '\n'); | 
| 12 |         if(HASH_VALUE_SHA1.equals(hexInfo)) { | 
| 13 |                 result = 'This soft is a genuine software'; | 
| 17 | txtVerify.append('Current:'+ ':\n'+ hexInfo + '\n'); | 
| 18 | txtVerify.append(result); | 
以上代碼中的HASH_VALUE_MD5和HASH_VALUE_SHA1分別是使用Code_Test_Key.keystore簽名后的APK實(shí)際計(jì)算出的HASH值。
 
 Demo運(yùn)行效果如下:
 
 
 
 圖17-1  驗(yàn)證MD5值
 
 
 圖17-2  驗(yàn)證SHA1值
 
 Demo源代碼下載: Code_Test.rar(825.11 KB, 下載次數(shù): 308, 售價(jià): 1 資源分) 
                                     |