天天看點

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

android開發中,難免會遇到需要加解密一些資料内容存到本地檔案、或者通過網絡傳輸到其他伺服器和裝置的問題,但并不是使用了加密就絕對安全了,如果加密函數使用不正确,加密資料很容易受到逆向破解攻擊。還有很多開發者沒有意識到的加密算法的問題。

密碼學的三大作用:加密( encryption)、認證(authentication),鑒定(identification) 

加密:防止壞人擷取你的資料。 

認證:防止壞人修改了你的資料而你卻并沒有發現。 

鑒權:防止壞人假冒你的身份。

明文、密文、密鑰、對稱加密算法、非對稱加密算法,這些基本概念和加密算法原理就不展開叙述了。

2.1 android 加密相關api結構

android sdk使用的api和java提供的基本相似,由 java cryptography architecture (jca,java加密體系結構) ,java cryptography extension (jce,java加密擴充包) ,java secure sockets extension(jsse,java安全套接字擴充包),java authentication and authentication service(jaas,java 鑒别與安全服務)組成。

jca提供基本的加密架構,如證書、數字簽名、消息摘要和密鑰對産生器,對應的android api中的以下幾個包:

jce擴充了jca,提供了各種加密算法、摘要算法、密鑰管理等功能,對應的android api中的以下幾個包:

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

jsse提供了ssl(基于安全套接層)的加密功能,使用https加密傳輸使用,對應的android api主要是java.net.ssl包中。

jaas 提供了在java平台上進行使用者身份鑒别的功能。對應的android api主要在以下幾個包:

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

它們其實隻是一組接口,實際的算法是可由不同的provider提供,android api預設的provider主要是是bouncy castle和openssl。 

此外android api還提供了android.security和android.security.keystore(api 23新增)來管理keychain和keystore。

2.2 base64編碼算法

base64編碼算法是一種用64個字元(abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789+/)來表示任意二進制資料的方法。在計算機網絡發展的早期,由于“曆史原因”,電子郵件不支援非ascii碼字元,如果要傳送的電子郵件帶有非ascii碼字元(諸如中文)或者圖檔,使用者收到的電子郵件将會是一堆亂碼,是以發明了base64編碼算法。至于為何會亂碼?請大家自行google。在加解密算法中,原始的資料和加密後的資料一般也是二進制資料,為了不傳輸出錯,友善儲存或者調試代碼,一般需要對加密後的資料進行base64編碼。 

android提供了base64編碼的工具類android.util.base64,可以直接使用,不用自己去實作base64編碼的算法了。 

如:

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

開發者建議: 

base64隻是一種編碼方式,并不是一種加密算法,不要使用base64來加密資料。

2.3 随機數生成器

在android加密算法中需要随機數時要使用securerandom來擷取随機數。 

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

注意不要給securerandom設定種子。調用seeded constructor或者setseed(byte[])是不安全的。securerandom()預設使用的是dev/urandom作為種子産生器,這個種子是不可預測的。 

1、不要使用random類來擷取随機數。 

2、在使用securerandom時候,不要設定種子。使用以下函數設定種子都是有風險的:

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

2.4 hash算法

hash算法是指任意長度的字元串輸入,此算法能給出固定n比特的字元串輸出,輸出的字元串一般稱為hash值。 

具有以下兩個特點:

抗碰撞性:尋找兩個不同輸入得到相同的輸出值在計算上是不可行的,需要大約 

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

 的時間去尋找到具有相同輸出的兩個輸入字元串。

不可逆:不可從結果推導出它的初始狀态。

抗碰撞性使hash算法對原始輸入的任意一點更改,都會導緻産生不同的hash值,是以hash算法可以用來檢驗資料的完整性。我們經常見到在一些網站下載下傳某個檔案時,網站還提供了此檔案的hash值,以供我們下載下傳檔案後檢驗檔案是否被篡改。 

不可逆的特性使hash算法成為一種單向密碼體制,隻能加密不能解密,可以用來加密使用者的登入密碼等憑證。 

1、建議使用sha-256、sha-3算法。 

如使用sha-256算法對message字元串做哈希:

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

2、不建議使用md2、md4、md5、sha-1、ripemd算法來加密使用者密碼等敏感資訊。這一類算法已經有很多破解辦法,例如md5算法,網上有很多查詢的字典庫,給出md5值,可以查到加密前的資料。

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

3、不要使用哈希函數做為對稱加密算法的簽名。 

4、注意:當多個字元串串接後再做hash,要非常當心。 

如:字元串s,字元串t,串接做hash,記為 h (s||t)。但是有可能發生以下情況。如“builtin||securely” 和 “built||insecurely”的hash值是完全一樣的。 

如何修改進而避免上述問題産生? 

改為h(length(s) || s || t)或者 h(h(s)||h(t))或者h(h(s)||t)。

實際開發過程中經常會對url的各個參數,做詞典排序,然後取參數名和值串接後加上某個secret字元串,計算出hash值,作為此url的簽名, 

如foo=1, bar=2, baz=3 排序後為bar=2, baz=3, foo=1,做hash的字元串為:secretbar2baz3foo1,在參數和值之間沒有分隔符,則”foo=bar”和”foob=ar”的hash值是一樣的,”foo=bar&fooble=baz”和”foo=barfooblebaz”一樣,這樣通過精心構造的惡意參數就有可能與正常參數的hash值一樣,進而騙過伺服器的簽名校驗。

2.5 消息認證算法

要確定加密的消息不是别人僞造的,需要提供一個消息認證碼(mac,message authentication code)。 

消息認證碼是帶密鑰的hash函數,基于密鑰和hash函數。

密鑰雙方事先約定,不能讓第三方知道。

消息發送者使用mac算法計算出消息的mac值,追加到消息後面一起發送給接收者。 

接收者收到消息後,用相同的mac算法計算接收到消息mac值,并與接收到的mac值對比是否一樣。 

建議使用hmac-sha256算法,避免使用cbc-mac。 

hmac-sha256例子如下:

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

2.6 對稱加密算法

在對稱加密算法中,資料發信方将明文(原始資料)和加密密鑰一起經過特殊加密算法處理後,使其變成複雜的加密密文發送出去。收信方收到密文後,若想解讀原文,則需要使用加密用過的密鑰及相同算法的逆算法對密文進行解密,才能使其恢複成可讀明文。在對稱加密算法中,使用的密鑰隻有一個,發收信雙方都使用這個密鑰對資料進行加密和解密,這就要求解密方事先必須知道加密密鑰。 

該算法的缺點是,如果一旦密鑰洩漏,那麼加密的内容将都不可信了。 

1、建議使用aes算法。 

2、des預設的是56位的加密密鑰,已經不安全,不建議使用。 

3、注意加密模式不要使用ecb模式。ecb模式不安全,說明問題的經典的三張圖檔,如 

明文是:

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

用ecb加密模式後:

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

用cbc加密模式後:

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

4、android 提供的aes加密算法api預設使用的是ecb模式,是以要顯式指定加密算法為:cbc或cfb模式,可帶上pkcs5padding填充。aes密鑰長度最少是128位,推薦使用256位。

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

2.7 非對稱加密

非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對,如果用公開密鑰對資料進行加密,隻有用對應的私有密鑰才能解密;如果用私有密鑰對資料進行加密,那麼隻有用對應的公開密鑰才能解密(這個過程可以做數字簽名)。 

非對稱加密主要使用的是rsa算法。 

1、注意密鑰長度不要低于512位,建議使用2048位的密鑰長度。 

使用rsa進行數字簽名的算法,如:

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

2、使用rsa算法做加密,rsa加密算法應使用cipher.getinstance(rsa/ecb/oaepwithsha256andmgf1padding),否則會存在重播攻擊的風險。 

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

2.8 加密算法pbe

pbe是一種基于密碼的加密算法,其特點是使用密碼代替了密鑰,而密碼由使用者自己掌管,采用随機數雜湊多重加密等方法保證資料的安全性。 

使用基于密碼的加密算法pbe時,生成密鑰時要加鹽,鹽的取值最好來自securerandom,并指定疊代次數。 

Android應用安全開發之淺談加密算法的坑1、需要了解的基本概念2、Android SDK提供的API3、總結

(以上所有示例算法僅供參考)

幾條原則: 

1、不要自己設計加密算法和協定,使用業界标準的算法。 

2、對稱加密算法不要使用ecb模式,不建議使用des算法。 

3、要選擇合适長度的密鑰。 

4、要確定随機數生成器的種子具有足夠的資訊熵。 

5、不要使用沒有消息認證的加密算法加密消息,無法防重放。 

6、當多個字元串拼接後做hash,要非常當心。 

7、當給算法加yan鹽取值時不要太短,不要重複。 

8、使用初始化向量時iv時,iv為常量的cbc,cfb,gcm等和ecb一樣可以重放,即采用上一個消息的最後一塊密文作為下一個消息的iv,是不安全的。 

9、密鑰應遵循的原則 

(1)密鑰不能為常量,應随機,定期更換,如果加密資料時使用的密鑰為常量,則相同明文加密會得到相同的密文,很難防止字典攻擊。 

(2)開發同學要防範密鑰寫死的毛病。 

而在實際開發中,密鑰如何儲存始終是繞不過的坎?如果寫死在代碼中容易被逆向,如果放在裝置的某個檔案,也會被有經驗的破解者逆向找到,在這裡推薦阿裡聚安全的安全元件服務,其中的安全加密功能提供了開發者密鑰的安全管理與加密算法實作,保證密鑰的安全性,實作安全的加解密操作。

參考: 

1、《java加密與解密的藝術》 

2、《android application secure design/secure coding guidebook》