做網(wǎng)絡(luò)框架,勢(shì)必要與http請(qǐng)求打交道,那么加密策略也是各大公司必不可少的部分。這篇文章我來(lái)總結(jié)下我接觸過(guò)的加密算法和策略。
一、基礎(chǔ)
首先http協(xié)議本身存在安全性問(wèn)題,主要為如下幾點(diǎn):
-
數(shù)據(jù)隱私性:通信使用明文、內(nèi)容可能被竊取。 -
數(shù)據(jù)完整性:無(wú)法證明報(bào)文完整性,內(nèi)容可能遭篡改。 -
身份認(rèn)證:不驗(yàn)證通信方身份,可能遭遇偽裝。
因此要解決這些問(wèn)題,就引入了加密。那么目前加密主要分兩大類:
-
自定義:說(shuō)白了就是跟服務(wù)端約定好加解密方案和規(guī)則,對(duì)請(qǐng)求和響應(yīng)進(jìn)行加密,防止明文裸奔,同時(shí)做好完整性認(rèn)證和身份認(rèn)證。 -
三方:用https,https在http基礎(chǔ)上增加了ssl加密層,對(duì)傳輸數(shù)據(jù)幫你做好了加解密,通過(guò)購(gòu)買證書(shū)、添加證書(shū)記錄、頒發(fā)證書(shū)后上傳來(lái)完成域名https化就行??蛻舳酥恍枰渲孟戮W(wǎng)絡(luò)庫(kù)去支持https,目前volley和okhttp都支持https。
二、加密算法
好,那么不管是自定義還是三方方案,都會(huì)用到加密算法,那么基本加密算法還是有必要了解下。
2.1 簽名和加密
A向B發(fā)送信息,數(shù)據(jù)簽名是讓B確認(rèn)信息是A發(fā)送的,不是別人。而數(shù)據(jù)加密保證數(shù)據(jù)不能被除B之外的其他人獲取到。
2.2 加密算法
1)對(duì)稱性加密算法
加密和解密使用同一個(gè)密鑰(私鑰),信息接收雙方都需事先知道密匙和加解密算法。
AES 高級(jí)加密標(biāo)準(zhǔn),又稱Rijndael加密法,是美國(guó)聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)。
-
ECB模式 (Electronic Codebook Book)將整個(gè)明文分成若干段相同的小段,然后對(duì)每一小段進(jìn)行加密。 -
CBC模式(Cipher Block Chaining)先將明文切分成若干小段,然后每一小段與初始?jí)K或者上一段的密文段進(jìn)行異或運(yùn)算后,再與密鑰進(jìn)行加密。
優(yōu)點(diǎn):加解密速度快、效率高。
缺點(diǎn):對(duì)稱加密時(shí),都需要使用其他人不知道的唯一秘鑰,密鑰數(shù)量巨大,管理和分發(fā)非常困難,秘鑰一旦泄露,加密信息就不安全了。
作用:對(duì)傳輸明文加解密。
2)非對(duì)稱加密算法
加密和解密所使用的不是同一個(gè)密鑰,通常有兩個(gè)密鑰,稱為"公鑰"和"私鑰",它們兩個(gè)必需配對(duì)使用,否則不能打開(kāi)加密文件。雙方分別生成公私鑰,公鑰給對(duì)方,私鑰自己保留。拿對(duì)方的公鑰向?qū)Ψ桨l(fā)送加密信息,對(duì)方拿私鑰解密。
RSA 目前主流的非對(duì)稱加密算法。
優(yōu)點(diǎn):秘鑰管理方便,安全性高。
缺點(diǎn):加解密過(guò)程復(fù)雜,耗時(shí)長(zhǎng),只適合對(duì)少量數(shù)據(jù)加密。
數(shù)據(jù)加密:任何發(fā)送方都可以用接收方的公鑰加密,接收方用對(duì)應(yīng)的私鑰解密。
數(shù)據(jù)簽名:用發(fā)送方的私鑰加密,任何接收方都可以用發(fā)送方公鑰解密。
3)散列算法/哈希算法
一種單向加密算法,過(guò)程不可逆。
MD5 信息摘要算法。把任意數(shù)據(jù)轉(zhuǎn)換為定長(zhǎng)(或限制長(zhǎng)度)的數(shù)據(jù),
SHA1 也是一種哈希算法,與md5類似。SHA1摘要比md5長(zhǎng)32位,安全性更好,但是運(yùn)算步驟要多一些,所以慢一些。
作用:進(jìn)行一致性驗(yàn)證、數(shù)字簽名、安全訪問(wèn)認(rèn)證。
4)密鑰交換方案
D-H 依賴的是:離散對(duì)數(shù)運(yùn)算。
有兩個(gè)公開(kāi)的數(shù)g和p,其中p為素?cái)?shù),g是p的一個(gè)元根。
甲:私鑰a A = g^a mod p 把A發(fā)給乙
乙:私鑰b B= g^b mod p 把B發(fā)給甲
甲:B^a mod p = Fkey
乙:A^b mod p =Skey
Fkey = Skey
只要私鑰不泄漏就行。
ECDH = ECC +DH https使用ECDH密鑰交換.
DH和ECDH的主要的作用就是在通信雙方發(fā)送一些公有參數(shù),保留私有參數(shù),而后通過(guò)一系列計(jì)算雙方都能夠得到一個(gè)一致的結(jié)果。而這個(gè)運(yùn)算的逆運(yùn)算復(fù)雜度過(guò)高,在有限時(shí)間內(nèi)不可解(至少量子計(jì)算機(jī)問(wèn)世以前不可解),以保證密鑰安全性。
5)其他算法
嚴(yán)格意義上不算加密。
Base64 一種編碼方式,用來(lái)將非ASCII字符的數(shù)據(jù)轉(zhuǎn)換成ASCII字符的一種轉(zhuǎn)換算法。
作用:便于網(wǎng)絡(luò)傳輸。
算法基本分這么四類,每一類都包含但不限于這么幾種,每類我只例舉了目前最為主流的方案,最個(gè)基本介紹。
三、加密策略
那么,介紹完加密算法,接下來(lái)談?wù)勀壳爸饕褂玫募用懿呗浴?/p>
3.1 RSA+SHA1
用SHA算法進(jìn)行簽名,用RSA算法進(jìn)行加密。
加密流程:
1)利用私鑰將請(qǐng)求參數(shù)進(jìn)行 SHA1withRSA 簽名即可。
/**
* 進(jìn)行sha1 Rsa算法簽名
* @param str
* @param privateKey
* @return
*/
public static byte[] sha1WithRsa(String str, PrivateKey privateKey) {
try {
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(privateKey);
signature.update(str.getBytes());
return signature.sign();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
2)加密完成開(kāi)始打包參數(shù)。
主要玩的是這個(gè)類:/Android/sdk/sources/android-27/java/security/Signature.java
3.2 RSA+AES
使用RSA來(lái)首先傳輸AES的密鑰給對(duì)方,然后再使用AES來(lái)進(jìn)行加密通訊。
加密流程:
1)將請(qǐng)求參數(shù)進(jìn)行AES加密。
public static byte[] encryptByAes(String data, String pass, String init,
String mode) throws Exception {
String transformation;
//選擇CBC or ECB模式
if (mode.equals(Constant.ECODE_METHOD)) {
transformation = Constant.AES_TRANSFORMATION_CBC;
} else {
transformation = Constant.AES_TRANSFORMATION_ECB;
}
try {
Cipher cipher = Cipher.getInstance(transformation);
int blockSize = cipher.getBlockSize();
...
// 將隨機(jī)生成的密碼變成AES算法的私鑰
SecretKeySpec keyspec = new SecretKeySpec(hexString2Bytes(pass),
"AES");
// ECB don't need ivspec
IvParameterSpec ivspec = new IvParameterSpec(init.getBytes());
if (mode.equals(Constant.ECODE_METHOD)) {
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
} else {
cipher.init(Cipher.ENCRYPT_MODE, keyspec);
}
byte[] encrypted = cipher.doFinal(plaintext);
return encrypted;
} catch (Exception e) {
e.printStackTrace();
return new byte[0];
}
}
2)利用私鑰將AES加密后的結(jié)果進(jìn)行RSA加密。
/**
* 進(jìn)行Rsa算法加密
* @param data 需要加密的數(shù)據(jù)
* @param privateKey 加密所需要的私鑰
* @return
*/
public static byte[] encryptByRsa(String data, PrivateKey privateKey) {
try
Cipher cipher = Cipher.getInstance(Constant.RSA_TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] encryptData = cipher.doFinal(data.getBytes());
return encryptData;
} catch (Exception e) {
e.printStackTrace();
return new byte[0];
}
}
3)加密完成開(kāi)始打包參數(shù)。
主要玩的是這個(gè)類:Android/sdk/sources/android-27/javax/crypto/Cipher.java
公司保密性原因,具體細(xì)節(jié)不便過(guò)多透露,這里了解個(gè)大概策略就行,具體加解密代碼網(wǎng)上應(yīng)該能搜到一大堆。
3.3 數(shù)據(jù)簽名
這種方案就純跟服務(wù)端去自定義你們覺(jué)得合適的加密方式來(lái)滿足明文保密、明文完整性驗(yàn)證和身份驗(yàn)證的需要。
3.4 Https
HTTPS = HTTP+SSL(TLS)。
原本HTTP和TCP/UDP直接通信,而加了SSL后,就變成HTTP先和SSL通信,再由SSL和TCP/UDP通信。
HTTPS和HTTP的主要區(qū)別:
- https協(xié)議需要到ca申請(qǐng)證書(shū),一般免費(fèi)證書(shū)較少,需要一定費(fèi)用。
- http是超文本傳輸協(xié)議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協(xié)議。
- HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全。
說(shuō)白了,https就是在http協(xié)議層面幫你做了加密。
優(yōu)點(diǎn):加密傳輸、身份認(rèn)證、安全性高。
缺點(diǎn):
- HTTPS協(xié)議握手階段比較費(fèi)時(shí),會(huì)使頁(yè)面的加載時(shí)間延長(zhǎng),同時(shí)增加耗電;(這個(gè)沒(méi)驗(yàn)證過(guò)具體程度)
- 證書(shū)需要一定費(fèi)用。
- 加密和證書(shū)都依賴第三方,存在風(fēng)險(xiǎn)。
Https也是對(duì)稱加密和非對(duì)稱加密結(jié)合的方式。
https流程解析:

client -> http請(qǐng)求 ->server
server ->證書(shū)(公鑰、私鑰)->公鑰->client
client ->TLS驗(yàn)證公鑰有效- 生成隨機(jī)數(shù)用公鑰加密生成私鑰 ->server
server->用隨機(jī)數(shù)私鑰對(duì)明文進(jìn)行對(duì)稱加密 -> client
client ->隨機(jī)數(shù)私鑰對(duì)明文解密->server
各加密算法在https中的作用:
CA證書(shū):由它生產(chǎn)的公鑰能確認(rèn)服務(wù)端正確性,防止中間人攻擊。
AES:明文加密,但是加密效率高,但是密鑰不安全。
RSA:保證AES密鑰安全性。
DH/ECDH:向前安全。
注:只要 rsa 私鑰被破解了,就可以解開(kāi)以前的信息的對(duì)稱密鑰,然后就破解了以前的信息。
而 DH 是當(dāng)時(shí) client 和 server 共同算出的對(duì)稱密鑰,即時(shí) rsa 私鑰被破解,以往的信息仍然是安全的。
四、實(shí)戰(zhàn)
