Python加密與解密
閱讀目錄
前言
據記載,公元前400年,古希臘人發明了置換密碼。1881年世界上的第一個電話
保密專利出現。在第二次世界大戰期間,德國軍方啟用“恩尼格瑪”密碼機,
密碼學在戰爭中起著非常重要的作用。
隨著資訊化和數字化社會的發展,人們對資訊保安和保密的重要性認識不斷提高,
於是在1997年,美國國家標準局公佈實施了“美國資料加密標準(DES)”,
民間力量開始全面介入密碼學的研究和應用中,採用的加密演算法有DES、RSA、SHA等。
隨著對加密強度需求的不斷提高,近期又出現了AES、ECC等。
使用密碼學可以達到以下目的:
保密性:防止使用者的標識或資料被讀取。
資料完整性:防止資料被更改。
身份驗證:確保資料發自特定的一方。
加密演算法分類
對稱加密演算法:
對稱加密採用了對稱密碼編碼技術,它的特點是檔案加密和解密使用相同的金鑰
傳送方和接收方需要持有同一把金鑰,傳送訊息和接收訊息均使用該金鑰。
相對於非對稱加密,對稱加密具有更高的加解密速度,但雙方都需要事先知道金鑰,金鑰在傳輸過程中可能會被竊取,因此安全性沒有非對稱加密高。
常見的對稱加密演算法:DES,AES,3DES等等
非對稱加密演算法:
檔案加密需要公開金鑰(publickey)和私有金鑰(privatekey)。
接收方在傳送訊息前需要事先生成公鑰和私鑰,然後將公鑰傳送給傳送方。傳送放收到公鑰後,將待發送資料用公鑰加密,傳送給接收方。接收到收到資料後,用私鑰解密。
在這個過程中,公鑰負責加密,私鑰負責解密,資料在傳輸過程中即使被截獲,攻擊者由於沒有私鑰,因此也無法破解。
非對稱加密演算法的加解密速度低於對稱加密演算法,但是安全性更高。
非對稱加密演算法:RSA、DSA、ECC等演算法
訊息摘要演算法:
訊息摘要演算法可以驗證資訊是否被篡改。
在資料傳送前,首先使用訊息摘要演算法生成該資料的簽名,然後簽名和資料一同傳送給接收者。
接收者收到資料後,對收到的資料採用訊息摘要演算法獲得簽名,最後比較簽名是否一致,以此來判斷資料在傳輸過程中是否發生修改。
Python加密庫
PyCrypto是 Python 中密碼學方面最有名的第三方軟體包。可惜的是,它的開發工作於2012年就已停止。
其他人還在繼續釋出最新版本的 PyCrypto,如果你不介意使用第三方的二進位制包,仍可以取得Python 3.5 的相應版本。
比如,可以在 Github 上找到了對應Python3.5的PyCrypto 二進位制包。
幸運的是,有一個該專案的分支PyCrytodome 取代了 PyCrypto 。為了在 Linux 上安裝它,
你可以使用以下pip 命令:
pip3 install -i https://pypi.douban.com/simple pycryptodome
在Windows 系統上安裝則稍有不同:
pip3 install -i https://pypi.douban.com/simple pycryptodomex
DES加密
全稱為Data EncryptionStandard,即資料加密標準,是一種使用金鑰加密的塊演算法
入口引數有三個:Key、Data、Mode
Key為7個位元組共56位,是DES演算法的工作金鑰;
Data為8個位元組64位,是要被加密或被解密的資料;
Mode為DES的工作方式,有兩種:加密或解密
3DES(即Triple DES)是DES向AES過渡的加密演算法,
使用兩個金鑰,執行三次DES演算法,
加密的過程是加密-解密-加密
解密的過程是解密-加密-解密
from Crypto.Cipher import DES key = b'abcdefgh' # 金鑰 8位或16位,必須為bytes def pad(text): """ # 加密函式,如果text不是8的倍數【加密文字text必須為8的倍數!】,那就補足為8的倍數 :param text: :return: """ while len(text) % 8 != 0: text += ' ' return text des = DES.new(key, DES.MODE_ECB) # 建立一個DES例項 text = 'Python rocks!' padded_text = pad(text) encrypted_text = des.encrypt(padded_text.encode('utf-8')) # 加密 print(encrypted_text) # rstrip(' ')返回從字串末尾刪除所有字串的字串(預設空白字元)的副本 plain_text = des.decrypt(encrypted_text).decode().rstrip(' ') # 解密 print(plain_text) #
AES加密
高階加密標準(英語:Advanced EncryptionStandard,縮寫:AES),這個標準用來替代原先的DES
AES的區塊長度固定為128 位元,金鑰長度則可以是128,192或256位元(16、24和32位元組)
大致步驟如下:
1、金鑰擴充套件(KeyExpansion),
2、初始輪(Initial Round),
3、重複輪(Rounds),每一輪又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,
4、最終輪(Final Round),最終輪沒有MixColumns。
普通方式
from Cryptodome.Cipher import AES from binascii import b2a_hex, a2b_hex #祕鑰,此處需要將字串轉為位元組 key = 'abcdefgh' #加密內容需要長達16位字元,所以進行空格拼接 def pad(text): while len(text) % 16 != 0: text += ' ' return text #加密祕鑰需要長達16位字元,所以進行空格拼接 def pad_key(key): while len(key) % 16 != 0: key += ' ' return key #進行加密演算法,模式ECB模式,把疊加完16位的祕鑰傳進來 aes = AES.new(pad_key(key).encode(), AES.MODE_ECB) #加密內容,此處需要將字串轉為位元組 text = 'hello' #進行內容拼接16位字元後傳入加密類中,結果為位元組型別 encrypted_text = aes.encrypt(pad(text).encode()) encrypted_text_hex = b2a_hex(encrypted_text) print(encrypted_text_hex) # #此處是為了驗證是否能將位元組轉為字串後,進行解密成功 # #實際上a 就是 encrypted_text ,也就是加密後的內容 # #用aes物件進行解密,將位元組型別轉為str型別,錯誤編碼忽略不計 de = str(aes.decrypt(a2b_hex(encrypted_text_hex)), encoding='utf-8',errors="ignore") # #獲取str從0開始到文字內容的字串長度。 print(de[:len(text)]
面向物件方式
from Cryptodome.Cipher import AES from binascii import b2a_hex, a2b_hex AES_LENGTH = 16 class prpcrypt(): def __init__(self, key): self.key = key self.mode = AES.MODE_ECB self.cryptor = AES.new(self.pad_key(self.key).encode(), self.mode) # 加密函式,如果text不是16的倍數【加密文字text必須為16的倍數!】,那就補足為16的倍數 # 加密內容需要長達16位字元,所以進行空格拼接 def pad(self,text): while len(text) % AES_LENGTH != 0: text += ' ' return text # 加密金鑰需要長達16位字元,所以進行空格拼接 def pad_key(self,key): while len(key) % AES_LENGTH != 0: key += ' ' return key def encrypt(self, text): # 這裡金鑰key 長度必須為16(AES-128)、24(AES-192)、或32(AES-256)Bytes 長度.目前AES-128足夠用 # 加密的字元需要轉換為bytes # print(self.pad(text)) self.ciphertext = self.cryptor.encrypt(self.pad(text).encode()) # 因為AES加密時候得到的字串不一定是ascii字符集的,輸出到終端或者儲存時候可能存在問題 # 所以這裡統一把加密後的字串轉化為16進位制字串 return b2a_hex(self.ciphertext) # 解密後,去掉補足的空格用strip() 去掉 def decrypt(self, text): plain_text = self.cryptor.decrypt(a2b_hex(text)).decode() return plain_text.rstrip(' ') if __name__ == '__main__': pc = prpcrypt('abcdef') # 初始化金鑰 e = pc.encrypt("0123456789ABCDEF") d = pc.decrypt(e) print(e, d) e = pc.encrypt("00000000000000000000000000") d = pc.decrypt(e) print(e, d)
RSA加密
公鑰加密演算法,一種非對稱密碼演算法
公鑰加密,私鑰解密
3個引數:
rsa_n, rsa_e,message
rsa_n, rsa_e 用於生成公鑰
message: 需要加密的訊息
安裝 pip install rsa
使用
import rsa from binascii import b2a_hex, a2b_hex class rsacrypt(): def __init__(self, pubkey, prikey): self.pubkey = pubkey self.prikey = prikey def encrypt(self, text): self.ciphertext = rsa.encrypt(text.encode(), self.pubkey) # 因為rsa加密時候得到的字串不一定是ascii字符集的,輸出到終端或者儲存時候可能存在問題 # 所以這裡統一把加密後的字串轉化為16進位制字串 return b2a_hex(self.ciphertext) def decrypt(self, text): decrypt_text = rsa.decrypt(a2b_hex(text), prikey) return decrypt_text if __name__ == '__main__': pubkey, prikey = rsa.newkeys(256) rs_obj = rsacrypt(pubkey,prikey) text='hello' ency_text = rs_obj.encrypt(text) print(ency_text) print(rs_obj.decrypt(ency_text)) """ b'7cb319c67853067abcd16aad25b3a8658e521f83b1e6a6cf0c4c2e9303ad3e14' b'hello' """