如何保證APP與服務(wù)端通信安全?4個(gè)技巧給你的數(shù)據(jù)加把鎖
最近公司外包給別人做的一個(gè)APP項(xiàng)目上線了,拿到源碼一看那代碼質(zhì)量真是一言難盡啊!
剛上線用戶比較少倒也沒出啥問題,不過隨著用戶慢慢變多,問題逐漸暴露出來了。
最嚴(yán)重的問題就是我們的APP與服務(wù)器的通信接口沒有加密處理被人抓包了,有人非法請(qǐng)求我們的接口獲取數(shù)據(jù)。
怎么處理這個(gè)問題呢?領(lǐng)導(dǎo)又把這個(gè)光榮而艱巨的任務(wù)分給了我,沒辦法只能硬著頭皮上啊,經(jīng)過幾天摸索終于總結(jié)出了一套還算安全的APP與服務(wù)端通信的機(jī)制。
1.防非法調(diào)用——身份認(rèn)證
身份認(rèn)證指只有經(jīng)過合法授權(quán)的用戶才能調(diào)用我們的接口,這里我們采用的是Token驗(yàn)證機(jī)制。
APP與服務(wù)端的整個(gè)通信過程如下:
- 用戶首先需要輸入賬號(hào)密碼進(jìn)行登錄;
- APP帶上用戶輸入的賬號(hào)密碼請(qǐng)求服務(wù)端登錄接口;
- 服務(wù)端校驗(yàn)賬號(hào)密碼,校驗(yàn)成功返回一個(gè)唯一Token作為用戶身份憑證;
- APP將Token緩存,同時(shí)登錄成功;
- 用戶使用APP瀏覽數(shù)據(jù),APP每次向服務(wù)端請(qǐng)求數(shù)據(jù)時(shí)須同時(shí)帶上緩存的Token;
- 服務(wù)端收到請(qǐng)求,首先會(huì)校驗(yàn)Token的合法性,校驗(yàn)成功正常返回?cái)?shù)據(jù),校驗(yàn)失敗直接返回錯(cuò)誤。
(1) Token驗(yàn)證機(jī)制解決了什么問題?
設(shè)想一個(gè)場(chǎng)景,我們檢測(cè)到API接口正在被惡意調(diào)用,因?yàn)樗械慕涌诙急仨殠oken才能調(diào)用,根據(jù)Token我們就能快速反查到對(duì)應(yīng)的用戶,所以Token驗(yàn)證機(jī)制可以幫助我們快速確定調(diào)用者的身份。
發(fā)現(xiàn)惡意調(diào)用,我們通過Token確定調(diào)用者的身份后可以采取Token失效、封禁帳號(hào)等措施來阻止惡意調(diào)用繼續(xù)。
(2) Token驗(yàn)證機(jī)制能防止抓包嗎?
Token驗(yàn)證機(jī)制并不能防止APP被抓包,因?yàn)門oken同樣存在泄露的風(fēng)險(xiǎn),惡意調(diào)用者只需要帶上Token再請(qǐng)求我們的API接口同樣還是能獲取到數(shù)據(jù)。
因?yàn)锳PP與服務(wù)端都是明文通信,一抓包就能看到請(qǐng)求參數(shù)以及返回?cái)?shù)據(jù),所以為了防止被抓包我們必須要對(duì)數(shù)據(jù)進(jìn)行加密處理。
2.防抓包——數(shù)據(jù)加密
數(shù)據(jù)加密的過程,就是對(duì)原來明文傳輸?shù)臄?shù)據(jù)按某種加密算法進(jìn)行加密處理,使其成為不可讀無意義的密文。
加密算法大體上可分為對(duì)稱加密、非對(duì)稱加密和散列算法等幾種方式,后面我們的方案都會(huì)涉及到。
(1) 對(duì)稱加密
對(duì)稱加密是一種可逆的加密算法,其中“對(duì)稱”的意思是加密過程和解密過程使用的是同一個(gè)密鑰。
常見的對(duì)稱加密算法有DES、3DES、AES、IDEA等。
使用對(duì)稱加密算法一次完整的加解密過程為:
- APP與服務(wù)端事先約定好對(duì)稱加密的密鑰,各自保存;
- APP使用密鑰將明文參數(shù)加密,再將密文發(fā)送到服務(wù)端;
- 服務(wù)端收到密文后使用同樣的密鑰對(duì)密文進(jìn)行解密操作得到明文;
- 服務(wù)端同樣需要對(duì)數(shù)據(jù)進(jìn)行加密之后才能返回給APP;
對(duì)稱加密算法的特點(diǎn):
- 對(duì)稱加密算法的特點(diǎn)是算法公開、計(jì)算量小、加密速度快、加密效率高。對(duì)稱加密算法的安全性依賴于密鑰,任何人只要拿到密鑰就能對(duì)數(shù)據(jù)進(jìn)行加解密操作。
- 由于參與通信的雙方都需要持有密鑰,任何一方的秘鑰泄露,那么雙方的通信將無安全性可言,所以怎么安全的保存和傳遞密鑰是使用對(duì)稱加密最需要關(guān)注的問題。
(2) 非對(duì)稱加密
顧名思義非對(duì)稱加密指的是加密過程和解密過程使用不同的密鑰,非對(duì)稱加密算法需要一對(duì)密鑰(公鑰和私鑰),公鑰用來加密數(shù)據(jù)、私鑰用來解密數(shù)據(jù)。
常見的非對(duì)稱加密算法有RSA、ECC、ElGamal等。
非對(duì)稱加密一次完成的加解密過程為:
- APP和服務(wù)端各自生成一對(duì)密鑰對(duì)(公鑰和私鑰),公鑰分別給到對(duì)方、私鑰自己保存;
- APP使用服務(wù)端的公鑰對(duì)數(shù)據(jù)進(jìn)行加密,然后將加密后的密文發(fā)送到服務(wù)端;
- 服務(wù)端收到密文后使用自己的私鑰進(jìn)行解密得到明文數(shù)據(jù);
- 服務(wù)端返回?cái)?shù)據(jù)同樣需要使用APP的公鑰對(duì)數(shù)據(jù)進(jìn)行加密;
非對(duì)稱加密算法特點(diǎn):
- 非對(duì)稱加密算法使用公鑰加密、私鑰解密,私鑰不需要公開傳輸所以安全性較高。同時(shí)私鑰可以對(duì)數(shù)據(jù)進(jìn)行簽名、公鑰可以用來驗(yàn)證簽名,可以解決中間人攻擊和信息被篡改的問題。
- 由于加解密過程使用不同的密鑰,所以對(duì)大量數(shù)據(jù)進(jìn)行加解密運(yùn)算的話速度是比較慢的,通常情況下非對(duì)稱加密算法只適合對(duì)少量數(shù)據(jù)進(jìn)行加解密操作。
對(duì)稱加密算法運(yùn)算速度快但安全性不足、非對(duì)稱加密算法安全性高但運(yùn)算速度慢,那么我們的數(shù)據(jù)加密方案采用哪種加密算法呢?
既然兩種加密算法都有優(yōu)缺點(diǎn),那我們可以將兩者結(jié)合一下:用對(duì)稱加密算法加解密數(shù)據(jù)這樣可以保證運(yùn)算速度,用非對(duì)稱加密算法加密對(duì)稱加密算法的密鑰這樣可以兼顧密鑰的安全性。
3.防重放攻擊——時(shí)間戳+隨機(jī)字符串
數(shù)據(jù)加密之后再進(jìn)行通信雖然抓包之后看不到明文數(shù)據(jù)了,但是這并不能阻止不懷好意之人發(fā)起重放攻擊。
攔截到請(qǐng)求之后只需再原樣發(fā)送該請(qǐng)求到服務(wù)端就可以發(fā)起重放攻擊,如果接口內(nèi)有一些查庫之類的比較耗性能的邏輯,那么在短時(shí)間內(nèi)發(fā)起大量重放攻擊的話將會(huì)直接導(dǎo)致服務(wù)端崩潰。
怎么解決這個(gè)問題?
道理其實(shí)很簡單,我們只需要保證請(qǐng)求只能被正確處理一次即可,這里我們采用時(shí)間戳+隨機(jī)字符串的解決方案。
(1) 時(shí)間戳
我們?cè)诎l(fā)送的數(shù)據(jù)里加入當(dāng)前的時(shí)間戳,服務(wù)端在收到請(qǐng)求數(shù)據(jù)后首先取出時(shí)間戳與服務(wù)器當(dāng)前時(shí)間進(jìn)行比較,如果兩者相差超過一定時(shí)間(比如5分鐘),那么我們就認(rèn)為本次請(qǐng)求超時(shí),直接拒絕執(zhí)行或返回錯(cuò)誤就可以。
(2) 隨機(jī)字符串
我們?cè)诎l(fā)送的數(shù)據(jù)中加入一個(gè)隨機(jī)生成的字符串,服務(wù)端在收到請(qǐng)求數(shù)據(jù)后首先在緩存中查找該字符串,如果在緩存中找到則認(rèn)為這是一次重復(fù)請(qǐng)求直接拒絕處理,否則將該字符串加入緩存并繼續(xù)執(zhí)行正確邏輯。
在請(qǐng)求中加入時(shí)間戳與隨機(jī)字符串之后,服務(wù)端收到請(qǐng)求后會(huì)首先對(duì)時(shí)間戳和隨機(jī)字符串進(jìn)行校驗(yàn),校驗(yàn)通過才會(huì)執(zhí)行正常的業(yè)務(wù)處理邏輯。
4. 防篡改——數(shù)字簽名
為了防重放攻擊,我們?cè)跀?shù)據(jù)中加入了時(shí)間戳與隨機(jī)字符串,但是別人在攔截到我們的請(qǐng)求之后也可以對(duì)時(shí)間戳和隨機(jī)字符串進(jìn)行篡改,面對(duì)這種情況服務(wù)端要怎么分辨呢?
為了防止數(shù)據(jù)在傳輸過程中被篡改,我們引入數(shù)字簽名機(jī)制。
(1) 信息摘要算法
信息摘要算法(或者叫散列算法)是一種不可逆算法,任意長度的明文數(shù)據(jù)經(jīng)過信息摘要算法計(jì)算后都可以得出一個(gè)固定長度的值(簽名)。
常見的信息摘要算法有MD5、SHA-1等。
詳細(xì)的簽名過程:
- 將數(shù)據(jù)密文、時(shí)間戳、隨機(jī)字符串以及私密的加鹽值一起進(jìn)行信息摘要算法計(jì)算得到簽名值;
- APP將數(shù)據(jù)密文、時(shí)間戳、隨機(jī)字符串以及簽名值一起發(fā)往服務(wù)端;
- 服務(wù)端收到數(shù)據(jù)后對(duì)數(shù)據(jù)密文、時(shí)間戳、隨機(jī)字符串以及加鹽值一起進(jìn)行同樣的信息摘要算法計(jì)算,將計(jì)算出的簽名與數(shù)據(jù)中簽名進(jìn)行對(duì)比,簽名一致證明沒有沒有被篡改;
(2) 為什么進(jìn)行信息摘要計(jì)算要“加鹽”?
舉個(gè)例子就明白了,比如說123經(jīng)過MD5計(jì)算后的簽名值是abc,那么就會(huì)產(chǎn)生123->abc這樣的對(duì)應(yīng)關(guān)系,看到簽名值abc我就能反查到原值為123。如果有人收集并保存了足夠多的這種對(duì)應(yīng)關(guān)系,那么就有可能從簽名值反推出原值。
這個(gè)時(shí)候加鹽操作就派上了用場(chǎng),首先我們生成一個(gè)加鹽值qwe,這個(gè)加鹽值qwe并不會(huì)在網(wǎng)絡(luò)傳輸,只有通信雙方自己知道。
我們不直接計(jì)算123的簽名值,我們將加鹽值附加到123的后面得到123qwe,接著我們對(duì)123qwe進(jìn)行MD5計(jì)算得到一個(gè)不一樣的簽名值def。
所以說即使原值一樣,但只要加鹽值不同那么最后得到簽名值就不一樣,這樣也就無法從簽名值反推出原值了。
5.完整的Java解決方案
因?yàn)槲抑饕鉐ava開發(fā),所以就用Java語言實(shí)現(xiàn)了一套加解密方案,對(duì)稱加密采用AES算法、非對(duì)稱加密采用RSA算法,信息摘要算法采用MD5算法。
完整代碼執(zhí)行流程:
下面分步驟進(jìn)行詳細(xì)介紹:
準(zhǔn)備工作:APP與服務(wù)端各自生成一對(duì)RSA密鑰對(duì)(公鑰和私鑰),公鑰給到對(duì)方、私鑰各自私密保存;
APP發(fā)送加密數(shù)據(jù)流程:
- 生成一個(gè)隨機(jī)的AES算法密鑰;
- 使用服務(wù)端的RSA公鑰對(duì)AES密鑰明文進(jìn)行加密得到AES密鑰密文;
- 對(duì)參數(shù)明文進(jìn)行AES加密得到參數(shù)密文;
- 生成當(dāng)前請(qǐng)求時(shí)間的時(shí)間戳;
- 為該次請(qǐng)求生成一個(gè)隨機(jī)字符串;
- 將參數(shù)密文、時(shí)間戳、隨機(jī)字符串和AES密鑰密文進(jìn)行MD5計(jì)算得到md5值;
- 使用APP自己的RSA私鑰對(duì)md5值進(jìn)行簽名得到簽名值;
- 將參數(shù)密文、時(shí)間戳、隨機(jī)字符串、AES密鑰密文和簽名值一起發(fā)送到服務(wù)端;
服務(wù)端解密數(shù)據(jù)流程:
- 校驗(yàn)時(shí)間戳與服務(wù)器當(dāng)前時(shí)間的差值是否在合理的區(qū)間,超過則認(rèn)為該次請(qǐng)求超時(shí);
- 校驗(yàn)隨機(jī)字符串是否已經(jīng)在緩存中,如果已經(jīng)在緩存中說明該次請(qǐng)求為重復(fù)請(qǐng)求,否則將該字符串加入緩存;
- 從收到的數(shù)據(jù)中取出參數(shù)密文、時(shí)間戳、隨機(jī)字符串和AES密鑰密文進(jìn)行MD5計(jì)算得到md5值;
- 使用APP的RSA公鑰對(duì)計(jì)算得到的md5值和請(qǐng)求數(shù)據(jù)中的簽名值進(jìn)行驗(yàn)證,簽名驗(yàn)證通過則說明請(qǐng)求數(shù)據(jù)沒有被篡改;
- 服務(wù)端使用自己的RSA私鑰解密AES密鑰密文得到AES密鑰明文;
- 使用AES密鑰明文對(duì)參數(shù)密文進(jìn)行AES解密操作得到參數(shù)明文;
- 拿到參數(shù)明文之后進(jìn)行正常的業(yè)務(wù)處理邏輯;
- 服務(wù)端數(shù)據(jù)需要經(jīng)過同樣的加密操作之后才能返回給APP;
6.總結(jié)
APP與服務(wù)端肯定是要使用HTTPS協(xié)議進(jìn)行通信的,再搭配上RAS+AES混合加密算法以及數(shù)字簽名機(jī)制,相信這套方案在絕大部分情況下是可以保證通信及數(shù)據(jù)安全的。
當(dāng)然了,不排除APP有被人破解的可能,這種情況下任何加密機(jī)制都是白搭。但是不能說我們的加密機(jī)制就沒用了,我們只需要將破解我們APP的成本提高到一定程度就可以了。
這個(gè)道理其實(shí)就跟門鎖一樣,市面上絕大部分門鎖只要有時(shí)間都可以被開鎖的人打開,那你能說門鎖就沒有存在的意義了嗎?