一、雜湊演算法
(1)概念
雜湊演算法又稱為雜湊函式、雜湊演算法、雜湊函式,它能從任何資料長度生成一個固定長度的訊息摘要(如下圖)。對於某個特定的訊息而言,這個訊息摘要(或雜湊值)可以看做是這個訊息的指紋,且該訊息是唯一表示。雜湊函式是數字簽名和驗證的核心部分。
(2)雜湊演算法的特性
- 單向性
雜湊函式必須具有單向性,也就是說給定一個輸入,通過雜湊函式可以得到一個雜湊值,但是反過來,給定一個雜湊值,是無法獲得輸入的。換句話說,就是給定一個雜湊值(指紋),我們不可能找到對應的訊息。 - 衝突避免
很難找到兩個不同的訊息,使得產生的雜湊值一致(發生衝突)。 - 輸入敏感
原始資料任何微小的變動都會導致雜湊值完全不一樣 - 正向快速
給定訊息和雜湊演算法,在有限時間和有效資源內計算出雜湊值
(3)雜湊碰撞
雜湊碰撞也就是說存在不同的訊息(輸入),使得雜湊函式的輸出,也就是雜湊值一樣,這種概率非常非常低。以下面的md5為例,兩個輸入有細微差別,但是雜湊值是一樣的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # coding: utf-8 import hashlib # 兩段HEX位元組串,注意它們有細微差別 a = bytearray.fromhex( "0e306561559aa787d00bc6f70bbdfe3404cf03659e704f8534c00ffb659c4c8740cc942feb2da115a3f4155cbb8607497386656d7d1f34a42059d78f5a8dd1ef" ) b = bytearray.fromhex( "0e306561559aa787d00bc6f70bbdfe3404cf03659e744f8534c00ffb659c4c8740cc942feb2da115a3f415dcbb8607497386656d7d1f34a42059d78f5a8dd1ef" ) # 輸出MD5,它們的結果一致 print (hashlib.md5(a).hexdigest()) print (hashlib.md5(b).hexdigest()) ### a和b輸出結果都為: cee9a457e790cf20d4bdaa6d69f01e41 cee9a457e790cf20d4bdaa6d69f01e41 |
以CRC32為例,它的摘要長度為32bit,也就是說存在2^32種可能。如今網際網路頁面總數在2008年的時候就已經超過1萬億,如果採用CRC32的摘要,那麼發生雜湊碰撞的就很多。而MD5的摘要長度為128bit,也就是有2^128種可能,但是目前已經證明MD5演算法是不安全的。同樣的SHA1演算法(160bit)也被證明是不安全的,推薦使用SHA256演算法才比較安全。
(4)常見雜湊演算法
目前比較流行的雜湊演算法有MD5、SHA-1和SHA-2
- MD4
MD4已經被證明時不夠安全的,不推薦使用
- MD5
MD5是MD4的改進版本,輸出是128bit。同樣,MD5也被證明了不具備強抗碰撞性,也是不夠安全的
- SHA-1
SHA是一個雜湊函式族,SHA-1演算法的雜湊值長度為160bit,抗窮舉性比MD5和MD4更好。但是SHA-1已經被證明不具備“強抗碰撞性”(谷歌已經攻破SHA-1),
SHA-2
SHA-224、SHA-256、SHA-384,和 SHA-512 演算法統稱為SHA-2,演算法原理跟SHA-1類似。
總結來說,MD5和SHA-1已經不夠安全,推薦至少使用SHA-256演算法。
(5)應用
雜湊演算法的應用主要體現在以下3個方面:
- 檔案校驗
- 數字簽名
- 鑑權協議(安全通訊)
二、非對稱加密技術
(1)概念
非對稱加密演算法也稱為公鑰加密演算法,其分為3個部分,分別是:公鑰、私鑰和加密解密演算法。
非對稱加密往往需要密碼學安全偽隨機數生成器來產生一對祕鑰(公鑰和私鑰),這兩者是成對的,公鑰是可以公開的,而私鑰則是使用者自己保留。用私鑰加密的資料只有公鑰才可以解密(反過來,用公鑰加密的資料,只有私鑰可以解密)。公鑰和私鑰之間的這種數學關係,使得私鑰可以用於生成特定訊息的簽名。而這個簽名可以在不暴露私鑰的前提下通過公鑰進行驗證。
也就是說我對一段訊息用私鑰進行簽名(也就是加密),然後把這個資料連同簽名和我的公鑰傳送給對方,對方就可以通過公鑰對簽名進行驗證(解密)對比資料從而驗證資料的有效性。
在比特幣系統中,公鑰生成的錢包地址用於接收比特幣,而私鑰則用於比特幣支付時的交易簽名。
在支付比特幣時,比特幣的所有者需要在交易中提交自己的公鑰和該交易的簽名。而比特幣網路中所有節點可以通過所提交的公鑰和簽名進行驗證,從而確認支付者對交易的比特幣的所有權。
(2)加密、解密過程
- 加密過程:通過加密演算法和公鑰對明文進行加密,得到密文
- 解密過程:通過解密演算法(這裡加密、解密演算法要一樣)和祕鑰進行解密,得到明文。
如下圖所示,加密過程是單向的,公鑰加密後的密文只能用對應的私鑰解密。
(3)常見非對稱加密演算法
- RSA
- ElGamal
- 揹包演算法
- Rabin(RSA的特例)
- 迪菲-赫爾曼金鑰交換協議中的公鑰加密演算法
- 橢圓曲線加密演算法(英語:Elliptic Curve Cryptography, ECC)
其中使用最廣泛的是RSA演算法(由發明者Rivest、Shmir和Adleman姓氏首字母縮寫而來)是著名的公開祕鑰加密演算法,ElGamal是另一種常用的非對稱加密演算法。
(4)應用
非對稱加密演算法的應用非常廣泛,下面列舉常見的幾種
- 數字簽名
- 數字證照
- 加密通訊HTTPS
(5)python程式設計實現
生成金鑰對
1 2 3 4 5 6 7 8 | def create_genisus_keypair(): # 第一個節點的金鑰對 pubkey, privkey = rsa.newkeys( 1024 ) with open ( 'genisus_public.pem' , 'w+' ) as f: f.write(pubkey.save_pkcs1().decode()) with open ( 'genisus_private.pem' , 'w+' ) as f: f.write(privkey.save_pkcs1().decode()) |
直接開啟genisus_public.pem和genisus_private.pem,我們可以看到一長串的字串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | genisus_public.pem: - - - - - BEGIN RSA PUBLIC KEY - - - - - MIGJAoGBAJIiGuUOlhKFQEHIr5YXa9uajM + sI5FEZ / 8RJdR5EOC4Wo + 9bZfyrvnu PRBtK7PJzUXHdXCaNohPzA5IuiEpkoELPyWfCozQF9FAgK2Gyf1rBeC7e2lUvuwI h5IXhRjC2Rom6wiJRWXn / W0 / EezrXl8YlYmrRR1Boa9OB1RFJvJXAgMBAAE = - - - - - END RSA PUBLIC KEY - - - - - genisus_private.pem: - - - - - BEGIN RSA PRIVATE KEY - - - - - MIICYAIBAAKBgQCSIhrlDpYShUBByK + WF2vbmozPrCORRGf / ESXUeRDguFqPvW2X 8q757j0QbSuzyc1Fx3VwmjaIT8wOSLohKZKBCz8lnwqM0BfRQICthsn9awXgu3tp VL7sCIeSF4UYwtkaJusIiUVl5 / 1tPxHs615fGJWJq0UdQaGvTgdURSbyVwIDAQAB AoGAOiw7ep3A3iSPfOCQDXbLaANxNKa5DfYmVCKWZavALUUWQAxPmWJxh2rwgh6D fDHEdpe9R5MMTF0 / xRvsQGQvZU2sNNhA2ebVOB4mMCPcURYWCbJXjT14IC7rfwPp YnkpiCHxP + HBS2xjMyf63vk7tKR / zCfzm9tsDAKqKuFUYPECRQCrQpiuYxp2Znch szwR15q0HUpU8 / HdCQlKdBK2fa4M2Y1xPqNjpOlQ2B8zCS3aOQ / 9nhbVaRy0LqFD sUjPPJsTqbaSyQI9ANpwsv1MHkpYGlYSrCItFS1oRoD / foxByVdVORCtarA0z9xe Am8kEi9HcnZf2jsYvqHAeQsTtuPw0PvMHwJEXL0 + csilztHj1zL452yKkNh / pQtI wPogttmuPHZIZxrz9gwGbHIkCixOkNN6qf5Wg281TDGUYpoRp9d75wUZsQcpH8kC PE0rvYBREO5w27UG2bslNDMbgLT4DkwcvbXVzNhAe82OitSufauoEaiUVDLPwDha kJZyehDYwSccH6ilPwJFAIhBzCQ61A2zfEJlgKeuX3OJGq1pywpnv + vFyqnDc4T6 oEW9kfnrAI + 6x4L4jyyHOWMNfkAPajtkQ + YwxZqUmKL8ixr0 - - - - - END RSA PRIVATE KEY - - - - - |
加密、解密
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # 匯入金鑰 with open ( 'genisus_private.pem' , 'r' ) as f: privkey = rsa.PrivateKey.load_pkcs1(f.read().encode()) with open ( 'genisus_public.pem' , 'r' ) as f: pubkey = rsa.PublicKey.load_pkcs1(f.read().encode()) # 明文 message = 'hello world' # 公鑰加密 crypto = rsa.encrypt(message.encode(), pubkey) # 私鑰解密 message = rsa.decrypt(crypto, privkey).decode() print (message) |
三、數字簽名
(1)概念
數字簽名,就是隻有資訊的傳送者才能產生的別人無法偽造的一段數字串,這段數字串同時也是對資訊的傳送者傳送資訊真實性的一個有效證明。它是進行身份鑑別和網上安全交易的通用技術。
數字簽名應用了前2節所說到的非對稱加密技術(公鑰加密演算法)和雜湊演算法。
(2)功能
- 數字簽名主要有三個作用:
- 保證資訊傳輸的完整性(完整性)
- 傳送者身份認證(鑑權)
- 防止交易中發生抵賴(不可抵賴性)
數字簽名是加密過程,數字簽名驗證是解密過程。
(3)簽名和驗證
- 傳送者簽名過程
數字簽名是傳送方首先通過一個雜湊演算法將獲取資訊的一個摘要
然後通過祕鑰對這個摘要進行簽名
最後把簽名和原文一起傳送給接收者 - 接收者驗證過程
數字簽名驗證,接收者收到傳送者傳送的簽名和原文後,首先進行分離
採用跟傳送者一樣的雜湊演算法提取原文的摘要
然後用傳送者的公鑰對簽名進行解密獲得解密後的摘要
兩者對比,如果一致,則說明收到的資訊是完整的,在傳輸過程中沒有被修改過。
這裡,讀者細心想會發現,如果一個黑客,將傳送者的私鑰和接收者手上擁有的傳送者的公鑰都替換成黑客自己的私鑰和公鑰。那這個時候接收者,在驗證的時候是無法發現問題的,因為簽名用的私鑰是黑客的私鑰,驗證用的公鑰也是黑客的公鑰,兩者是成對的。這就變成了對公鑰是否合法的驗證,那麼要解決這個問題就涉及到數字證照的概念(如下圖所示)。這個讀者可以看我另外寫的一篇文章《數字證照是什麼》,這裡就不展開講。
(4)應用
數字簽名技術的應用很廣泛,例如個人安全郵件證照、訪問安全https站點、網上籤約、電子交易等。
(5)python程式設計實現
首先生成一對祕鑰(公鑰和私鑰)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 明文 message = 'hello world' # 匯入金鑰 with open ( 'genisus_private.pem' , 'r' ) as f: privkey = rsa.PrivateKey.load_pkcs1(f.read().encode()) with open ( 'genisus_public.pem' , 'r' ) as f: pubkey = rsa.PublicKey.load_pkcs1(f.read().encode()) # 私鑰簽名 signature = rsa.sign(message.encode(), privkey, 'SHA-1' ) # 公鑰驗證 try : rsa.verify(message.encode(), signature, pubkey) except rsa.pkcs1.VerificationError: print 'invalid' |
關注我的微信公眾號(shuwoom的部落格),每週定期推送文章:
參考:
https://www.jianshu.com/p/bf1d7eee28d0
https://zh.wikipedia.org/wiki/%E6%95%A3%E5%88%97%E5%87%BD%E6%95%B8
http://www.infoq.com/cn/news/2017/02/google-first-sha1-collision
http://blog.jobbole.com/106733/
https://baike.baidu.com/item/%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D
https://blog.csdn.net/u011630575/article/details/53241027