這兩天在整理網(wǎng)絡(luò)請(qǐng)求加密相關(guān)的知識(shí),發(fā)現(xiàn)有篇文章總結(jié)的很不錯(cuò)絮供,轉(zhuǎn)載一下硫戈,整體知識(shí)結(jié)構(gòu)如原作者文章所述,部分地方有加入自己的補(bǔ)充或修改
轉(zhuǎn)載請(qǐng)注明出處:
Android網(wǎng)絡(luò)請(qǐng)求加密機(jī)制詳解
Android開(kāi)發(fā)中罚随,難免會(huì)遇到需要加解密一些數(shù)據(jù)內(nèi)容存到本地文件玉工、或者通過(guò)網(wǎng)絡(luò)傳輸?shù)狡渌?wù)器和設(shè)備的問(wèn)題,但并不是使用了加密就絕對(duì)安全了淘菩,如果加密函數(shù)使用不正確遵班,加密數(shù)據(jù)很容易受到逆向破解攻擊。還有很多開(kāi)發(fā)者沒(méi)有意識(shí)到的加密算法的問(wèn)題潮改。
1狭郑、需要了解的基本概念
密碼學(xué)的三大作用:加密( Encryption)、認(rèn)證(Authentication)汇在,鑒定(Identification)
加密:防止壞人獲取你的數(shù)據(jù)愿阐。
鑒權(quán):防止壞人假冒你的身份。
明文趾疚、密文缨历、密鑰、對(duì)稱(chēng)加密算法糙麦、非對(duì)稱(chēng)加密算法辛孵,這些基本概念和加密算法原理就不展開(kāi)敘述了。
Base64編碼算法是一種用64個(gè)字符(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/)來(lái)表示任意二進(jìn)制數(shù)據(jù)的方法赡磅。在計(jì)算機(jī)網(wǎng)絡(luò)發(fā)展的早期魄缚,由于“歷史原因”,電子郵件不支持非ASCII碼字符焚廊,如果要傳送的電子郵件帶有非ASCII碼字符(諸如中文)或者圖片冶匹,用戶(hù)收到的電子郵件將會(huì)是一堆亂碼,因此發(fā)明了Base64編碼算法咆瘟。至于為何會(huì)亂碼嚼隘?請(qǐng)大家自行Google。在加解密算法中袒餐,原始的數(shù)據(jù)和加密后的數(shù)據(jù)一般也是二進(jìn)制數(shù)據(jù)飞蛹,為了不傳輸出錯(cuò)谤狡,方便保存或者調(diào)試代碼,一般需要對(duì)加密后的數(shù)據(jù)進(jìn)行base64編碼卧檐。
Android提供了Base64編碼的工具類(lèi)android.util.Base64墓懂,可以直接使用,不用自己去實(shí)現(xiàn)base64編碼的算法了霉囚。 如:
/**
* base64 編碼
* input: 第一個(gè)參數(shù)一般是加密后的byte型數(shù)據(jù)
* flag: 第二個(gè)參數(shù)flag是編碼解碼方式捕仔,可填多個(gè),此處表示略去換行符盈罐,還有其他幾種flag下面有詳細(xì)介紹
*/
String base64String = Base64.encodeToString(input, Base64.NO_WRAP);
/**
* base64 解碼
* output: 需要base64解碼的數(shù)據(jù)
* flag: 編碼解碼方式榜跌,同上
*/
byte[] bytes = Base64.decode(base64String , Base64.NO_WRAP);
Base64編碼方式有以下幾種:
CRLF:這個(gè)參數(shù)看起來(lái)比較眼熟,它就是Win風(fēng)格的換行符暖呕,意思就是使用CR LF這一對(duì)作為一行的結(jié)尾而不是Unix風(fēng)格的LF
DEFAULT:這個(gè)參數(shù)是默認(rèn),使用默認(rèn)的方法來(lái)編碼
NO_PADDING:這個(gè)參數(shù)是略去編碼字符串最后的“=”
NO_WRAP:這個(gè)參數(shù)意思是略去所有的換行符(設(shè)置后CRLF就沒(méi)用了)
URL_SAFE:這個(gè)參數(shù)意思是編碼時(shí)不使用對(duì)URL和文件名有特殊意義的字符來(lái)作為編碼字符苞氮,具體就是以-和_取代+和/
NO_CLOSE:這個(gè)參數(shù)意思是不關(guān)閉正在包裝的輸出流
開(kāi)發(fā)者建議: base64只是一種編碼方式湾揽,并不是一種加密算法,不要使用base64來(lái)加密數(shù)據(jù)笼吟。
要確保加密的消息不是別人偽造的库物,需要提供一個(gè)消息認(rèn)證碼(MAC,Message authentication code)贷帮。
消息認(rèn)證碼是帶密鑰的hash函數(shù)戚揭,基于密鑰和hash函數(shù)。
密鑰雙方事先約定撵枢,不能讓第三方知道民晒。
消息發(fā)送者使用MAC算法計(jì)算出消息的MAC值,追加到消息后面一起發(fā)送給接收者锄禽。
接收者收到消息后潜必,用相同的MAC算法計(jì)算接收到消息MAC值,并與接收到的MAC值對(duì)比是否一樣沃但。
開(kāi)發(fā)者建議:
建議使用HMAC-SHA256算法磁滚,避免使用CBC-MAC。
在對(duì)稱(chēng)加密算法中宵晚,數(shù)據(jù)發(fā)信方將明文(原始數(shù)據(jù))和加密密鑰一起經(jīng)過(guò)特殊加密算法處理后垂攘,使其變成復(fù)雜的加密密文發(fā)送出去。收信方收到密文后淤刃,若想解讀原文晒他,則需要使用加密用過(guò)的密鑰及相同算法的逆算法對(duì)密文進(jìn)行解密,才能使其恢復(fù)成可讀明文逸贾。在對(duì)稱(chēng)加密算法中仪芒,使用的密鑰只有一個(gè)唁影,發(fā)收信雙方都使用這個(gè)密鑰對(duì)數(shù)據(jù)進(jìn)行加密和解密,這就要求解密方事先必須知道加密密鑰掂名。
該算法的缺點(diǎn)是据沈,如果一旦密鑰泄漏,那么加密的內(nèi)容將都不可信了饺蔑。
-
DES
DES算法把64位的明文輸入塊變?yōu)?4位的密文輸出塊锌介,它所使用的密鑰也是64位
DES算法流結(jié)構(gòu)如下:
DES算法流程圖如下:
由于DES默認(rèn)使用56位加密密鑰,已經(jīng)不安全猾警,如果想要安全使用DES加密孔祸,則需要注意避開(kāi)使用第8,16,24,...64位作為有效數(shù)據(jù)位发皿,操作起來(lái)沒(méi)有那么方便崔慧,因此不是很經(jīng)常使用,對(duì)稱(chēng)加密一般使用AES加密穴墅。 -
AES
AES算法流程
對(duì)于發(fā)送方惶室,它首先創(chuàng)建一個(gè)AES私鑰,并用口令對(duì)這個(gè)私鑰進(jìn)行加密玄货。然后把用口令加密后的AES密鑰通過(guò)Internet發(fā)送到接收方皇钞。發(fā)送方解密這個(gè)私鑰,并用此私鑰加密明文得到密文松捉,密文和加密后的AES密鑰一起通過(guò)Internet發(fā)送到接收方夹界。接收方收到后再用口令對(duì)加密密鑰進(jìn)行解密得到AES密鑰,最后用解密后的密鑰把收到的密文解密成明文隘世。下圖是這個(gè)過(guò)程的實(shí)現(xiàn)流程可柿。
開(kāi)發(fā)者建議:
1、建議使用AES算法丙者。
2趾痘、DES默認(rèn)的是56位的加密密鑰,已經(jīng)不安全蔓钟,不建議使用
3永票、Android 提供的AES加密算法API默認(rèn)使用的是ECB模式,所以要顯式指定加密算法為:CBC或CFB模式滥沫,可帶上PKCS5Padding填充侣集。AES密鑰長(zhǎng)度最少是128位,推薦使用256位兰绣。
非對(duì)稱(chēng)加密算法需要兩個(gè)密鑰:公開(kāi)密鑰(publickey)和私有密鑰(privatekey)世分。公開(kāi)密鑰與私有密鑰是一對(duì),如果用公開(kāi)密鑰對(duì)數(shù)據(jù)進(jìn)行加密缀辩,只有用對(duì)應(yīng)的私有密鑰才能解密臭埋;如果用私有密鑰對(duì)數(shù)據(jù)進(jìn)行加密冯乘,那么只有用對(duì)應(yīng)的公開(kāi)密鑰才能解密(這個(gè)過(guò)程可以做數(shù)字簽名)务漩。
非對(duì)稱(chēng)加密主要使用的是RSA算法尽纽。
-
RSA
RSA算法實(shí)現(xiàn)流程
首先垒拢,接收方創(chuàng)建RSA密匙對(duì),即一個(gè)公鑰和一個(gè)私鑰荣恐,公鑰被發(fā)送到發(fā)送方,私鑰則被保存在接收方液斜。發(fā)送方在接收到這個(gè)公鑰后,用該公鑰對(duì)明文進(jìn)行加密得到密文,然后把密文通過(guò)網(wǎng)絡(luò)傳輸給接收方叠穆。接收方在收到它們后少漆,用RSA私鑰對(duì)收到的密文進(jìn)行解密,最后得到明文硼被。圖8是整個(gè)過(guò)程的實(shí)現(xiàn)流程示损。
開(kāi)發(fā)者建議:
1、注意密鑰長(zhǎng)度不要低于512位嚷硫,建議使用2048位的密鑰長(zhǎng)度检访。
RSA算法是公開(kāi)密鑰系統(tǒng)的代表,其安全性建立在具有大素?cái)?shù)因子的合數(shù)论巍,其因子分解困難這一法則之上的烛谊。Rijndael算法作為新一代的高級(jí)加密標(biāo)準(zhǔn)风响,運(yùn)行時(shí)不需要計(jì)算機(jī)有非常高的處理能力和大的內(nèi)存嘉汰,操作可以很容易的抵御時(shí)間和空間的攻擊,在不同的運(yùn)行環(huán)境下始終能保持良好的性能状勤。這使AES將安全鞋怀,高效,性能持搜,方便密似,靈活性集于一體,理應(yīng)成為網(wǎng)絡(luò)數(shù)據(jù)加密的首選葫盼。相比較残腌,因?yàn)锳ES密鑰的長(zhǎng)度最長(zhǎng)只有256比特,可以利用軟件和硬件實(shí)現(xiàn)高速處理贫导,而RSA算法需要進(jìn)行大整數(shù)的乘冪和求模等多倍字長(zhǎng)處理抛猫,處理速度明顯慢于AES[5];所以AES算法加解密處理效率明顯高于RSA算法孩灯。在密鑰管理方面闺金,因?yàn)锳ES算法要求在通信前對(duì)密鑰進(jìn)行秘密分配,解密的私鑰必須通過(guò)網(wǎng)絡(luò)傳送至加密數(shù)據(jù)接收方峰档,而RSA采用公鑰加密败匹,私鑰解密(或私鑰加密寨昙,公鑰解密),加解密過(guò)程中不必網(wǎng)絡(luò)傳輸保密的密鑰掀亩;所以RSA算法密鑰管理要明顯優(yōu)于AES算法舔哪。
從上面比較得知,由于RSA加解密速度慢归榕,不適合大量數(shù)據(jù)文件加密尸红,因此在網(wǎng)絡(luò)中完全用公開(kāi)密碼體制傳輸機(jī)密信息是沒(méi)有必要,也是不太現(xiàn)實(shí)的刹泄。AES加密速度很快外里,但是在網(wǎng)絡(luò)傳輸過(guò)程中如何安全管理AES密鑰是保證AES加密安全的重要環(huán)節(jié)。這樣在傳送機(jī)密信息的雙方特石,如果使用AES對(duì)稱(chēng)密碼體制對(duì)傳輸數(shù)據(jù)加密盅蝗,同時(shí)使用RSA不對(duì)稱(chēng)密碼體制來(lái)傳送AES的密鑰,就可以綜合發(fā)揮AES和RSA的優(yōu)點(diǎn)同時(shí)避免它們?nèi)秉c(diǎn)來(lái)實(shí)現(xiàn)一種新的數(shù)據(jù)加密方案姆蘸。加解密實(shí)現(xiàn)流程如下圖:
具體過(guò)程是先由接收方創(chuàng)建RSA密鑰對(duì)墩莫,接收方通過(guò)Internet發(fā)送RSA公鑰到發(fā)送方,同時(shí)保存RSA私鑰逞敷。而發(fā)送方創(chuàng)建AES密鑰狂秦,并用該AES密鑰加密待傳送的明文數(shù)據(jù),同時(shí)用接受的RSA公鑰加密AES密鑰推捐,最后把用RSA公鑰加密后的AES密鑰同密文一起通過(guò)Internet傳輸發(fā)送到接收方裂问。當(dāng)接收方收到這個(gè)被加密的AES密鑰和密文后,首先調(diào)用接收方保存的RSA私鑰牛柒,并用該私鑰解密加密的AES密鑰堪簿,得到AES密鑰。最后用該AES密鑰解密密文得到明文皮壁。
-
Android端 AES+RSA結(jié)合實(shí)踐
基本要求:
保證傳輸數(shù)據(jù)的安全性
保證數(shù)據(jù)的完整性
能夠驗(yàn)證客戶(hù)端的身份
基本流程:
Android端:
1.服務(wù)器端(server)分別生成自己的RSA密鑰對(duì),并提供接口給Android客戶(hù)端獲取RSA公鑰(rsaPublicKey)椭更。
2.client生成AES密鑰(aesKey)。
3.client使用自己的AES密鑰(aesKey)對(duì)轉(zhuǎn)換為json格式的請(qǐng)求明文數(shù)據(jù)(data)進(jìn)行加密蛾魄,得到加密后的請(qǐng)求數(shù)據(jù)encryptData虑瀑。
4.client提供server提供的接口獲取RSA公鑰(rsaPublicKey)。
5.client使用獲取RSA公鑰(rsaPublicKey)對(duì)AES密鑰(aesKey)進(jìn)行加密滴须,得到encryptAesKey舌狗。
6.client將encryptAesKey作為http請(qǐng)求頭參數(shù),將加密后的請(qǐng)求數(shù)據(jù)encryptData作為請(qǐng)求體一起傳輸給服務(wù)器端描馅。
服務(wù)器端
1.server響應(yīng)client的http請(qǐng)求把夸,讀取http請(qǐng)求頭。獲得client傳過(guò)來(lái)的加密后的AES密鑰(encryptAesKey)铭污,
讀取http請(qǐng)求體恋日,獲得client傳過(guò)來(lái)的加密后的請(qǐng)求數(shù)據(jù)(encryptData)膀篮。
2.server使用自己的RSA私鑰(rsaPrivateKey)對(duì)加密后的AES密鑰(encryptAesKey)進(jìn)行RSA解密,得到AES密鑰(aesKey)岂膳。
3.使用解密后的AES密鑰(aesKey)對(duì)加密后的請(qǐng)求數(shù)據(jù)(encryptData),進(jìn)行AES解密操作誓竿,得到解密后的請(qǐng)求數(shù)據(jù)(data),該數(shù)據(jù)為json格式谈截。
4.對(duì)解密后的請(qǐng)求數(shù)據(jù)(data)進(jìn)行json解析筷屡,然后做相關(guān)的響應(yīng)操作。
基本上如下圖所示的流程:
總結(jié)
幾條原則:
1簸喂、不要自己設(shè)計(jì)加密算法和協(xié)議毙死,使用業(yè)界標(biāo)準(zhǔn)的算法。
2喻鳄、對(duì)稱(chēng)加密算法不要使用ECB模式扼倘,不建議使用DES算法。
3除呵、要選擇合適長(zhǎng)度的密鑰再菊。
4、要確保隨機(jī)數(shù)生成器的種子具有足夠的信息熵颜曾。
5纠拔、不要使用沒(méi)有消息認(rèn)證的加密算法加密消息,無(wú)法防重放泛豪。
6稠诲、當(dāng)多個(gè)字符串拼接后做hash,要非常當(dāng)心候址。
7吕粹、當(dāng)給算法加yan鹽取值時(shí)不要太短种柑,不要重復(fù)岗仑。
8、使用初始化向量時(shí)IV時(shí)聚请,IV為常量的CBC荠雕,CFB,GCM等和ECB一樣可以重放驶赏,即采用上一個(gè)消息的最后一塊密文作為下一個(gè)消息的IV炸卑,是不安全的。
9煤傍、密鑰應(yīng)遵循的原則
(1)密鑰不能為常量盖文,應(yīng)隨機(jī),定期更換蚯姆,如果加密數(shù)據(jù)時(shí)使用的密鑰為常量五续,則相同明文加密會(huì)得到相同的密文洒敏,很難防止字典攻擊。
(2)開(kāi)發(fā)同學(xué)要防范密鑰硬編碼的毛病疙驾。
而在實(shí)際開(kāi)發(fā)中凶伙,密鑰如何保存始終是繞不過(guò)的坎?如果硬編碼在代碼中容易被逆向它碎,如果放在設(shè)備的某個(gè)文件函荣,也會(huì)被有經(jīng)驗(yàn)的破解者逆向找到,在這里推薦阿里聚安全的安全組件服務(wù)扳肛,其中的安全加密功能提供了開(kāi)發(fā)者密鑰的安全管理與加密算法實(shí)現(xiàn)傻挂,保證密鑰的安全性,實(shí)現(xiàn)安全的加解密操作挖息。