Android Keystore 實作筆記




先講一下使用情境,OWASP說App內部儲存的資料有資安風險,要求加密,所以如果你手上有一些企業級的App, 有一些很好心的單位,就會主動幫你做資安檢測,然後檢測項目就是根據OWASP去延伸。

但我一直不能理解的是,Android本身的App資料預設就是只有該App能存取,就連使用者本身都要root才能去取得資料,而root這件事本身就是自己敞開大門歡迎小偷來偷,總不能說你買了一本筆記本,然後把提款帳號密碼寫在上面,放在客廳桌上,然後家裡大門不關,跟做筆記本的廠商說,你看你這樣會害我帳號密碼被偷有資安風險吧?

之前也有機會問到某組織的資安組長,他說他們是在模擬器的環境中做檢測的,模擬器不等於真實環境,而且模擬器為了方便debug預設就是root,怎麼能依照這樣的流程來判定這樣有風險呢?再者我認為真正威脅應該是,在真實世界中我手機掉了,或者是我正常使用的過程中會導致帳號密碼被竊取或外洩,這才是真正有殺傷力的,不是嗎?

回歸正題,所以在客戶端的資料如:SharedPreferences、SQLite,要如何加密呢?
有三個方式

  1. 客戶端加密
    建議使用AES加密演算法,但這種方式把是把key放在App裡面,只要反組譯App很輕鬆就可以取得key,比較進階的做法是使用NDK的方式透過C或C++的方式取得key,但這也只是增加破解難度而已,治標不治本
  2. Server端取得鑰匙
    就是把key放在Server端,要用的時候再拿,算是安全但比較費工的方式
  3. 使用Keystore
    前面講了這麼多知識廢話,現在要進入今天的正題了,Keystore是什麼呢?簡單來說他是系統提供一個存放鑰匙的地方,只有App能取得自己放的鑰匙,別人是不能亂拿的。

    所以在這個前提之下,我們就有一個可以在客戶端安全存放鑰匙的地方了,不過需要注意的地方是在Android 4.3(API 18)才有提供這個功能,而部分的演算法甚至要求更高的版本,所以使用前要先注意一下,像我這邊想使用的AES就必須要API 23才能使用。

    而在API 18我們能用的只有RSA,如果你只是要加密很短的資料,RSA就夠用了,但如果像我的需求要加密的資料很多,那會建議使用我等一下要講的進階用法。

    就是在Keystore的部份我們使用RSA演算法,但我們也使用AES來加快速度,做法是客戶端資料的加解密使用AES,因為我想要支援版本較低的手機(Android 4.3),所以無法將AES的key放進Keystore,所以這邊的做法是使用RSA加密AES的key後再儲存在客戶端,這樣一來就達成了安全性與加解密速度的平衡了
最後紀錄幾個關鍵的問題點
RSA因為演算法的關係,同樣的資料每次加密後的結果都不一樣,別拿來加密SharedPreferences的key。

RSA Android預設的key長度是2048,要注意資料加密要比key少11 byte,如果長度超過要記得做分段處理。

byte轉Base64處理比轉hex好,Base64相對比較省資源,Base64比原來多1/3但hex是變兩倍。

Base64會轉出空白?(應該是某些xml中不顯示的符號),但拿來當key會被濾掉,導致資料對不起來,建議使用

Base64.decode(content, Base64.NO_WRAP);

以上筆記,希望有幫到大家。

留言