數據安全及各類加密算法對比

平時開發中不只會遇到各類須要保護用戶隱私的狀況,並且還有可能須要對公司核心數據進行保護,這時候加密隱私數據就成爲了必要。然而市場上存在着各類各樣的抓包工具及解密算法,甚至一些公司有專門的逆向部門,這就加大了數據安全的風險,本文將經過如下幾個方面對各類加密算法進行分析對比:php

  • Base64編碼(基礎)
  • 單項散列函數 MD五、SHA一、SHA25六、SHA512等
  • 消息認證碼 HMAC-MD五、HMAC-SHA1
  • 對稱加密 DES|3DES|AES(高級加密標準)
  • 非對稱加密 RSA
  • 數字簽名
  • 證書

一般咱們對消息進行加解密有兩種處理方式:css

  1. 只須要保存一個值,保證該值得機密性,不須要知道原文(用戶登陸)
  2. 除了保證機密性外還須要對加密後的值進行解密獲得原文

Base64編碼

因爲咱們可能對各類各樣的數據進行加密,好比:視頻、音頻、文本文件等,因此加密以前咱們須要統一文件類型,而後再進行加密處理。git

  • Base64編碼
// 要編碼的字符串
NSString *str = @"haha";

// 轉換成二進制文件
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];

// 進行base64編碼
NSString *dataStr = [data base64EncodedStringWithOptions:kNilOptions];

NSLog(@"%@", dataStr);複製代碼
  • Base64解碼
// 先對數據進行解碼
NSData *encData = [[NSData alloc]initWithBase64EncodedString:dataStr options:kNilOptions];
    
// 將二進制數據轉換成字符串
NSString *encStr = [[NSString alloc]initWithData:encData encoding:NSUTF8StringEncoding];
    
NSLog(@"%@", encStr);複製代碼

接下來分析一下Base64的編碼過程,參考維基百科:github

image

若是要編碼的字節數不能被3整除,最後會多出1個或2個字節,那麼可使用下面的方法進行處理:先使用0字節值在末尾補足,使其可以被3整除,而後再進行Base64的編碼。在編碼後的Base64文本後加上一個或兩個=號,表明補足的字節數。也就是說,當最後剩餘兩個八位字節(2個byte)時,最後一個6位的Base64字節塊有四位是0值,最後附加上兩個等號;若是最後剩餘一個八位字節(1個byte)時,最後一個6位的base字節塊有兩位是0值,最後附加一個等號。 參考下表:算法

image
  • Base64編碼原理
  1. 將全部字符串轉換成ASCII碼
  2. 將ASCII碼轉換成8位二進制
  3. 將二進制三位歸成一組(不足三位在後邊補0),再按每組6位,拆成若干組
  4. 統一在6位二進制後不足8位的補0
  5. 將補0後的二進制轉換成十進制
  6. 從Base64編碼表取出十進制對應的Base64編碼

若原數據長度不是3的倍數時且剩下1個輸入數據,則在編碼結果後加2個=;若剩下2個輸入數據,則在編碼結果後加1個=數據庫

如上面的例子:瀏覽器

原數據爲A,數據長度爲1,1 % 3 = 1 後面加兩個==安全

原數據爲bc,數據長度爲2,2 % 3 = 2 後面加一個=服務器

  • Base64編碼的特色
  1. 能夠將任意的二進制數據進行Base64編碼。
  2. 全部的數據都能被編碼爲並只用65個字符就能表示的文本文件。
  3. 編碼後的65個字符包括AZ,az,0~9,+,/,=
  4. 對文件或字符串進行Base64編碼後將比原始大小增長33%。
  5. 可以逆運算
  6. 不夠安全,但卻被不少加密算法做爲編碼方式

單項散列函數

單向散列函數也稱爲消息摘要函數、哈希函數或者雜湊函數。
單向散列函數輸出的散列值又稱爲消息摘要或者指紋微信

特色:

  1. 對任意長度的消息散列獲得散列值是定長的
  2. 散列計算速度快,很是高效
  3. 消息不一樣,則散列值必定不一樣
  4. 消息相同,則散列值必定相同
  5. 具有單向性,沒法逆推計算

經典算法:

  • MD四、MD五、SHA一、SHA25六、SHA512等

安全性:

  • md5解密網站:www.cmd5.com
  • MD5的強抗碰撞性已經被證明攻破,即對於重要數據不該該再繼續使用MD5加密。

疑問一:單項散列函數爲何不可逆??

原來好多同窗知識知道md5加密是不可逆的,殊不知道是爲何,其實散列函數能夠將任意長度的輸入通過變化獲得不一樣的輸出,若是存在兩個不一樣的輸入獲得了相同的散列值,咱們稱之爲這是一個碰撞,由於使用的hash算法,在計算過程當中原文的部分信息是丟失了的,一個MD5理論上能夠對應多個原文,由於MD5是有限多個,而原文是無限多個的。

網上看到一個形象的例子:2 + 5 = 7,可是根據 7 的結果,卻並不能推算出是由 2 + 5計算得來的

疑問二:爲何有些網站能夠解密MD5後的數據??

MD5解密網站,並非對加密後的數據進行解密,而是數據庫中存在大量的加密後的數據,對用戶輸入的數據進行匹配(也叫暴力碰撞),匹配到與之對應的數據就會輸出,並無對應的解密算法。

MD5改進

由以上信息能夠知道,MD5加密後的數據也並非特別安全的,其實並無絕對的安全策略,咱們能夠對MD5進行改進,加大破解的難度,典型的加大解密難度的方式有一下幾種:

  1. 加鹽(Salt):在明文的固定位置插入隨機串,而後再進行MD5
  2. 先加密,後亂序:先對明文進行MD5,而後對加密獲得的MD5串的字符進行亂序
  3. 先亂序,後加密:先對明文字符串進行亂序處理,而後對獲得的串進行加密
  4. 先亂序,再加鹽,再MD5等
  5. HMac消息認證碼

也能夠進行屢次的md5運算,總之就是要加大破解的難度。

Hmac消息認證碼(對MD5的改進)

原理:

  1. 消息的發送者和接收者有一個共享密鑰
  2. 發送者使用共享密鑰對消息加密計算獲得MAC值(消息認證碼)
  3. 消息接收者使用共享密鑰對消息加密計算獲得MAC值
  4. 比較兩個MAC值是否一致

使用:

  1. 客戶端須要在發送的時候把(消息)+(消息·HMAC)一塊兒發送給服務器
  2. 服務器接收到數據後,對拿到的消息用共享的KEY進行HMAC,比較是否一致,若是一致則信任
image

對稱加密算法

對稱加密的特色:

  • 加密/解密使用相同的密鑰
  • 是可逆的

經典算法:

  • DES 數據加密標準
  • 3DES 使用3個密鑰,對消息進行(密鑰1·加密)+(密鑰2·解密)+(密鑰3·加密)
  • AES 高級加密標準

密碼算法能夠分爲分組密碼和流密碼兩種:

  • 分組密碼:每次只能處理特定長度的一zu數據的一類密碼算法。一個分組的比特數量就稱之爲分組長度。
  • 流密碼:對數據流進行連續處理的一類算法。流密碼中通常以1比特、8比特或者是32比特等做爲單位倆進行加密和解密。

分組模式:主要有兩種

  • ECB模式(又稱電子密碼本模式)
    • 使用ECB模式加密的時候,相同的明文分組會被轉換爲相同的密文分組。
    • 相似於一個巨大的明文分組 -> 密文分組的對照表。
image

某一塊分組被修改,不影響後面的加密結果

  • CBC模式(又稱電子密碼鏈條)

    • 在CBC模式中,首先將明文分組與前一個密文分組進行XOR(異或)運算,而後再進行加密。
    • 每個分組的加密結果依賴須要與前一個進行異或運算,因爲第一個分組沒有前一個分組,因此須要提供一個初始向量iv
    image

某一塊分組被修改,影響後面的加密結果

代碼演示兩種分組模式

  • AES - ECB模式

加密:

/** * 加密字符串並返回base64編碼字符串 * * @param string 要加密的字符串 * @param keyString 加密密鑰 * @param iv 初始化向量(8個字節) * * @return 返回加密後的base64編碼字符串 */
    NSLog(@"%@", [[EncryptionTools sharedEncryptionTools] encryptString:@"haha" keyString:@"abc" iv:nil]);
    
    // 輸出 MIoAu+xUEpQZSUmkZUW6JQ==複製代碼

解密:

NSLog(@"%@", [[EncryptionTools sharedEncryptionTools] decryptString:@"MIoAu+xUEpQZSUmkZUW6JQ==" keyString:@"abc" iv:nil]);
    
// 輸出 haha複製代碼
  • AES - CBC模式

加密:

uint8_t iv[8] = {1,2,3,4,5,6,7,8};

NSData *data = [[NSData alloc] initWithBytes:iv length:sizeof(iv)];

NSLog(@"%@", [[EncryptionTools sharedEncryptionTools] encryptString:@"haha" keyString:@"abc" iv:data]);
    
// 輸出 E/wWqUTiw/E+1DThAzV39A==複製代碼

解密:

NSLog(@"%@", [[EncryptionTools sharedEncryptionTools] decryptString:@"E/wWqUTiw/E+1DThAzV39A==" keyString:@"abc" iv:data]);
    
// 輸出 haha複製代碼

對稱加密存在的問題??

很明顯,對稱加密主要取決於祕鑰的安全性,數據傳輸的過程當中,若是祕鑰被別人破解的話,之後的加解密就將失去意義

image

其實有點兒相似於咱們日常看的諜戰類的電視劇,地下黨將情報發送給後方,一般須要一箇中間人將密碼本傳輸給後方,若是中間人被抓交出密碼本,那麼未來全部的情報都將失去意義,因而可知情報工做多麼的重要!!!

對稱密碼體制中只有一種密鑰,而且是非公開的,若是要解密就得讓對方知道密鑰。因此保證其安全性就是保證密鑰的安全,而非對稱密鑰體制有兩種密鑰,其中一個是公開的,這樣就能夠不須要像對稱密碼那樣傳輸對方的密鑰了

非對稱加密

鑑於對稱加密存在的風險,非對稱加密應運而生

特色:

  • 使用公鑰加密,使用私鑰解密
  • 公鑰是公開的,私鑰保密
  • 加密處理安全,可是性能極差

非對稱密碼體制的特色:算法強度複雜、安全性依賴於算法與密鑰,可是因爲其算法複雜,而使得加密解密速度沒有對稱加密解密的速度快

經典算法:

  • RSA
RSA算法原理
* 求N,準備兩個質數p和q,N = p x q
* 求L,L是p-1和q-1的最小公倍數。L = lcm(p-1,q-1)
* 求E,E和L的最大公約數爲1(E和L互質)
* 求D,E x D mode L = 1複製代碼
RSA加密實踐
* p = 17,q = 19 =>N = 323
* lcm(p-1,q-1)=>lcm(1618)=>L= 144
* gcd(E,L)=1 =>E=5
* E乘以幾能夠mode L =1? D=29能夠知足
* 獲得公鑰爲:E=5,N=323
* 獲得私鑰爲:D=29,N=323
* 加密 明文的E次方 mod N = 1235次方 mod 323 = 225(密文)
* 解密 密文的D次方 mod N = 22529次方 mod 323 = 123(明文)複製代碼
openssl生成密鑰命令
  • 生成強度是 512 的 RSA 私鑰:$ openssl genrsa -out private.pem 512
  • 以明文輸出私鑰內容:$ openssl rsa -in private.pem -text -out private.txt
  • 校驗私鑰文件:$ openssl rsa -in private.pem -check
  • 從私鑰中提取公鑰:$ openssl rsa -in private.pem -out public.pem -outform PEM -pubout
  • 以明文輸出公鑰內容:$ openssl rsa -in public.pem -out public.txt -pubin -pubout -text
  • 使用公鑰加密小文件:$ openssl rsautl -encrypt -pubin -inkey public.pem -in msg.txt -out msg.bin
  • 使用私鑰解密小文件:$ openssl rsautl -decrypt -inkey private.pem -in msg.bin -out a.txt
  • 將私鑰轉換成 DER 格式:$ openssl rsa -in private.pem -out private.der -outform der
  • 將公鑰轉換成 DER 格式:$ openssl rsa -in public.pem -out public.der -pubin -outform der
非對稱加密存在的安全問題

原理上看非對稱加密很是安全,客戶端用公鑰進行加密,服務端用私鑰進行解密,數據傳輸的只是公鑰,原則上看,就算公鑰被人截獲,也沒有什麼用,由於公鑰只是用來加密的,那還存在什麼問題呢??那就是經典的中間人攻擊

image

廢了半天勁畫的圖,太low了,我仍是本身總結一遍吧!!!

中間人攻擊詳細步驟:

  1. 客戶端向服務器請求公鑰信息
  2. 服務端返回給客戶端公鑰被中間人截獲
  3. 中間人將截獲的公鑰存起來
  4. 中間人本身僞造一套本身的公鑰和私鑰
  5. 中間人將本身僞造的公鑰發送給客戶端
  6. 客戶端將重要信息利用僞造的公鑰進行加密
  7. 中間人獲取到本身公鑰加密的重要信息
  8. 中間人利用本身的私鑰對重要信息進行解密
  9. 中間人篡改重要信息(將給客戶端轉帳改成向本身轉帳)
  10. 中間人將篡改後的重要信息利用原來截獲的公鑰進行加密,發送給服務器
  11. 服務器收到錯誤的重要信息(給中間人轉帳)

疑問一:爲何會形成中間人攻擊??

形成中間人攻擊的直接緣由就是客戶端沒辦法判斷公鑰信息的正確性。

疑問二:怎麼解決中間人攻擊??

須要對公鑰進行數字簽名。就像古代書信傳遞,家人之因此知道這封信是你寫的,是由於信上有你的簽名、印章等證實你身份的信息。

數字簽名須要嚴格驗證發送發的身份信息!!!

數字證書

數字證書包含:

  • 公鑰
  • 認證機構的數字簽名(權威機構CA)

數字證書能夠本身生成,也能夠從權威機構購買,可是注意,本身生成的證書,只能本身承認,別人都不承認.

權威機構簽名的證書:
GitHub官網爲例,Chrome瀏覽器打開網址,地址欄有一個小綠鎖,點擊,內容以下:

權威機構認證的證書:

image

能夠看到鏈接是安全的,點擊證書能夠看到詳細信息


image

這是由權威機構認證的證書,可是是須要花錢的,一年至少得一兩千,因此也有些公司用本身簽名的證書,本身簽名的證書不被信任,可能會提示用戶有風險,好比原來的12306網站,如今大多數網站也都採用了CA簽名數字證書進行簽名,本身作簽名的也很差找了!!!12306都改爲CA認證的了。。。

本身生成一個證書

  • 生成私鑰
openssl genrsa -out private.pem 1024複製代碼
  • 建立證書請求
openssl req -new -key private.pem -out rsacert.csr複製代碼
  • 生成證書並簽名,有效期10年
openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt複製代碼
  • 將 PEM 格式文件轉換成 DER 格式
openssl x509 -outform der -in rsacert.crt -out rsacert.der複製代碼
  • 導出P12文件
openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt複製代碼
image

注意:

  • 在iOS開發中,不能直接使用 PEM 格式的證書,由於其內部進行了Base64編碼,應該使用的是DER的證書,是二進制格式的
  • OpenSSL默認生成的都是PEM格式的證書

代碼演示:

// p12 是私鑰
    // .der 是公鑰
    // 非對稱加密,使用公鑰加密,私鑰解密
    
    // 加載公鑰
    [[RSACryptor sharedRSACryptor] loadPublicKey:[[NSBundle mainBundle] pathForResource:@"rsacert.der" ofType:nil]];
    
    // 對數據加密
    NSData *data = [[RSACryptor sharedRSACryptor] encryptData:[@"hahaha" dataUsingEncoding:NSUTF8StringEncoding]];
    
    // 對加密獲得的密文進行base64編碼打印
    NSLog(@"%@", [data base64EncodedStringWithOptions:kNilOptions]);
    
    // 輸出結果:PflhCgTVNegcQXrb39RJOoxCRRIHuZ3LN0/hoxTDFBbC+8yKjp0m+/hxVUWBVsTo28WnNFCAFfrQ2of5SkqttD51a5eLb21R7bQSQRxg/gVZ5hePcE3vh7Slfcxm2qJM+J8hRWDP/MF4BiDLXI9ZqTpLCSS5mjJtmUBf2wNvI1Y=
    
    // 私鑰解密
    
    // 加載私鑰
    [[RSACryptor sharedRSACryptor] loadPrivateKey:[[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil] password:@"123456"];

    // 解密
    NSData *decryDeta = [[RSACryptor sharedRSACryptor] decryptData:data];
    
    NSLog(@"%@", [[NSString alloc] initWithData:decryDeta encoding:NSUTF8StringEncoding]);
    
    // 輸出:hahaha複製代碼

代碼地址

總結

至此數據安全和加解密相關結算完畢,寫博客的過程,也是學習的過程,斷斷續續的寫了三四天,總算寫完了,同時也對原來一些模糊的概念有了更清晰的認識,寫的這篇文章看了文頂頂老師的視頻,受益不淺,十分感謝,最近學習發現,學的越多,感受會的越少,時間十分的不夠用。同時渴望遇到一些但願進步、不甘平凡的同行!!!共勉!!!



做者:czj_warrior
連接:https://www.jianshu.com/p/b44927161081
此文章來源於第三方轉載!!!

小編這呢,給你們推薦一個優秀的iOS交流平臺,平臺裏的夥伴們都是很是優秀的iOS開發人員,咱們專一於技術的分享與技巧的交流,你們能夠在平臺上討論技術,交流學習。歡迎你們的加入(想要進入的可加小編微信)。 13142121176

相關文章
相關標籤/搜索