【Python】PyCryptodome模塊實現多種加密算法

PyCryptodome是python一個強大的加密算法庫,可以實現常見的單向加密、對稱加密、非對稱加密、非對稱加密算法簽名和流加密算法。
直接pip安裝即可:pip install pycryptodome
官網地址:https://pypi.org/project/pycryptodome/

一、base64編碼簡單介紹

原理:將要編碼的內容按3字節爲一組進行分組,最後一組不夠3位的則補0(顯然最多補兩個0)
每組中每字節最高2位改成0不使用,原先各位的內容保持原有順序往後移;最後在上一步中補了幾個0就加幾個等號以供解碼時按等號個數刪除0(經此操作原先3節字就變成了只使用低6位的4字節)

  • 轉換前 10101101,10111010,01110110
  • 轉換後 00101011, 00011011 ,00101001 ,00110110

用途:一是SMTP中要以BASE64形式傳輸二進制文件,二是常用於將二進制數據轉成可打印的ASCII碼字符進行存儲(下文各加密算法的密鑰一般使用十六進制字符串形式存儲,但也有以base64形式存儲)。
其他:本質上講Base64只能算是一種編碼不能算是一種加密算法,PyCryptodome庫也不支持。但從”Base64讓人一下看不懂原本內容是什麼“的角度講你也不能說他完全不算加密,平時也經常用,我們就順道講一講如何實現。

# 對bytes類型進行再次編碼(先將字符串轉換爲byttes)
def base_info():
    str = '我喜歡 computer'
    #e = base64.b64encode(b"123456")       # 結果:b'MTIzNDU2'
    e = base64.b64encode(str.encode())     # 結果:b'5oiR5Zac5qyiIGNvbXB1dGVy'
    print("編碼過程:",e)
    d = base64.b64decode(b'5oiR5Zac5qyiIGNvbXB1dGVy')
    print("解碼過程:",d.decode())

二、單向加密算法

別稱:單向加密算法,又稱哈希函數、散列函數、雜湊函數、摘要算法,英文名One-way encryption algorithm。
原理:單向加密如其名只能加密不能解密(彩虹表攻擊不是正經的解密),不能解密的原因是本質上並不是用IV(Initial Vector)去加密M輸出M的密文,而是用M去加密IV輸出IV的密文。
用途:消息認證摘要、內容或文檔的數字指紋、口令存儲。
其他:單向加密又可以分爲hash和hmac兩大類,hmac和hash的算法是一樣的,其實可以認爲hmac就是hash加鹽的形式(不過這鹽值不是hash中常用的拼接在最前邊或拼接在最後邊,具體怎麼拼接的我不太確定)。
一般來說標準庫就挺好用時我們一般就直接用標準庫,python的標準庫就能容易地實現單向加密算法,所以單向加密我們使用標準庫實現。
python中hash類算法使用hashlib庫實現,hmac類算法使用hmac庫實現。

import hashlib
import time

print(hashlib.algorithms_available)     # 支持的單向加密算法

encode = 'utf-8'                        # 編碼
appkey = 'md5test.'                     # 待加密信息

time_span = str(int(time.time()))
o_token = appkey                            # 可以對o_token進行處理appkey+time_span
hl = hashlib.md5()                         # 創建md5對象,也可以hl = hashlib.new("md5")
hl.update(o_token.encode(encoding=encode))  # 轉換爲bytes
token = hl.hexdigest().upper()              # hexdigest() 加密過程:以十六進制字符串形式輸出
print('第一種MD5加密後爲 :' + token)

# 另一種寫法:b前綴代表的就是bytes
str_md5 = hashlib.md5(b'md5test.').hexdigest().upper()
print('第二種MD5加密後爲 :' + str_md5)

三、對稱加密算法

別名:對稱加密算法,又稱密鑰加密算法、單密鑰算法、共享密鑰算法,英文名Symmetric Encryption Algorithms。
原理:對稱加密算法最關鍵的就是SP變換,S變換通過代替操作實現混亂(即消除統計信息),P變換通過換位操作實現擴散(即雪崩效應);加解密是使用同一個密鑰的逆操作過程。
用途:對稱加密可以還原內容,且代替和換位操作運算量不大,適用於大量內容的加解密。對稱加密算法的缺點是加解密雙方密鑰分發困難。
其他:對稱加密算法有ECB、CBC、CFB、OFB、CTR等等多種模式,各種模式的加密是有些區別的,比如ECB不需要IV、CBC等則需要IV、EAX則需要nonce和tag等等,所以實現不同模式時寫法會有差別需要具體研究,不能完全照搬下邊的例子。

def aes_encrypt_cbc(org_str, key,iv):
    print('--------------->密碼分組鏈接模式CBC加密開始<---------------')
    aes = AES.new(get_bytes(key), AES.MODE_CBC,get_bytes(iv))
    encrypt_aes = aes.encrypt(get_bytes(org_str))
    encrypted_text = str(base64.b64encode(encrypt_aes), encoding='utf-8')
    print('加密後的數據:', encrypted_text)
    return (encrypted_text)


def aes_decrypt_cbc(secret_str, key,iv):
    print('--------------->密碼分組鏈接模式CBC解密開始<---------------')
    aes = AES.new(get_bytes(key), AES.MODE_CBC,get_bytes(iv))
    base64_decrypted = base64.b64decode(secret_str.encode(encoding='utf-8'))
    decrypted_text = str(aes.decrypt(base64_decrypted), encoding='utf-8').replace('\0', '')
    print('解密後的數據:', decrypted_text)


# bytes不是count的倍數那就補足爲count的倍數
def add_to_count(value):
    while len(value) % count != 0:
        value += b'\x00'
    return value                            # 返回bytes


# str轉換爲bytes超過count位時處理
def get_bytes(org_str):
    org_bytes = str.encode(org_str)
    n = int(len(org_bytes) / count)
    i = 0
    new_bytes = b''
    while n >= 1:
        i = i + 1
        new_byte = org_bytes[(i-1)*count:count*i-1]
        new_bytes += new_byte
        n = n - 1
    if len(org_bytes) % count == 0:
        all_bytes = org_bytes
    elif len(org_bytes) % count != 0 and n>1:
        all_bytes = new_bytes + add_to_count (org_bytes[i*count:])
    else:
        all_bytes = add_to_count (org_bytes)
    return all_bytes

四、非對稱加密算法:

別稱:非對稱加密算法,又稱公鑰加密算法,英文名Asymmetric Cryptographic Algorithm。
原理:非對稱加密依賴與明文經過與公鑰進行數學運算可得出密文,而密文經過與密鑰進行數學運算又可得到明文。
用途:非對稱加密算法的優點是密鑰分發簡單,但缺點也是很明顯的,其加解密過程依賴於數學運算運算量大所以加解密速度慢(另外同樣的密鑰強度其安全性弱於對稱加密算法),其只適用於少量內容的加解密,最典型的就是https中用於完成對稱密鑰的交換。

    def generate_key(self):
        key = RSA.generate(1024)     # 256倍數並且>= 1024
        # print(key)
        # 提取私鑰並存入文件
        private_key = key.exportKey()
        file_out = open("private_key.pem", "wb")
        file_out.write(private_key)

        # 提取公鑰存入文件
        public_key = key.publickey().exportKey()
        file_out = open("public_key.pem", "wb")
        file_out.write(public_key)

    # 加密/過程(無法加密太長的內容,可以分段加密)
    def RSA_encrypt(self,secret_str):
        self.generate_key()
        public_key = RSA.importKey(open("public_key.pem").read())   # 讀取文件
        e_cipher = PKCS1_OAEP.new(public_key)                         # 實例化加密套件
        encrypted_data = e_cipher.encrypt(secret_str.encode())        # 加密
        print(encrypted_data)
        # 解密
        private_key = RSA.importKey(open("private_key.pem", "rb").read())
        d_cipher = PKCS1_OAEP.new(private_key)
        org_data = d_cipher.decrypt(encrypted_data)
        print(org_data.decode())

五、非對稱加密算法簽名實現(以RSA爲例)

我一直以爲私鑰加密公鑰解密和公鑰加密私鑰解密沒什麼兩樣,但首先一是和一個朋友說用私鑰加密發送回來時她疑或說私鑰可以加密嗎,然後回公司又和領導說私鑰加密公鑰解密的時候他直接說私鑰不能加密只能做簽名。
首先說私鑰加密公鑰解密在數學原理上是可行的,而且所謂的數字簽名其本質就是我用你的公鑰可以解開這加密的內容說明這些內容就是你的,即數字簽名和簽名認證本質就是私鑰加密公鑰解密。
但另一方面,因爲公鑰是公開的所以私鑰加密並不能起加密通信的作用,所以一般沒有直接的私鑰加密公鑰解密的操作----但我不太明白爲什麼PyCryptodome這些庫在程序試圖使用私鑰加密時直接報錯拒絕執行(TypeError: This is not a private key),雖然沒什麼用,私鑰加密也沒有什麼危害吧?

六、流加密算法實現(以RC4爲例)

別稱:流加密算法,又稱序列加密算法,英文名Stream cipher。
原理:流加密算法加密和解密也使用同一個密鑰,所以從咬文嚼字來說他也屬於對稱加密算法。流加密算法與前邊單向加密算法、對稱加密算法、非對稱加密算法的區別是前三者都是分組加密算法即一個分組使用同一個密鑰,而流加密算法每一位都使用不同的密鑰。
用途:流加密主要基於異或(xor)操作,運算相對簡單,但安全性較低,沒有很多的使用場景,最典型的是WEP上的使用但也正由於其安全性問題導致WEP的淘汰。

參考:https://www.cnblogs.com/lsdb/p/10912518.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章