Python實現常見的加密演算法

2020-08-11 18:16:26

一、什麼叫數據加密

數據加密是指利用加密演算法和祕鑰將明文轉變爲密文的過程。常見的加密方式有 base64 RSA MD5 SHA-1,HMAC,DES/AES,ECC

二、數據加密的方式

1、單向加密

指只能加密數據而不能解密數據,這種加密方式主要是爲了保證數據的完整性,常見的加密演算法有MD5、sha系列等(位於python內建的hashlib模組中)。

2、對稱加密

指數據加密和解密使用相同的祕鑰,這種加密方式主要是爲了保證數據的機密性,常見的加密演算法有DES、AES(位於python第三方庫pycrytodomex中)。

3、非對稱加密

也叫公鑰加密,指數據加密和解密使用不同的金鑰,這種加密方式基本不可能被破解,主要用於身份驗證等方面,常見的加密演算法有DSA、RSA(位於python第三方模組rsa中)。

三、加密演算法

1、單向加密演算法(MD5、sha系列)不可逆

MD5加密:
MD5訊息摘要演算法(英語:MD5 Message-Digest Algorithm),一種被廣泛使用的密碼雜湊函數,可以產生出一個128位元(16位元組)的雜湊值(hash value),用於確保資訊傳輸完整一致。md5加密演算法是不可逆的,所以解密一般都是通過暴力窮舉方法,通過網站的介面實現解密。
Python實現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)
2、對稱加密演算法(AES、DES)
  • 安裝第三方庫:
    pip install pycryptodomex -i https://pypi.douban.com/simple
    常見對稱密碼在 Crypto.Cipher 庫下,主要有:DES DES3 AES。按照時間發展順序是:DES->DES3->AES
    非對稱密碼在 Crypto.PublicKey 庫下,主要有:RSA ECC DSA
    雜湊密碼(單向加密)在 Crypto.Hash 庫下,常用的有:MD5 SHA-1 SHA-128 SHA-256
    亂數在 Crypto.Random 庫下
    實用小工具在 Crypto.Util 庫下
    數位簽名在 Crypto.Signature 庫下
  • 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)。本章主要介紹最常用的 ECB 和 CBC 模式。
AES爲分組密碼,分組密碼也就是把明文分成一組一組的,每組長度相等,每次加密一組數據,直到加密完整個明文。在AES標準規範中,分組長度只能是128位元,也就是說,每個分組爲16個位元組(每個位元組8位元)。金鑰的長度可以使用128位元、192位或256位。金鑰的長度不同,推薦加密輪數也不同。
AESECB模式加密方法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:])]


def aesEncrypt(key, data):
    '''
    AES的ECB模式加密方法
    :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
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)

AESCBC模式加密方法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)
3、非對稱加密演算法(RSA、DSA)
  • 安裝第三方庫:
    pip install rsa -i https://pypi.douban.com/simple

RSA加密演算法是一種非對稱加密演算法。在公開金鑰加密和電子商業中RSA被廣泛使用。它被普遍認爲是目前最優秀的公鑰方案之一。RSA是第一個能同時用於加密和數位簽名的演算法,它能夠抵抗到目前爲止已知的所有密碼攻擊。

加密和解密使用不同的祕鑰。 一把作爲公開的公鑰,另一把作爲私鑰。這對金鑰中的公鑰進行加密,私鑰用於解密。 事實上,公鑰加密演算法很少用於數據加密,它通常只是用來做身份認證,因爲它的金鑰太長,加密速度太慢–公鑰加密演算法的速度甚至比對稱加密演算法的速度慢上3個數量級(1000倍)。

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
4、補充演算法(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