Android應用安全開發之淺談加密算法的坑
Android開發中,難免會遇到需要加解密一些數據內容存到本地文件、或者通過網絡傳輸到其他服務器和設備的問題,但並不是使用了加密就絕對安全了,如果加密函數使用不正確,加密數據很容易受到逆向破解攻擊。還有很多開發者沒有意識到的加密算法的問題。
1、需要了解的基本概念
密碼學的三大作用:加密( Encryption)、認證(Authentication),鑒定(Identification)
加密:防止壞人獲取你的數據。
認證:防止壞人修改了你的數據而你卻並沒有發現。
鑒權:防止壞人假冒你的身份。
明文、密文、密鑰、對稱加密算法、非對稱加密算法,這些基本概念和加密算法原理就不展開敘述了。
2、Android SDK提供的API
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中的以下幾個包:
JSSE提供了SSL(基於安全套接層)的加密功能,使用HTTPS加密傳輸使用,對應的Android API主要是java.net.ssl包中。
JAAS 提供了在Java平台上進行用戶身份鑒別的功能。對應的Android API主要在以下幾個包:
它們其實隻是一組接口,實際的算法是可由不同的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編碼的算法了。
如:
開發者建議:
base64隻是一種編碼方式,並不是一種加密算法,不要使用base64來加密數據。
2.3 隨機數生成器
在Android加密算法中需要隨機數時要使用SecureRandom來獲取隨機數。
如:
注意不要給SecureRandom設置種子。調用seeded constructor或者setSeed(byte[])是不安全的。SecureRandom()默認使用的是dev/urandom作為種子產生器,這個種子是不可預測的。
開發者建議:
1、不要使用Random類來獲取隨機數。
2、在使用SecureRandom時候,不要設置種子。使用以下函數設置種子都是有風險的:
2.4 Hash算法
Hash算法是指任意長度的字符串輸入,此算法能給出固定n比特的字符串輸出,輸出的字符串一般稱為Hash值。
具有以下兩個特點:
-
抗碰撞性:尋找兩個不同輸入得到相同的輸出值在計算上是不可行的,需要大約
的時間去尋找到具有相同輸出的兩個輸入字符串。
- 不可逆:不可從結果推導出它的初始狀態。
抗碰撞性使Hash算法對原始輸入的任意一點更改,都會導致產生不同的Hash值,因此Hash算法可以用來檢驗數據的完整性。我們經常見到在一些網站下載某個文件時,網站還提供了此文件的hash值,以供我們下載文件後檢驗文件是否被篡改。
不可逆的特性使Hash算法成為一種單向密碼體製,隻能加密不能解密,可以用來加密用戶的登錄密碼等憑證。
開發者建議:
1、建議使用SHA-256、SHA-3算法。
如使用SHA-256算法對message字符串做哈希:
2、不建議使用MD2、MD4、MD5、SHA-1、RIPEMD算法來加密用戶密碼等敏感信息。這一類算法已經有很多破解辦法,例如md5算法,網上有很多查詢的字典庫,給出md5值,可以查到加密前的數據。
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例子如下:
2.6 對稱加密算法
在對稱加密算法中,數據發信方將明文(原始數據)和加密密鑰一起經過特殊加密算法處理後,使其變成複雜的加密密文發送出去。收信方收到密文後,若想解讀原文,則需要使用加密用過的密鑰及相同算法的逆算法對密文進行解密,才能使其恢複成可讀明文。在對稱加密算法中,使用的密鑰隻有一個,發收信雙方都使用這個密鑰對數據進行加密和解密,這就要求解密方事先必須知道加密密鑰。
該算法的缺點是,如果一旦密鑰泄漏,那麼加密的內容將都不可信了。
開發者建議:
1、建議使用AES算法。
2、DES默認的是56位的加密密鑰,已經不安全,不建議使用。
3、注意加密模式不要使用ECB模式。ECB模式不安全,說明問題的經典的三張圖片,如
明文是:
用ECB加密模式後: