實際工做和開發過程當中,網絡通訊過程當中的數據傳輸和存儲大多須要通過嚴格的加解密設計,好比用戶的登錄與註冊,敏感信息傳輸,支付網站和銀行的交易信息,甚至爲了防止被拖庫,數據庫的敏感信息存儲也須要通過精心的設計。在進行安全設計過程當中,或多或少涉及到密碼學的一些概念,好比對稱加密算法,非對稱加密算法(也名公鑰算法),消息認證,Hash函數(也名散列函數或摘要算法),數字簽名(也名指紋或摘要),流密碼等。html
一直以來,對於這些概念,你是否有一種模棱兩可,似懂非懂的感受?下面我們一塊兒揭開密碼學這層神祕的面紗。git
基本概念
密碼體制
密碼體制是知足如下5個條件的五元組(P, C, K, E, D),知足條件:github
P(Plaintext)是可能明文的有限集(明文空間);web
C(Ciphertext)是可能密文的有限集(密文空間);算法
K(Key)是一切可能密鑰構成的有限集(密鑰空間);數據庫
E(Encrtption)和D(Decryption)是分別由密鑰決定的全部加密算法和解密算法的集合;安全
存在:網絡
\(k \in K\) ,有加密算法 \(e_k:P \rightarrow C\) , \(e_k \in E\);同時有由 $ \in K$ 決定的解密算法 \(d_{k_1} : C \rightarrow P,d_{k_1} \in D\);知足關係 \(d_{k_1} (e_k(x)) = x, x \in P\)。hexo
密碼破譯
密碼破譯根本目的在於破譯出密鑰或密文,假設破譯者Oscar是在已知密碼體制的前提下來破譯Bob使用的密鑰。這個假設被稱爲Kerckhoff準則,最多見的破解類型有以下5種,從1~5,Oscar的破譯難度逐漸下降。app
- 惟密文攻擊:Oscar僅具備密文串c,Oscar只能經過統計特性分析密文串p的規律;
- 已知明文攻擊:Oscar具備一些明文串p和相應的密文c,{p,c}能夠是{P,C}的任意非空子集;
- 選擇明文攻擊:Oscar可得到對加密機的暫時訪問,所以他能選擇特定明文串p並構造出相應的密文串c;
- 選擇密文攻擊:Oscar可暫時接近解密機,所以他能選擇特定密文串c並構造出相應的明文串p。
- 選擇文本攻擊:Oscar能夠製造任意明文(p) / 密文(c)並獲得對應的密文(c) / 明文(p)。
加密算法
對稱加密算法
對稱加密算法的加密密鑰和解密密鑰相同,常見的對稱加密算法有:AES、DES、2DES、3DES、RC四、RC五、RC6,Blowfish和IDEA,目前使用最普遍的是DES、AES。
graph LR A[發送方Bob<br>輸入明文P] -->|P|B["發送方Bob與接收方Alice<br>共用相同密鑰K<br>加密算法(如DES)<br>C=E(K,P)"]; B -->|傳輸密文C|C["接收方Alice與發送方Bob<br>共用相同密鑰K<br>解密算法(如DES)<br>P=D(K,C)"]; C -->|P|D["Alice接收方<br>輸出明文P"];
非對稱加密算法(公鑰算法)
公鑰算法的加密算法和解密算法使用不一樣的密鑰,分別爲公鑰和私鑰,這兩個密鑰中的任何一個均可以用來加密,而另外一個用來解密。常見的公鑰算法有:橢圓曲線(ECC)、RSA、Diffie-Hellman、El Gamal(安全性創建在基於求解離散對數是困難的)、DSA(適用於數字簽名)。
公鑰算法的應用
- 發送方Bob用接收方Alice的公鑰對消息進行加密,接收方Alice用本身的私鑰進行解密,可提供消息傳輸過程當中的保密性。
graph LR A[Bob<br>輸入明文P] -->|P|B["Bob的公鑰環{PUalice,……}<br>加密算法<br>C=E(PUalice,P)"]; B -->|傳輸密文C|C["Alice私鑰PRalice<br>解密算法<br>P=D(PRalice,C)"]; C -->|P|D["Alice<br>輸出明文P"];
- 發送方Bob採用本身的私鑰對明文進行加密,雖然任何持有Bob公鑰的人都可以解密,可是隻有擁有Bob私鑰的人才能產生密文C,而Bob的私鑰只有本身知道,所以密文C也叫作數字簽名,數字簽名C可用於認證源和數據的完整性。
graph LR A[Bob<br>輸入明文P] -->|P|B["Bob的私鑰PRbob<br>加密算法(如RSA)<br>C=E(PRbob,P)"]; B -->|傳輸數字簽名C|C["Alice的公鑰環{PUbob,……}<br>解密算法(如RSA)<br>P=D(PUbob,C)"]; C -->|P|D["Alice<br>輸出明文P"];
- 發送方Bob首先採用本身的私鑰對明文進行加密,而後使用接收方Alice的公鑰再進行一次加密後傳輸,則既可提供認證功能,又可提供消息傳輸過程當中的保密性。
graph LR A[Bob<br>輸入明文P] -->|P|B["Bob的私鑰PRbob<br>加密算法(如RSA)<br>C=E(PRbob,P)"]; B -->|數字簽名C|C["Bob的公鑰環{PUalice,……}<br>加密算法(如RSA)<br>C1=E(PUalice,C)"]; C -->|傳輸密文C1|D["Alice的私鑰PRalice<br>解密算法(如RSA)<br>C=D(PRalice,C1)"]; D -->|數字簽名C|E["Alice的公鑰環{PUbob,……}<br>解密算法(如RSA)<br>P=D(PUbob,C)"]; E -->|P|F["Alice<br>輸出明文P"];
- 發送方Bob用接收方Alic的公鑰對本身的私鑰進行加密,而後發送給Alice,Alic用本身的私鑰解密便可獲得發送方Bob的私鑰,從而實現密鑰交換功能。
graph LR A[Bob的私鑰<br>PRbob] -->|Bob的私鑰PRbob|B["Bob的公鑰環{PUalice,……}<br>加密算法(如RSA)<br>C=E(PUalice,PRbob)"]; B -->|傳輸密文C|C["Alice的私鑰PRalice<br>解密算法(如RSA)<br>PRbob=D(PRalice,C)"]; C -->|PRbob|D["Alice<br>Bob的私鑰PRbob"];
另外須要說明一下,Diffie-Hellman的密鑰交換算法與此方法不一樣,若是你學過密碼學,應該清楚其中的差別。而且並非全部的公鑰算法都支持加密/解密、數字簽名和密鑰交換功能,有的公鑰算法只支持其中的一種或兩種,下表列出部分公鑰算法鎖支持的應用。
算法 |
加密/解密 |
數字簽名 |
密鑰交換 |
RSA 安全性創建在基於大素數分解是困難的 |
Y |
Y |
Y |
橢圓曲線/ECC 安全性創建在橢圓曲線對數問題之上 (即由kP和P肯定k是困難的) |
Y |
Y |
Y |
Diff-Hellman 安全性創建在計算離散對數是很困難的 |
N |
Y |
Y |
DSS |
N |
Y |
N |
Hash函數(散列函數或摘要函數)
Hash函數將可變長度的消息映射爲固定長度的Hash值或消息摘要,常見的Hash算法有:MD二、MD四、MD五、SHA-一、SHA-22四、SHA-25六、SHA-38四、SHA-5十二、HAVAL、HMAC、HMAC-MD五、HMAC-SHA1。對於給定的密碼學Hash函數y=Hash(x),要求以下兩種狀況再計算上不可行:
- 對給定的y,找到對應的x;
- 找到兩個不一樣的x1和x2,使得Hash(x1)=Hash(x2),具備抗碰撞性的特色。
Hash函數的應用
- 消息認證是用來驗證消息完整性的一種機制或服務,消息認證確認收到的數據確實和發送時的同樣(即防篡改),而且還要確保發送方的身份是真實有效的的(即防冒充)。下圖以對稱加密算法爲例,由於對稱密鑰K只有Bob和Alice纔有,保證了發送方的合法有效性,同時比較C3與C是否相等,能夠肯定傳輸過程當中是否被篡改過。
graph LR A[Bob<br>輸入明文P] -->|P|B["Bob<br>Hash函數<br>(如sha256)<br>C=Hash(P)"]; B -->|C|C["Bob<br>C1=P||C"]; A -->|P|C; C -->|"C1=P||C"|D["Bob和Alice公用的密鑰K<br>對稱加密算法(如DES)<br>C2=E(K,C1)"]; D -->|傳輸密文C2|E["Alice和Bob公用的密鑰K<br>對稱解密算法(如DES)<br>C1=D(K,C2)"]; E -->|"C1=P||C"|F["Alice<br>1.Hash函數(如sha256)<br>C3=Hash(P)<br>2.比較C3與C是否相等"];
- **數字簽名(也名指紋或摘要)**是一種認證機制,它使得消息的產生者能夠添加一個起簽名做用的碼字,經過計算消息的Hash值並用產生者的私鑰加密Hash值來生成簽名,簽名保證了消息和來源和完整性。下圖最後一步比較C3與C若是不相等,認證失敗,該圖沒有提供保密性,由於傳輸過程當中只是將P和C1簡單的鏈接在一塊兒,並無對C2進行加密,若是須要提供保密性,可使用Alic的私鑰對C2加密後再傳輸。
graph LR A[Bob<br>輸入明文P] -->|P|B["Bob<br>Hash函數<br>(如sha256)<br>C=Hash(P)"]; B -->|C|C["Bob的私鑰PRbob<br>加密算法(如RSA)<br>C1=E(PRbob,C)"]; C -->|C1|D["Bob<br>C2=P||C1"]; A -->|P|D; D -->|傳輸C2|E["Alice的公鑰環{PUbob,……}<br>1.解密算法(如RSA)<br>C=D(PUbob,C1)<br>2.Hash函數(如sha256)<br>C3=Hash(P)<br>3.比較C3與C是否相等"];
- 用於產生單向口令文件,好比操做系統存儲的都是口令的Hah值而不是口令自己,當用戶輸入口令時,計算其Hash值和以前存儲的口令比對,這樣即便操做系統被黑以後,也能保證用戶口令的安全性。一樣適用於入侵檢測和病毒檢測,如將你須要保護的文件的Hash值存儲到安全系統中(好比只讀設備中,不可修改也不可刪除),這樣病毒入侵後只能修改文件而不能修改Hash值,因而能夠經過從新計算文件的Hash值和以前保存的Hash值比對。
加密方式
流密碼
典型的流密碼是每次加密一個字節的密文,加密長度能夠按需求設計,好比每次只加密一位或者大於一個字節的單元都行。實質上$Ci=Pi \oplus K1i,Pi=Ci \oplus K2i$,就是簡單的異或,加密異或一次,解密再異或一次,便可恢復明文字節流。
graph LR A["Bob<br>明文字節流P1~Pn"] -->|"P1~Pn"|C["Bob<br>加密函數<br>Ci=E(K1i,Pi)"]; B["Bob 由密鑰K1控制的<br>密鑰流發生器K11~K1n<br>其中K1i=K2i"] -->|"K11~K1n"|C; C -->|"傳輸密文C1~Cn"|E["Alice<br>解密函數<br>Pi=D(K2i,Ci)"]; D["Alice 由密鑰K2控制的<br>密鑰流發生器K21~K2n<br>其中K1i=K2i"] -->|"K21~K2n"|E; E -->|"明文字節流P1~Pn"|F["Alice<br>明文字節流P1~Pn"];
參考文獻
[1] MathJax語法規則
[2] Mermaid語法規則
[3] Mermaid官方教程
[4] Mermaid Github倉庫
[5] MathJax Github倉庫
[6] 經常使用加密算法概述
[7] HTTPS創建過程