什麼叫數據加密
數據加密是指利用加密演算法和祕鑰將明文轉變爲密文的過程。常見的加密方式有 base64、RSA、MD5、SHA-1、HMAC、DES/AES、ECC
數據加密的方式
單向加密:
指只能加密數據而不能解密數據,這種加密方式主要是爲了保證數據的完整性
常見的加密演算法有 MD5、sha 系列等(位於 python 內建的 hashlib 模組中)。
對稱加密:
指數據加密和解密使用相同的祕鑰,這種加密方式主要是爲了保證數據的機密性
常見的加密演算法有 DES、AES(位於 python 第三方庫 pycrytodomex 中)。
非對稱加密
也叫公鑰加密,指數據加密和解密使用不同的金鑰,這種加密方式基本不可能被破解,主要用於身份驗證等方面
常見的加密演算法有 DSA、RSA(位於 python 第三方模組 rsa 中)。
加密演算法
▍單向加密演算法(MD5、sha系列)不可逆
MD5 加密:MD5 訊息摘要演算法(英語:MD5 Message-Digest Algorithm)
一種被廣泛使用的密碼雜湊函數,可以產生出一個 128 位元(16 位元組)的雜湊值(hash value),用於確保資訊傳輸完整一致。
md5 加密演算法是不可逆的,所以解密一般都是通過暴力窮舉方法,通過網站的介面實現解密。
import hashlib m = hashlib.md5() m.update(str.encode("utf8")) print(m.hexdigest())
sha 加密:安全雜湊演算法(Secure Hash Algorithm)
主要適用於數位簽名標準(Digital Signature Standard DSS)裏面定義的數位簽名演算法(Digital Signature Algorithm DSA),SHA1 比 MD5 的安全性更強。
對於長度小於 2^ 64 位元的訊息,SHA1 會產生一個 160 位元的訊息摘要。
import hashlib sha1 = hashlib.sha1() data = 'helloword' sha1.update(data.encode('utf-8')) sha1_data = sha1.hexdigest() print(sha1_data)
▍對稱加密演算法(AES、DES)
DES 加密
DES 是一個分組加密演算法,典型的 DES 以 64 位元爲分組對數據加密
加密和解密用的是同一個演算法。
它的金鑰長度是 56 位(因爲每個第 8 位都用作奇偶校驗),金鑰可以是任意的 56 位的數,而且可以任意時候改變。
from Cryptodome.Cipher import DES key = b'88888888' data = "Good Good Study! Day Day Up!" count = 8 - (len(data) % 8) plaintext = data + count * "=" # 金鑰 des = DES.new(key, DES.MODE_ECB) # 加密 ciphertext = des.encrypt(plaintext.encode()) print(ciphertext) >>> b'D\xa4Z\x1dt\xba\xf3\xe8\xdbv\x1aP\x81\xe4\xe6Jx?\xfe\xf2\x0b\x82\nG\x08d\xea\xd0\t\x07vs' # 解密 plaintext = des.decrypt(ciphertext) plaintext = plaintext[:(len(plaintext)-count)] print(plaintext) >>> b'Good Good Study! Day Day Up!'
AES 加密
在密碼學中又稱 Rijndael 加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的 DES
目前使用的比較廣泛,一串看不懂的字串如果有 / 我們首先想到的是 aes 加密
AES 只是個基本演算法,實現 AES 有幾種模式,主要有 ECB、CBC、CFB 和 OFB 這幾種(其實還有個 CTR)。
AES 爲分組密碼,分組密碼也就是把明文分成一組一組的,每組長度相等,每次加密一組數據,直到加密完整個明文。在 AES 標準規範中,分組長度只能是 128 位元,也就是說,每個分組爲 16 個位元組(每個位元組 8 位元)。金鑰的長度可以使用 128 位元、192 位或 256 位。金鑰的長度不同,推薦加密輪數也不同。
- AES ECB 模式加密方法 Python 實現:
from Crypto.Cipher import AES import base64 BLOCK_SIZE = 16 # Bytes pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * \ chr(BLOCK_SIZE - len(s) % BLOCK_SIZE) unpad = lambda s: s[:-ord(s[len(s) - 1:])] # AES的ECB模式加密方法 def aesEncrypt(key, data): ''' :param key: 金鑰 :param data:被加密字串(明文) :return:密文 ''' key = key.encode('utf8') # 字串補位 data = pad(data) cipher = AES.new(key, AES.MODE_ECB) # 加密後得到的是bytes型別的數據,使用Base64進行編碼,返回byte字串 result = cipher.encrypt(data.encode()) encodestrs = base64.b64encode(result) enctext = encodestrs.decode('utf8') print(enctext) return enctext # AES的ECB模式解密方法 def aesDecrypt(key, data): ''' :param key: 金鑰 :param data: 加密後的數據(密文) :return:明文 ''' key = key.encode('utf8') data = base64.b64decode(data) cipher = AES.new(key, AES.MODE_ECB) # 去補位 text_decrypted = unpad(cipher.decrypt(data)) text_decrypted = text_decrypted.decode('utf8') print(text_decrypted) return text_decrypted if __name__ == '__main__': key = '5c44c819appsapi0' data = 'herish acorn' ecdata = aesEncrypt(key, data) aesDecrypt(key, ecdata)
AES CBC 模式加密方法 Python 實現
from Crypto.Cipher import AES import base64 # 金鑰(key), 密斯偏移量(iv) CBC模式加密 BLOCK_SIZE = 16 # Bytes pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * \ chr(BLOCK_SIZE - len(s) % BLOCK_SIZE) unpad = lambda s: s[:-ord(s[len(s) - 1:])] vi = '0102030405060708' # 偏移量 # 加密 def AES_Encrypt(key, data): data = pad(data) # 字串補位 cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8')) encryptedbytes = cipher.encrypt(data.encode('utf8')) # 加密後得到的是bytes型別的數據,使用Base64進行編碼,返回byte字串 encodestrs = base64.b64encode(encryptedbytes) # 對byte字串按utf-8進行解碼 enctext = encodestrs.decode('utf8') return enctext # 解密 def AES_Decrypt(key, data): data = data.encode('utf8') encodebytes = base64.decodebytes(data) # 將加密數據轉換位bytes型別數據 cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8')) text_decrypted = cipher.decrypt(encodebytes) # 去補位 text_decrypted = unpad(text_decrypted) text_decrypted = text_decrypted.decode('utf8') print(text_decrypted) return text_decrypted if __name__ == '__main__': key = '5c44c819appsapi0' data = 'herish acorn' enctext = AES_Encrypt(key, data) print(enctext) AES_Decrypt(key, enctext)
▍非對稱加密演算法(RSA、DSA)
安裝第三方庫:
RSA 加密演算法是一種非對稱加密演算法。加密和解密使用不同的祕鑰。一把作爲公開的公鑰,另一把作爲私鑰。這對金鑰中的公鑰進行加密,私鑰用於解密。
事實上,公鑰加密演算法很少用於數據加密,它通常只是用來做身份認證,因爲它的金鑰太長,加密速度太慢–公鑰加密演算法的速度甚至比對稱加密演算法的速度慢上 3 個數量級(1000 倍)。
在公開金鑰加密和電子商業中 RSA 被廣泛使用。它被普遍認爲是目前最優秀的公鑰方案之一。RSA 是第一個能同時用於加密和數位簽名的演算法,它能夠抵抗到目前爲止已知的所有密碼攻擊。
import rsa # 返回 公鑰加密、私鑰解密 public_key, private_key = rsa.newkeys(1024) print(public_key) # PublicKey(115358647593237027749555219330290547595292720354379729059572469455025379115527291514465303947468690370446593609121177089794716265226101498361786298396410892325533861129676356325971818358112602498513419680609056457389715318966834362898086552554130435425753061655286667511557573410756120684188042377774434444807, 65537) print(private_key) # PrivateKey(115358647593237027749555219330290547595292720354379729059572469455025379115527291514465303947468690370446593609121177089794716265226101498361786298396410892325533861129676356325971818358112602498513419680609056457389715318966834362898086552554130435425753061655286667511557573410756120684188042377774434444807, 65537, 111285529956928522901721617280604228002764723117703733926382810265271061290888840676549733913221737511493431004615227720952917381576663793443813612330045581626681883557204892676718975967265771623672679503776812616315334112382868415864141371197836942710738341439472967902074841400226409659228441303650822610777, # 38470842708546405208704625508367712891471208299333441783981501073550023095274000403563916879641908231011170773153102126825952183163444780110955065002626432268349573, 2998599444966402616240989100234166167805477168671480027322013770416359562366030923233399853472241710845190991402502764232214027989568380839340059) plaintext = b"15863274538" ciphertext = rsa.encrypt(plaintext, public_key) print(ciphertext) # b'\x04\xb3ri\x1e\nA\xfb\x94\xff\xde{HtNw\xd4Q{\xdeRJ\xe0Fwl\x97kL\xde\xe6m\xc1\x8f\xd4\t\x96=\xb62\xad\x02\xfe\xeb4\xb4i\x8f\x9e\x0fp\x10\xbe\x8fiNrrUB\xbc\xe3\x87Q-\xe2\xa5\x86\xd9\x0b6,.\x90\xa1\xa6\x80\xf3\xaa\xcc\xdf7!\xdcp\xea\x0eE_?$\x8b\xcd\xb2\xca\x18\xf9e\xb5\x9b^\x84CcU\xe5.\xaeeFlz\xdeh\xb8\xa3D\xcb\xb6\xd5\x02\xe38\x98\xc80#Q' plaintext = rsa.decrypt(ciphertext, private_key) print(plaintext) # b'15863274538' # 私鑰加簽、公鑰驗签 plaintext = b"15863274538" sign_message = rsa.sign(plaintext, private_key, "MD5") plaintext = b"15863274538" method = rsa.verify(b"15863274532", sign_message, public_key) print(method) # rsa.pkcs1.VerificationError: Verification failed
▍補充演算法
Base64
目前 Base64 已經成爲網路上常見的傳輸 8Bit 位元組程式碼的編碼方式之一。
在做支付系統時,系統之間的報文互動都需要使用 Base64 對明文進行轉碼,然後再進行簽名或加密,之後再進行(或再次 Base64)傳輸。
Base64 在 URL、Cookie、網頁傳輸少量二進制檔案中也有相應的使用。
from base64 import b64encode, b64decode plaintext = "我的銀行卡密碼是020012" ciphertext = b64encode(plaintext.encode()) print(ciphertext) # b'5oiR55qE6ZO26KGM5Y2h5a+G56CB5pivMDIwMDEy' plaintext = b64decode(ciphertext) print(plaintext) # b'\xe6\x88\x91\xe7\x9a\x84\xe9\x93\xb6\xe8\xa1\x8c\xe5\x8d\xa1\xe5\xaf\x86\xe7\xa0\x81\xe6\x98\xaf020012' print(plaintext.decode()) # 我的銀行卡密碼是020012
ref
- https://tw511.com/a/01/8289.html#2_6