最近在看HTTPS,其核心還是基與Rsa加密的SSL/TSL,所以整理一下在Android開發(fā)中常見的幾種加密方式
- MD5
- BASE64
- AES
- DES
- RSA
- SSL/TSL
MD5加密
MD5英文全稱Message-Digest Algorithm 5
,全稱消息算法摘要,是一種不可逆加密方式
特點
- 壓縮性:任意長度的數(shù)據(jù)椰于,算出的MD5值長度都是固定的洞豁。
- 容易計算:從原數(shù)據(jù)計算出MD5值很容易影兽。
- 抗修改性:對原數(shù)據(jù)進行任何改動坤溃,哪怕只修改1個字節(jié)播揪,所得到的MD5值都有很大區(qū)別徒爹。
- 強抗碰撞:已知原數(shù)據(jù)和其MD5值苍柏,想找到一個具有相同MD5值的數(shù)據(jù)(即偽造數(shù)據(jù))是非常困難的宜岛。
因為其特點,MD5加密通常用來驗證文件的完整性,防串改.
實現(xiàn)
在Java中提供了MessageDigest類來加密數(shù)據(jù).
byte[] resource; //需要加密的數(shù)據(jù)
MessageDigest md5=MessageDigest.getInstance("MD5");
byte[] bytes=md5.digest(resource);
StringBuilder builder=new StringBuilder(bytes.lenght);
for (byte byte :bytes ) {
String temp = Integer.toHexString(b & 0xff);
if (temp.lenght==1) {
builder.append(0);
}
builder.append(temp);
}
String MD5=builder.toString();
MD5加密是對字節(jié)數(shù)組進行操作的.所以無論加密文件或是其它都需要先轉(zhuǎn)換為字節(jié)數(shù)組.加密后的結(jié)果也是字節(jié)數(shù)組.
為了方便查看,需要按規(guī)定轉(zhuǎn)換為字節(jié)數(shù)組.
BASE64
BASE64并不是一種加密方式,而是對字節(jié)數(shù)組的一種編碼方式.實際上是讓字節(jié)數(shù)據(jù)轉(zhuǎn)換為文本的方案.
原理
BASE64是把字節(jié)數(shù)據(jù)轉(zhuǎn)換為ASC碼中對應(yīng)的64個字符(英文大小寫,+及/).
轉(zhuǎn)換方式為每6位字節(jié)對應(yīng)一個字符.不足位的后面補0.6位字節(jié)轉(zhuǎn)換為十進制數(shù)值.范圍是0-63,對應(yīng)64個字符.如果有不足位的,在編碼后會補上數(shù)量對應(yīng)的=
用處
- 統(tǒng)一編碼方式,不需要考慮字符集對數(shù)據(jù)的影響
- 可以把任何文件或數(shù)據(jù)都以紡一的文本方式保存
實現(xiàn)
在Java中提供了Base64類來實現(xiàn)編碼轉(zhuǎn)換
//編碼
String encode= Base64.encode(byte[] bytes,int flag);
//解碼
byte[] decode=Base64.decode(byte[] bytes,int flag);
flag表示編碼方式,通常使用Base64.DEFAULT
-
Base64.DEFAULT
默認(rèn)的編碼方式 -
Base64.NO_PADDING
忽略后綴的=號 -
Base64.NO_WRAP
省略換行符 -
Base64.CTRL
使用微軟的換行符,而不是Liunux的 -
Base64.URL_SAFE
使用-和_
代替+和/
以保證在URL的安全.通常用與網(wǎng)絡(luò)傳輸
AES
Advanced Encryption Standard
,全稱為高級加密標(biāo)準(zhǔn),又稱為 Rijndael 加密法,使用的是區(qū)塊加密方案.
區(qū)塊加密方案是把一定數(shù)量的字節(jié)劃分為一個區(qū)塊,把區(qū)塊內(nèi)的數(shù)據(jù)加密成相同位數(shù)的數(shù)據(jù)
AES是一種對稱加密方案,所以需要加密端和解密端都使用相同的密鑰.
特點
- 區(qū)塊 AES是對字節(jié)數(shù)組按區(qū)塊劃分,對區(qū)塊進行加密.AES區(qū)塊大小固定為128位.
- 密鑰 AES的密鑰長度有三種,128位/192位/256位 位數(shù)越多安全性越高.
- 矩陣 AES每次對區(qū)塊中的16個字節(jié)進行操作,這4個字節(jié)會組成一個4x4的矩陣.
- 回合密鑰 AES對每個矩陣的操作時都會根據(jù)密鑰生成一個16位的回合密鑰.對應(yīng)矩陣上的每一個字節(jié)
實現(xiàn)
在Java中通過MessageDigest來進行AES加解密
//密鑰原數(shù)據(jù)字符串,兩端必須一樣,128位的密鑰字符串長度必須為16
private static final String KEY=""
//加密方式,AES表示AES加密,CBC表示區(qū)塊的處理方式,PKC5Padding表示區(qū)塊的填充方式.
private static final String MODE="AES/CBC/PKCS5Padding"
//生成密鑰
KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY);
SecretKey secretKey = keyGenerator.generateKey();
//初始化密碼處理類
Cipher cipher = Cipher.getInstance(MODE);
cipher.init(Cipher.ENCRIPT_MODE,secretKey); //第一個參數(shù)為模式,ENCRIPT_MODE為加密, DECRIPT為解密
//cipher.init(Cipher.DECRIPT_MODE,secretKey,"BC"); 使用`PKCS7Padding`方式時需要加載bouncycastle包,BC為提供該填充方式的Provicer
byte[] date=cipher.doFinal(byte[] data); //加密和解密都是同一個方法,由初始化的模式?jīng)Q定.對源字節(jié)數(shù)組進行處理.生成新的字節(jié)數(shù)組.
填充方式有幾種.Java6沒有實現(xiàn)所有的填充方式.
-
NoPadding,PKCS5Padding,ISO10126Padding
Java6實現(xiàn) -
PKCS7Padding,ZeroBytePadding
需要加載bouncycastle
包
生成密鑰時,getInstance()
有個重載的方法可以添加一個provier.為密鑰添加一個隨機數(shù).
AES加密安全性高,速度快.
DES
Data Encryption Standard
,標(biāo)準(zhǔn)加密算法.使用64位密鑰的對稱加密.使用的也是區(qū)塊加密方案.
因為是64位密鑰,安全性不高,現(xiàn)已經(jīng)被AES加密替代.
實現(xiàn)方法同AES加密,只需要把MODE中的AES
改為DES
RSA
目前使用最廣泛的非對稱加密.生成一對密鑰--公鑰和私鑰.公鑰對來對外提供.私鑰只有密鑰生成者自己擁有
非對稱算法需要指定密鑰長度,越長安全性越好,但加解密的速度就越慢.通常指定1024或2048.
一次加密的的密文長度為密鑰長度/8-11,所以1024長度的密鑰一次只能加密117字節(jié).2048能加密245字節(jié).
所以非對稱加密通常只用與短數(shù)據(jù)加密,如簽名或?qū)ΨQ加密的密鑰.
RSA加密都是一用與一對多的場景.
RSA有兩種使用方式
- 加密算法
公鑰加密,只有私鑰才能解密 - 簽名算法
私鑰簽名,只有公鑰才能驗證.
如Github使用的SSH登錄就是使用的RSA加密算法.用戶把公鑰保存到服務(wù)器,
通過SSH登錄時服務(wù)器發(fā)一個隨機數(shù)給客戶端,客戶端使用私鑰加密發(fā)送到服務(wù)器,服務(wù)器用保存的公鑰解密.
RSA的密鑰的產(chǎn)生
- 隨機獲取兩個大質(zhì)數(shù),得其積N
- 獲取N的歐拉函數(shù)值->整數(shù)R
- 隨機獲取一個小與R并與之互質(zhì)的整數(shù)E,計算出E的反模元素D
- 公鑰是(N,E),私鑰是(N,D)
RSA的原理
- 歐拉定理
兩個互質(zhì)的正整數(shù),A和N,N的歐拉函數(shù)為P,則A的P次方除以N余1 - 費馬小定理(RSA算法核心)
因為質(zhì)數(shù)P的歐拉函數(shù)為P-1,所以一個整數(shù)A和一個質(zhì)數(shù)N互質(zhì)時,A的N-1次方除以N余1 - 反模元素
兩個互質(zhì)的正整數(shù).A和N,則一定存在一個整數(shù)B,使得A乘B除以N余數(shù)為1
實現(xiàn)
定義常量
private static final KEY_SIZE=1024;
private static final RSA="RSA";
private static final MODE="RSA/ECB/PCKS1Padding"
這里注意RSA的加密填充方式,需要兩端保持一至.
在Adrioid中默認(rèn)使用的是RSA/None/NoPadding
,在Java中使用的是RSA/None/PCKS1Padding
.
創(chuàng)建密鑰
KeyPairGenerator rsa = KeyPairGenerator.getInstance(RSA);
rsa.initialize(KEY_SIZE);
KeyPair keyPair = rsa.generateKeyPair();
Key publicKey = keyPair.getPublic();
byte[] publicKeyEncoded = publicKey.getEncoded();
Key privateKey = keyPair.getPrivate();
byte[] privateKeyEncoded = privateKey.getEncoded();
把字節(jié)數(shù)組轉(zhuǎn)換為Key
公鑰會以字節(jié)數(shù)組的形式公開.接收方需要把字節(jié)數(shù)據(jù)轉(zhuǎn)化為公鑰
//公鑰公開的方式為X509
KeySpec KeySpec = new X509EncodedKeySpec(publicKeyEncoded);
PublicKey publicKey = keyFactory.generatePublic(keySpec);
//私鑰公開的方式為PKCS8
KeySpec keySpec = new PKCS8EncodedKeySpec(publicKeyEncoded);
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
加解密
通常使用公鑰加密,使用私鑰解密.還是使用Cipher
類
Cipher cipher=Cipher.instance(MODE);
//使用公鑰加密
cipher.init(Cipher.ENCRIPT_MODE,publicKey);
cipher.doFinal();
//使用私鑰解密
cipher.init(Cipher.DECRIPT_MODE,privateKey);
cipher.doFinal();
SSL
安全套接字(Secure Socket Layer,SSL)協(xié)議是Web瀏覽器與Web服務(wù)器之間安全交換信息的協(xié)議囱怕,提供兩個基本的安全服務(wù):鑒別與保密霍弹。
- 鑒別 可選的客戶端認(rèn)證及強制的服務(wù)端認(rèn)證
- 保密 雙方在連接時定義好加密方式,所有傳遞內(nèi)容都會加密.
SSL是間與應(yīng)用層與TCP層.應(yīng)用數(shù)據(jù)經(jīng)過SSL層加密并加上SSL頭傳輸給TCP層.
SSL通信流程
- 握手
握手是在兩端連接后數(shù)據(jù)傳輸前的協(xié)議行為,通過三次握手確定雙方的身份,雙方的加密方式,以及確定密鑰.這個握手過程是通過RAS加密及身份證書完成的. - 加密通信
完成握手協(xié)議手,雙方就按確定的加密方式以對稱加密的方式對數(shù)據(jù)進行加密
握手協(xié)議
- 客戶端發(fā)送至服務(wù)器 一個會話ID,自身SSL版本.一個32位隨機數(shù).一自身支持的密碼套件列表.一個hello.
- 服務(wù)器接收后會根據(jù)客戶端提供的列表選擇一個密碼套件,確定與客戶端之間的加密方式
- 服務(wù)器發(fā)送至客戶端 會話ID,SSL版本,一個32位隨機數(shù),一個密碼套件.一個servieHello.及自己的證書.
- 客戶端收到證書后可以對證書進行驗證.然后生成一個32位隨機數(shù).這樣總共就有三個隨機數(shù)了.根據(jù)服務(wù)端確定的加密方式用這三個隨機數(shù)生成密鑰.然后從證書中獲得服務(wù)端的公鑰對第三個隨機數(shù)加密
- 客戶端發(fā)送至服務(wù)器 加密的第三個隨機數(shù).
- 服務(wù)器收到加密的隨機數(shù)后使用私鑰解密,然后使用三個隨機數(shù)生成密鑰.
- 服務(wù)器發(fā)送至客戶端 準(zhǔn)備完成,可以開始加密通信
證書
證書是一臺服務(wù)器對外提供的一個身份證明.需要通過可靠的第三方認(rèn)證機構(gòu)(CA)來發(fā)布.
一個數(shù)字證書通常有以下幾項
- 證書持有者的公鑰
- 證書的發(fā)布機構(gòu)
- CA的簽名
- 簽名摘要的算法
證書的驗證
一般的瀏覽器都會有CA根證書,含有所有CA的公鑰
- CA驗證 CA根證書中找到不證書的發(fā)布機構(gòu)
- CA簽名摘要驗證 使用CA的公鑰來解密簽名摘要,如果解不開說明證書不對
- CA簽名驗證 使用公鑰解密簽名.然后使用簽名摘要算法進行簽名摘要,比對解密手的簽名摘要.如果不同說明簽名被更改
- 證書過期驗證 實現(xiàn)了在線證書狀態(tài)協(xié)議(OCSP)的客戶端可以在線查詢證書是否過期
TSL
TLS 1.0是IETF(Internet Engineering Task Force,Internet工程任務(wù)組)制定的一種新的協(xié)議娃弓,它建立在SSL 3.0協(xié)議規(guī)范之上典格,是SSL 3.0的后續(xù)版本,可以理解為SSL 3.1