前言
安全問題在互聯(lián)網(wǎng),軟件領(lǐng)域從來都是不可忽視的,而隨著移動(dòng)互聯(lián)網(wǎng)的發(fā)展,移動(dòng)端不管是在設(shè)備持有量上,還是在用戶數(shù)量上,都已經(jīng)超越傳統(tǒng)PC端,成為第一大入口端。因此提高對(duì)于移動(dòng)安全領(lǐng)域的關(guān)注,加強(qiáng)移動(dòng)端的安全等級(jí),是很有必要的。
而一般情況下,移動(dòng)端安全大致上可以分為以下幾個(gè)維度:
- Web安全
- 網(wǎng)絡(luò)通訊安全
- 本地安全
Web安全,主要考慮Web服務(wù)中每一層可能的漏洞,及由此衍生的一系列安全問題,如:存儲(chǔ)層中的SQL注入問題,Nginx(容器)層的DDoS問題,前端層級(jí)的XSS跨站腳本問題等。
網(wǎng)絡(luò)通訊安全,需要考慮通訊過程中信息的安全性,防止由于信息泄露導(dǎo)致的其他安全問題,比如:常見的各種形式的中間人問題等。
本地安全主要指客戶端本地環(huán)境與數(shù)據(jù)的安全,以及代碼被破解獲得所導(dǎo)致的安全問題,如:明文存儲(chǔ)問題,惡意二次打包問題,越權(quán)操作問題等。
其中,本地安全攻擊大多發(fā)生在攻擊者自己手機(jī)上,開發(fā)者和運(yùn)維較難感知,所以容易被大家忽略,從而很容易成為整個(gè)鏈路的安全短板。本文將著重就本地安全,公司所采取的安全圖片方案跟大家做一個(gè)介紹,其中的一些細(xì)節(jié)基于安全考慮會(huì)略去,保留其基本思路,希望對(duì)大家有所幫助,也歡迎共同交流。
安全圖片解決方案
安全圖片方案解決了本地安全的幾個(gè)問題:
- 明文存儲(chǔ),過度依賴系統(tǒng)安全性(iOS:KC/UserDefault;Android:KeyStore/SharedPreference)
- 惡意二次打包
- 容易被逆向,被調(diào)試
- 敏感信息寫入代碼
優(yōu)點(diǎn)
- 使用便捷簡(jiǎn)單
- 對(duì)工程及代碼侵入性較小
- 顯著提高APP的安全性
當(dāng)然,該方案也存在一些問題,比如字段的存取需要走I/O以及二進(jìn)制流處理,一定程度上會(huì)影響APP性能,同時(shí)安全性建立在SDK本身和安全圖片安全性的基礎(chǔ)上,容易在這一塊出現(xiàn)安全短板。
所幸,正常獲取字段的開銷時(shí)間一般都不會(huì)超過30毫秒(視具體算法而定)。而安全性問題,還是需要靠持續(xù)加強(qiáng)SDK安全性,強(qiáng)化安全圖片使用的算法,來提升短板,增大破解成本。
安全圖片
我們的安全圖片方案主要包含了安全圖片生成,安全圖片消費(fèi),二次打包檢查,調(diào)試檢查等功能,這些功能分布在安全SDK及圖片生成工具(以web形式提供)中。
結(jié)構(gòu)如下:

可以看到,圖片文件作為信息加密和存儲(chǔ)的中心媒介,在其中起到了非常重要的作用。其實(shí)這里也可以用其他形式的文件,比如文本文件,視頻文件,音頻文件。
那么為什么要用圖片呢?綜合來看:
- 圖片資源在我們的移動(dòng)項(xiàng)目中非常常見,有比較大的混淆性
- 圖片的易操作性比較強(qiáng),比較容易插入想要加密的信息
- 讀取性能比較好,同時(shí)容易優(yōu)化
所以技術(shù)選型過程中,根據(jù)實(shí)際業(yè)務(wù)形態(tài),也可能選擇音頻、視頻、特殊文本等其他文件作為中心媒介,比如富含大量音視頻信息的APP/游戲,包含很多特殊格式電子書的電子書閱讀軟件,等等。
安全圖片方案-流程
從結(jié)構(gòu)圖可以看出,我們的圖片解決方案包含了"獲取web端(圖片生成工具)生成的安全圖片","在APP中通過SDK使用安全圖片"這兩個(gè)流程。
獲取安全圖片

獲取安全圖片流程中,由于iOS和Android各自的包檢查依賴項(xiàng)不一樣,在輸入項(xiàng)上會(huì)有所區(qū)別,iOS使用BundleID、Android使用keystore的數(shù)字簽名SHA1值作為檢查項(xiàng)。
在獲取到用戶輸入信息之后,還需要一個(gè)加密的關(guān)鍵信息:加密密鑰。
這里可以有三種思路:
- 由server端生成密鑰,存儲(chǔ)在服務(wù)器端,之后通過安全的通訊協(xié)議(如https)從服務(wù)器獲取。
- 由server端生成密鑰,之后按照某些算法或者規(guī)則插入到圖片當(dāng)中
- 從圖片中按照某種規(guī)則或者算法,生成一個(gè)密鑰
這三種方式各有利弊:
- 第一種方案的安全性基于通訊安全,能在本地安全被攻破的情況下保持安全鏈路完整,隔離不同業(yè)務(wù)方的密鑰安全性,但是隨之也帶來了一些新的問題,如:中間人攻擊、網(wǎng)絡(luò)性能問題等。
- 第二種針對(duì)業(yè)務(wù)方較多的情況下,安全等級(jí)較高,能做到不同業(yè)務(wù)方不同版本APP的安全性隔離,在密鑰生成算法或者密鑰規(guī)則泄露后(低概率),可以及時(shí)更新密鑰,阻止安全事故的擴(kuò)大化;但同時(shí)也存在,可能對(duì)圖片的使用造成輕微影響,算法可能較為復(fù)雜,在讀取時(shí)對(duì)性能造成影響,算法門檻較高等問題。
- 最后一種較為簡(jiǎn)單,門檻低,同時(shí)對(duì)圖片影響較小,讀取開銷相對(duì)較小,也能滿足一般情況下的密鑰獲取方案;但當(dāng)密鑰獲取算法或規(guī)則泄露后(低概率),阻止安全事故擴(kuò)大化的成本相對(duì)較高,容易成為安全短板。
在得到了密鑰之后,結(jié)合用戶輸入的信息,通過對(duì)稱加密算法,生成加密后的密文再寫入圖片之中。
寫入圖片的方法很多,比如如下兩種:
- 在jpg中,可以通過寫入Exif區(qū),這塊區(qū)域存入了相機(jī)拍攝信息:時(shí)間、拍攝地點(diǎn)等等,可以在這個(gè)區(qū)域存入加密后的信息,實(shí)現(xiàn)圖片的無損加密。
- 在png中,可以在IEND(png文件尾部)區(qū)域后追加加密信息,在此區(qū)域追加的信息不會(huì)影響圖像的正常讀取。但是用png格式需要注意在編譯的時(shí)候會(huì)被編譯器自動(dòng)壓縮,從而失去加密的信息。可以考慮動(dòng)態(tài)獲取安全圖片來規(guī)避這個(gè)問題,比如從網(wǎng)絡(luò)中加載圖片再寫入本地。
上述方案相對(duì)比較簡(jiǎn)單,如果對(duì)安全性有更高的需求,可以從圖片本身結(jié)構(gòu)入手,比如通過你要加密的信息構(gòu)造出RGB、alpha等信息,然后按照標(biāo)準(zhǔn)png/jpg/bmp等格式構(gòu)造出一張全新的圖片,也可以在中間按照某種規(guī)則穿插一些混淆數(shù)據(jù)。這樣生成的圖片加密程度較高,不容易破解,但相對(duì)來說開發(fā)成本較高。
消費(fèi)安全圖片

目前我們的方案中,用戶拿到包含密文和密鑰的安全圖片之后,需要把安全圖片導(dǎo)入工程文件中(圖片可以正常使用),然后由安全SDK獲取圖片中的密鑰及密文,用密鑰解密密文后,獲取用戶所需要的信息。這里的過程基本就是安全圖片生成流程的一個(gè)反向過程。
不過和圖片生成流程不同的是,安全SDK同時(shí)需要考慮SDK本身的安全性,所需要做一些額外的事情,比如:
- 檢測(cè)APP是否被二次打包
- 檢測(cè)是否正在被調(diào)試
- SDK關(guān)鍵方法混淆
- 使用c/c++增加逆向成本
限于篇幅,這里暫不展開討論。
使用
使用工具生成安全圖片
我們的工具是基于h5和node構(gòu)建的,入口放在了內(nèi)部移動(dòng)門戶上,使用非常方便。
界面如圖:

只需要填入對(duì)應(yīng)的BundleID(SHA1)/Key/Value,再傳入一張APP中用到的圖片,工具就會(huì)根據(jù)傳入信息生成安全圖片,并讓用戶下載至本地。
使用安全圖片獲取KEY
整合SDK到APP中,并導(dǎo)入安全圖片后,SDK的使用方式非常簡(jiǎn)單,直接在APP中調(diào)用如下代碼,即可獲取所需key對(duì)應(yīng)的value:
String value = SecuritySDK.get(String key);
總結(jié)
本文闡述了我們實(shí)現(xiàn)安全圖片方案的基本思路,以及安全圖片方案的流程。當(dāng)然,其中還有一些具體實(shí)現(xiàn),以及我們?nèi)晕赐瓿傻?jì)劃去完善的東西,包括但不僅限于以下:
- 包加固,APP加固
- 混淆的解決方案
- 防調(diào)試的方法
- 防逆向的方法
- 安全環(huán)境監(jiān)測(cè)/風(fēng)險(xiǎn)控制/設(shè)備指紋
- 等等
這些在短短的一篇博客中都難以詳盡表述,所以會(huì)在后續(xù)的文章中,再一一和大家詳細(xì)說明,共同探討。也歡迎各位不吝賜教,暢所欲言,發(fā)表自己的意見和感想。