區塊鏈加密算法小探(一)

前言

區塊鏈的底層實現離不開各類加密算法,所以對密碼學技術的瞭解將會更有助於對區塊鏈的學習和理解。本系列從密碼學原理和具體代碼應用兩方面來概括整理下區塊鏈用到的各類密碼學算法。這裏用到的語言爲Python。python

工程領域歷來沒有黑科技;密碼學不是工程。 密碼學在信息技術領域的重要地位無需多言。若是沒有現代密碼學的研究成果,人類社會根本沒法進入信息時代。密碼學領域十分繁雜,本章將介紹密碼學領域中跟區塊鏈相關的一些基礎知識,包括 hash 算 法與摘要、加密算法、數字簽名和證書、PKI 體系、Merkle 樹、同態加密等,以及如何使用 這些技術實現信息的機密性、完整性、認證性和不可抵賴性。算法

(1)哈希算法

定義

哈希算法將任意長度的二進制值映射爲較短的固定長度的二進制值,這個小的二進制值稱爲哈希值。哈希值是一段數據惟一且極其緊湊的數值表示形式。若是散列一段明文並且哪怕只更改該段落的一個字母,隨後的哈希都將產生不一樣的值。要找到散列爲同一個值的兩個不一樣的輸入,在計算上是不可能的,因此數據的哈希值能夠檢驗數據的完整性。通常用於快速查找和加密算法。瀏覽器

一個優秀的hash 算法,將能實現:安全

  • 正向快速:給定明文和hash 算法,在有限時間和有限資源內能計算出hash 值。
  • 逆向困難:給定(若干)hash 值,在有限時間內很難(基本不可能)逆推出明文。
  • 輸入敏感:原始輸入信息修改一點信息,產生的hash 值看起來應該都有很大不一樣。
  • 衝突避免:很難找到兩段內容不一樣的明文,使得它們的hash 值一致(發生衝突)。

目前流行的哈希算法有MD五、SHA-1 和 SHA-2。bash

代碼實戰

""" @author: chaors @file: Hash.py @time: 2018/04/09 21:15 @desc: HASH算法 """

import hashlib

#SHA256
myhash = hashlib.sha256()  #sha512將是更安全的哈希算法
myhash.update("1000001".encode("utf-8"))

print(myhash.hexdigest())  #哈希密碼的二進制串

  #443372db1ff98d9737596b4f83a8381ab6aab60e44e29854b48be88c74cdf1f0
  #2的256次方,這個數字超級大,達到你幾乎無可能沒法經過哈希算法對不一樣數據得出同一個序列
  #數據被修改,hash值必定被改變

print(dir(hashlib))  #哈希算法有這麼多
/**
['__all__', '__builtin_constructor_cache', '__builtins__', '__cached__', '__doc__', '__file__', '__get_builtin_constructor', '__loader__', '__name__', '__package__', '__spec__', '_hashlib', 'algorithms_available', 'algorithms_guaranteed', 'blake2b', 'blake2s', 'md5', 'new', 'pbkdf2_hmac', 'sha1', 'sha224', 'sha256', 'sha384', 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', 'sha512', 'shake_128', 'shake_256']
*/
複製代碼

(2)對稱加密

定義

根據加解密的密鑰是否相同,算法能夠分爲對稱加密(symmetric cryptography,又稱公共密 鑰加密,common-key cryptography)和非對稱加密(asymmetric cryptography,又稱公鑰加 密,public-key cryptography)。兩種模式適用於不一樣的需求,剛好造成互補,不少時候也能夠 組合使用,造成混合加密機制。服務器

顧名思義,加解密的密鑰是相同的。 優勢是加解密效率高(速度快,空間佔用小),加密強度高。 缺點是參與多方都須要持有密鑰,一旦有人泄露則安全性被破壞;另外如何在不安全通道下分發密鑰也是個問題網絡

表明算法包括DES、3DES、AES、IDEA等。函數

  • DES(Data Encryption Standard):經典的分組加密算法,1977 年由美國聯邦信息處理標準(FIPS)所採用FIPS-46-3,將64 位明文加密爲64 位的密文,其密鑰長度爲56位+8位校驗。如今已經很容易被暴力破解。工具

  • AES(Advanced Encryption Standard):美國國家標準研究所(NIST)採用它取代DES成爲對稱加密實現的標準。AES也是分組算法,分組長度爲12八、19二、256 位三種。AES的優點在於處理速度快,整個過程能夠數學化描述,目前還沒有有有效的破解手段。學習

  • ...

廢話少說擼代碼

""" @author: chaors @file: AES_DES.py @time: 2018/04/09 21:29 @desc: 對稱加密算法:DES, AES """

import pyDes  #DES加密模塊
from Crypto.Cipher import AES  #AES加密模塊
from binascii import b2a_hex, a2b_hex  #二進制轉十六進制

pwd = b"\0\0\0\4\0\0\0\0"  #加密密碼要求8個字節
data = "heollo, bitcoin..."
key = pyDes.des(b"DESCRYPT",  #加密算法
                pyDes.CBC,  #加密模式
                pwd,  #加密密碼
                pad=None,
                padmode=pyDes.PAD_PKCS5)  #加密參數
newdata = key.encrypt(data)

print("DES encrypt data:", newdata)
print("DES decrypt data:", key.decrypt(newdata))

class AES_chaors:
    def __init__(self, key):
        self.key = key  #加密密碼
        self.model = AES.MODE_ECB  #加密函數,加密文本必須是16的倍數,不足補零

    def encrypt(self, text):  #加密
        cryptor = AES.new(self.key, self.model, self.key)  #新建加密算法
        text = text.encode("utf-8")
        length = 16  #密碼長度
        count = len(text)  #求長度
        add = length - (count%length)
        text = text + (b"\0"*add)  #填充0
        self.ciphertext = cryptor.encrypt(text)  #加密

        return b2a_hex(self.ciphertext).decode("ASCII")  #ASCII轉16進制

    def decrypt(self, text):  #解密
        cryptor = AES.new(self.key, self.model, self.key)  # 新建解密算法
        lasttext = cryptor.decrypt(a2b_hex(text))  #文本轉16進制

        return lasttext.rstrip(b'\0').decode("utf-8")

if __name__ == '__main__':
    aes = AES_chaors("chaors love codi".encode("utf-8"))
    print("AES encrypt:", aes.encrypt("hello, bitcoin!!!"))
    print("AES decrypt:", aes.decrypt(aes.encrypt("hello, bitcoin!!!")))
複製代碼

python3使用AES的大坑

python使用AES加密模塊依賴於Crypto庫,網上你能找到的大部分導入方式都是:

from Crypto.Cipher import AES  #AES加密模塊
複製代碼

可是這個時候,pycharm一般會報錯:

Crypto庫導入錯誤

咱們知道這個錯的意思是,缺乏庫文件支持。咱們習慣性地將光標移動到Crypto處按下「alt+Enter」快捷鍵安裝模塊,發現並無什麼卵用。因而,打開pycharm的工具包看有沒有,發現只有一個小寫的crypto庫,看着差很少覺得就是他,接着安裝。

安裝長得像Crypto的crypto

運行文件發現仍然報錯,我也是python小白,試着將文件裏的Crypto改成crypto,發現根本於事無補!!!

#from Crypto.Cipher import AES #AES加密模塊
from crypto.Cipher import AES  #!!!於事無補
複製代碼

依然是這個邪門的錯誤:

from Crypto.Cipher import AES  #AES加密模塊
ModuleNotFoundError: No module named 'Crypto'
複製代碼

鬱悶了一小會,問度娘。搜到的好幾個解決方案是讓我找到安裝的crypto路徑,將crypto改成Crypto便可。但是寶寶根本找不到啊,python下安裝的全部例如hashlib的路徑都沒找到(Mac本,誰知道在哪留言告訴小小白我...)

踏破鐵鞋柳暗花明,最終仍是找到了解決方案: 將crypto卸載,在pycharm工具包中安裝pycrypto庫(必定要先把以前的crypto卸載再安裝),或者命令行執行安裝:

pip uninstall crypto
pip install pycrypto
複製代碼

如此,就解決了Crypto.Cipher在引入時候的報錯問題。

(3)非對稱加密(主要RSA)

定義

顧名思義,加密密鑰和解密密鑰是不一樣的,分別稱爲公鑰和私鑰。 公鑰通常是公開的,人人可獲取的,私鑰通常是我的本身持有,不能被他人獲取。 優勢是公私鑰分開,不安全通道也可以使用。

缺點是加解密速度慢,通常比對稱加解密算法慢兩到三個數量級;同時加密強度相比對稱加 密要差。

表明算法包括:RSA、ElGamal、橢圓曲線(Elliptic Curve Crytosystems,ECC)系列算 法。

  • RSA:經典的公鑰算法,1978 年由Ron Rivest、Adi Shamir、Leonard Adleman 共同提出,三人於2002 年得到圖靈獎。算法利用了對大數進行質因數分解困難的特性,但目前尚未數學證實二者難度等價,或許存在未知算法在不進行大數分解的前提下解密。
  • ElGamal:由TaherElGamal 設計,利用了模運算下求離散對數困難的特性。
  • 橢圓曲線算法:現代備受關注的算法系列,基於對橢圓曲線上特定點進行特殊乘法逆運 算難以計算的特性。

RSA算法等已被認爲不夠安全,通常推薦採用橢圓曲線系列算法。比特幣的祕鑰對就是使用橢圓曲線密碼學(Elliptic Curve Cryptography)生成的。

RSA的另外一個引用

相似在紙質合同上簽名確認合同內容,數字簽名用於證明某數字內容的完整性(integrity)和 來源(或不可抵賴,non-repudiation)。 一個典型的場景是,A 要發給 B 一個文件(一份信息),B 如何獲知所獲得的文件即爲 A 發 出的原始版本?A 先對文件進行摘要,而後用本身的私鑰進行加密,將文件和加密串都發給 B。B 收到後文件和加密串,用 A 的公鑰來解密加密串,獲得原始的數字摘要,跟對文件進行 摘要後的結果進行比對。若是一致,說明該文件確實是 A 發過來的,而且文件內容沒有被修改過。

代碼理解

""" @author: chaors @file: RSA.py @time: 2018/04/09 22:09 @desc: 非堆成加密算法:RSA """

import rsa  #RSA加密模塊

#生成公鑰,私鑰祕鑰對
pubkey, privatekey = rsa.newkeys(1024)
print(pubkey, privatekey)

#祕鑰和pem祕鑰文件的相互轉化
with open("rsa_pub.pem", "w+") as publicfile:  #公鑰寫入文件
    publicfile.write(pubkey.save_pkcs1().decode())

with open("rsa_private.pem", "w+") as privatefile:  #私鑰寫入文件
    privatefile.write(privatekey.save_pkcs1().decode())

with open("rsa_pub.pem", "r") as publicfile:  #從文件中讀取公鑰
    pubkey = rsa.PublicKey.load_pkcs1(publicfile.read().encode())

with open("rsa_private.pem", "r") as privatefile:  #從文件中讀取私鑰
    privatekey = rsa.PrivateKey.load_pkcs1(privatefile.read().encode())

msg = "我自橫刀向天笑,去留肝膽兩崑崙。"  #原始信息
encryptdata = rsa.encrypt(msg.encode("utf-8"), pubkey)  #加密
print("RSA encrypt:", encryptdata,
      "\nRSA decrypt:", rsa.decrypt(encryptdata, privatekey).decode("utf-8"))

#數字簽名
sign = rsa.sign(msg.encode(), privatekey, "SHA-1")  #私鑰簽名
print(rsa.verify(msg.encode(), sign, pubkey))  #公鑰驗證
print(rsa.verify((msg+"0").encode(), sign, pubkey))  #公鑰驗證
複製代碼

(4)混合加密機制

前面說到對稱加密和非對稱加密兩種模式適用於不一樣的需求,剛好造成互補,不少時候也能夠 組合使用,造成混合加密機制。

即先用計算複雜度高的非對稱加密協商一個臨時的對稱加密密鑰(會話密鑰,通常相對內容 來講要短的多),而後雙方再經過對稱加密對傳遞的大量數據進行加解密處理。

典型的場景是如今你們經常使用的HTTPS 機制。HTTPS其實是利用了TransportLayerSecurity/Secure Socket Layer(TLS/SSL)來實現可靠的傳輸。TLS 爲SSL的升級版本,目前普遍應用的爲TLS 1.0,對應到SSL3.1 版本。

創建安全鏈接的具體步驟以下:

  1. 客戶端瀏覽器發送信息到服務器,包括隨機數R1,支持的加密算法類型、協議版本、壓縮算法等。注意該過程爲明文。

  2. 服務端返回信息,包括隨機數R二、選定加密算法類型、協議版本,以及服務器證書。注意該過程爲明文。

  3. 瀏覽器檢查帶有該網站公鑰的證書。該證書須要由第三方CA來簽發,瀏覽器和操做系統會預置權威CA的根證書。若是證書被篡改做假(中間人攻擊),很容易經過CA的證書驗證出來。

  4. 若是證書沒問題,則用證書中公鑰加密隨機數R3,發送給服務器。此時,只有客戶端和服務器都擁有R一、R2 和R3 信息,基於R一、R2 和R3,生成對稱的會話密鑰(如AES算法)。後續通訊都經過對稱加密進行保護。

注:本文必要術語來源於網絡,代碼出自本人之手。後續會有其餘算法的持續更新。。。

###互聯網顛覆世界,區塊鏈顛覆互聯網!

---------------------------------------------------------20180409 23:40
相關文章
相關標籤/搜索