1. 程式人生 > 其它 >Python實現常見的幾種加密演算法(MD5,SHA-1,HMAC,DESAES,RSA和ECC)

Python實現常見的幾種加密演算法(MD5,SHA-1,HMAC,DESAES,RSA和ECC)

生活中我們經常會遇到一些加密演算法,今天我們就聊聊這些加密演算法的Python實現。部分常用的加密方法基本都有對應的Python庫,基本不再需要我們用程式碼實現具體演算法。

MD5加密

全稱:MD5訊息摘要演算法(英語:MD5 Message-Digest Algorithm),一種被廣泛使用的密碼雜湊函式,可以產生出一個128位(16位元組)的雜湊值(hash value),用於確保資訊傳輸完整一致。md5加密演算法是不可逆的,所以解密一般都是通過暴力窮舉方法,通過網站的介面實現解密。Python程式碼:


import hashlib
m = hashlib.md5()
m.update(str.encode("utf8"))
print(m.hexdigest())

SHA1加密

全稱:安全雜湊演算法(Secure Hash Algorithm)主要適用於數字簽名標準(Digital Signature Standard DSS)裡面定義的數字簽名演算法(Digital Signature Algorithm DSA),SHA1比MD5的安全性更強。對於長度小於2^ 64位的訊息,SHA1會產生一個160位的訊息摘要。Python程式碼:


import hashlib
sha1 = hashlib.sha1()
data = '2333333'
sha1.update(data.encode('utf-8'))
sha1_data = sha1.hexdigest()
print(sha1_data)

HMAC加密

全稱:雜湊訊息鑑別碼(Hash Message Authentication Code), HMAC加密演算法是一種安全的基於加密hash函式和共享金鑰的訊息認證協議。實現原理是用公開函式和金鑰產生一個固定長度的值作為認證標識,用這個標識鑑別訊息的完整性。使用一個金鑰生成一個固定大小的小資料塊,即 MAC,並將其加入到訊息中,然後傳輸。接收方利用與傳送方共享的金鑰進行鑑別認證等。Python程式碼:


import hmac
import hashlib
# 第一個引數是金鑰key,第二個引數是待加密的字串,第三個引數是hash函式
mac = hmac.new('key','hello',hashlib.md5)
mac.digest() # 字串的ascii格式
mac.hexdigest() # 加密後字串的十六進位制格式

DES加密

全稱:資料加密標準(Data Encryption Standard),屬於對稱加密演算法。DES是一個分組加密演算法,典型的DES以64位為分組對資料加密,加密和解密用的是同一個演算法。它的金鑰長度是56位(因為每個第8 位都用作奇偶校驗),金鑰可以是任意的56位的數,而且可以任意時候改變。Python程式碼:


import binascii
from pyDes import des, CBC, PAD_PKCS5
# 需要安裝 pip install pyDes

def des_encrypt(secret_key, s):
iv = secret_key
k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
en = k.encrypt(s, padmode=PAD_PKCS5)
return binascii.b2a_hex(en)

def des_decrypt(secret_key, s):
iv = secret_key
k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
de = k.decrypt(binascii.a2b_hex(s), padmode=PAD_PKCS5)
return de

secret_str = des_encrypt('12345678', 'I love YOU~')
print(secret_str)
clear_str = des_decrypt('12345678', secret_str)
print(clear_str)

AES加密

全稱:高階加密標準(英語:Advanced Encryption Standard),在密碼學中又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣為全世界所使用。Python程式碼:


import base64
from Crypto.Cipher import AES

'''
AES對稱加密演算法
'''
# 需要補位,str不是16的倍數那就補足為16的倍數
def add_to_16(value):
while len(value) % 16 != 0:
value += '\0'
return str.encode(value) # 返回bytes
# 加密方法
def encrypt(key, text):
aes = AES.new(add_to_16(key), AES.MODE_ECB) # 初始化加密器
encrypt_aes = aes.encrypt(add_to_16(text)) # 先進行aes加密
encrypted_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8') # 執行加密並轉碼返回bytes
return encrypted_text
# 解密方法
def decrypt(key, text):
aes = AES.new(add_to_16(key), AES.MODE_ECB) # 初始化加密器
base64_decrypted = base64.decodebytes(text.encode(encoding='utf-8')) # 優先逆向解密base64成bytes
decrypted_text = str(aes.decrypt(base64_decrypted), encoding='utf-8').replace('\0', '') # 執行解密密並轉碼返回str
return decrypted_text

RSA加密

全稱:Rivest-Shamir- Adleman,RSA加密演算法是一種非對稱加密演算法。在公開金鑰加密和電子商業中RSA被廣泛使用。它被普遍認為是目前比較優秀的公鑰方案之一。RSA是第一個能同時用於加密和數字簽名的演算法,它能夠抵抗到目前為止已知的所有密碼攻擊。Python程式碼:


# -*- coding: UTF-8 -*-
# reference codes: https://www.jianshu.com/p/7a4645691c68

import base64
import rsa
from rsa import common

# 使用 rsa庫進行RSA簽名和加解密
class RsaUtil(object):
PUBLIC_KEY_PATH = 'xxxxpublic_key.pem' # 公鑰
PRIVATE_KEY_PATH = 'xxxxxprivate_key.pem' # 私鑰

# 初始化key
def __init__(self,
company_pub_file=PUBLIC_KEY_PATH,
company_pri_file=PRIVATE_KEY_PATH):

if company_pub_file:
self.company_public_key = rsa.PublicKey.load_pkcs1_openssl_pem(open(company_pub_file).read())
if company_pri_file:
self.company_private_key = rsa.PrivateKey.load_pkcs1(open(company_pri_file).read())

def get_max_length(self, rsa_key, encrypt=True):
"""加密內容過長時 需要分段加密 換算每一段的長度.
:param rsa_key: 鑰匙.
:param encrypt: 是否是加密.
"""
blocksize = common.byte_size(rsa_key.n)
reserve_size = 11 # 預留位為11
if not encrypt: # 解密時不需要考慮預留位
reserve_size = 0
maxlength = blocksize - reserve_size
return maxlength

# 加密 支付方公鑰
def encrypt_by_public_key(self, message):
"""使用公鑰加密.
:param message: 需要加密的內容.
加密之後需要對接過進行base64轉碼
"""
encrypt_result = b''
max_length = self.get_max_length(self.company_public_key)
while message:
input = message[:max_length]
message = message[max_length:]
out = rsa.encrypt(input, self.company_public_key)
encrypt_result += out
encrypt_result = base64.b64encode(encrypt_result)
return encrypt_result

def decrypt_by_private_key(self, message):
"""使用私鑰解密.
:param message: 需要加密的內容.
解密之後的內容直接是字串,不需要在進行轉義
"""
decrypt_result = b""

max_length = self.get_max_length(self.company_private_key, False)
decrypt_message = base64.b64decode(message)
while decrypt_message:
input = decrypt_message[:max_length]
decrypt_message = decrypt_message[max_length:]
out = rsa.decrypt(input, self.company_private_key)
decrypt_result += out
return decrypt_result

# 簽名 商戶私鑰 base64轉碼
def sign_by_private_key(self, data):
"""私鑰簽名.
:param data: 需要簽名的內容.
使用SHA-1 方法進行簽名(也可以使用MD5)
簽名之後,需要轉義後輸出
"""
signature = rsa.sign(str(data), priv_key=self.company_private_key, hash='SHA-1')
return base64.b64encode(signature)

def verify_by_public_key(self, message, signature):
"""公鑰驗籤.
:param message: 驗籤的內容.
:param signature: 對驗籤內容簽名的值(簽名之後,會進行b64encode轉碼,所以驗籤前也需轉碼).
"""
signature = base64.b64decode(signature)
return rsa.verify(message, signature, self.company_public_key)

ECC加密

全稱:橢圓曲線加密(Elliptic Curve Cryptography),ECC加密演算法是一種公鑰加密技術,以橢圓曲線理論為基礎。利用有限域上橢圓曲線的點構成的Abel群離散對數難解性,實現加密、解密和數字簽名。將橢圓曲線中的加法運算與離散對數中的模乘運算相對應,就可以建立基於橢圓曲線的對應密碼體制。Python程式碼:


# -*- coding:utf-8 *-
# author: DYBOY
# reference codes: https://blog.dyboy.cn/websecurity/121.html
# description: ECC橢圓曲線加密演算法實現
"""
考慮K=kG ,其中K、G為橢圓曲線Ep(a,b)上的點,n為G的階(nG=O∞ ),k為小於n的整數。
則給定k和G,根據加法法則,計算K很容易但反過來,給定K和G,求k就非常困難。
因為實際使用中的ECC原則上把p取得相當大,n也相當大,要把n個解點逐一算出來列成上表是不可能的。
這就是橢圓曲線加密演算法的數學依據
點G稱為基點(base point)
k(k<n)為私有金鑰(privte key)
K為公開金鑰(public key)
"""

def get_inverse(mu, p):
"""
獲取y的負元
"""
for i in range(1, p):
if (i*mu)%p == 1:
return i
return -1

def get_gcd(zi, mu):
"""
獲取最大公約數
"""
if mu:
return get_gcd(mu, zi%mu)
else:
return zi

def get_np(x1, y1, x2, y2, a, p):
"""
獲取n*p,每次+p,直到求解階數np=-p
"""
flag = 1 # 定義符號位(+/-)

# 如果 p=q k=(3x2+a)/2y1mod p
if x1 == x2 and y1 == y2:
zi = 3 * (x1 ** 2) + a # 計算分子 【求導】
mu = 2 * y1 # 計算分母

# 若P≠Q,則k=(y2-y1)/(x2-x1) mod p
else:
zi = y2 - y1
mu = x2 - x1
if zi* mu <