Python中HMAC加密算法的應(yīng)用
HMAC 算法可用于驗證在應(yīng)用程序之間傳遞或存儲在潛在易受攻擊位置的信息的完整性。基本思想是生成與共享密鑰組合的實際數(shù)據(jù)的加密散列。然后,可以使用所得到的散列來檢查所發(fā)送或存儲的消息以確定信任級別,而不發(fā)送秘密密鑰。
簽名消息
new() 函數(shù)創(chuàng)建一個用于計算消息簽名的新對象。此示例使用默認(rèn)的 MD5 散列算法。
```python
hmac_simple.py
import hmac
digest_maker = hmac.new(b'secret-shared-key-goes-here')with open('lorem.txt', 'rb') as f:
while True:
block = f.read(1024)
if not block:
break
digest_maker.update(block)digest = digest_maker.hexdigest()print(digest)運(yùn)行時,代碼讀取數(shù)據(jù)文件并為其計算 HMAC 簽名。
$ python3 hmac_simple.py
4bcb287e284f8c21e87e14ba2dc40b16
可選的摘要類型
盡管默認(rèn)的 hmac 算法是 MD5,但那不是最安全的方法。MD5 摘要算法有一些缺點,例如碰撞?(兩個不同的消息產(chǎn)生了不同的哈希值)。SHA-1 被公認(rèn)為是比較健壯的,應(yīng)該使用它。
hmac_sha.py
import hmac
import hashlib
digest_maker = hmac.new(
b'secret-shared-key-goes-here',
b'',
hashlib.sha1,)with open('hmac_sha.py', 'rb') as f:
while True:
block = f.read(1024)
if not block:
breakdigest_maker.update(block)digest = digest_maker.hexdigest()print(digest)
new() 函數(shù)接受三個參數(shù)值,第一個是密鑰,共享于兩個通信的端點之間,所以兩個端點都使用相同的值。第二個參數(shù)是初始化消息值。如果需要認(rèn)證的消息內(nèi)容非常小,例如時間戳或者 HTTP POST,那么整個消息體可以傳入 new() 而不用 update() 方法。最后一個參數(shù)是要使用的摘要算法。默認(rèn)的是 hashlib.md5,例子中使用的是 hashlib.sha1。
$ python3 hmac_sha.py
dcee20eeee9ef8a453453f510d9b6765921cf099
二進(jìn)制摘要
前一個例子使用了 hexdigest() 方法生成可打印的摘要字符串。這個摘要字符串是由 digest() 方法生成的值的不同表現(xiàn)形式而已,這
hmac_base64.py
import base64
import hmac
import hashlib
with open('lorem.txt', 'rb') as f:
body = f.read()hash = hmac.new(
b'secret-shared-key-goes-here',
body,
hashlib.sha1,)digest = hash.digest()print(base64.encodestring(digest))base64 編碼的字符串以換行符結(jié)尾,當(dāng)將字符串嵌入到 HTTP 頭或者其他敏感的上下文中時,經(jīng)常需要將這個換行符刪除。
$ python3 hmac_base64.py
b'olW2DoXHGJEKGU0aE9fOwSVE/o4=\n'
消息簽名的應(yīng)用
HMAC 算法應(yīng)該用于任何公共網(wǎng)絡(luò)服務(wù),并且任何數(shù)據(jù)都應(yīng)該存儲在安全性很重要的地方。例如,當(dāng)數(shù)據(jù)被通過管道或者 socket 發(fā)送的時候,數(shù)據(jù)應(yīng)該被簽名,然后在使用之前驗簽。此處給出的擴(kuò)展示例位于文件 hmac_pickle.py。
第一步是創(chuàng)建一個函數(shù)計算一個字符串的摘要,以及一個簡單的類,用于實例化并通過通信通道傳遞。
hmac_pickle.py
import hashlib
import hmac
import io
import pickle
import pprint
def make_digest(message):
"Return a digest for the message."
hash = hmac.new(
b'secret-shared-key-goes-here',
message,
hashlib.sha1,
)
return hash.hexdigest().encode('utf-8')class SimpleObject:
"""Demonstrate checking digests before unpickling.
"""
def __init__(self, name):
self.name = name
def __str__(self):
return self.name接下來,創(chuàng)建一個 BytesIO 緩沖池代表一個 socket 或者管道。例子中使用了一個原生的,但是很容易解析的,格式化的數(shù)據(jù)流。首先數(shù)據(jù)的摘要和長度被寫入,后面緊跟了一個換行符。對象的序列化形式由 pickle 生成。真實的系統(tǒng)可能不希望依賴于長度值,因為如果摘要錯誤,則長度也是錯誤的。某些不太可能出現(xiàn)在實際數(shù)據(jù)中的終結(jié)符序列可能更加合適。
然后示例程序中往數(shù)據(jù)流中寫入了兩個對象。第一個是使用正確的摘要值寫入的。
使用緩沖區(qū)模擬可寫套接字或者管道
out_s = io.BytesIO()
往流中寫入一個有效的對象
digest\nlength\npickle
o = SimpleObject('digest matches')
pickled_data = pickle.dumps(o)
digest = make_digest(pickled_data)
header = b'%s %d\n' % (digest, len(pickled_data))
print('WRITING: {}'.format(header))
out_s.write(header)
out_s.write(pickled_data)第二個寫入流中的對象使用了一個無效的摘要值,摘要值是由其他一些數(shù)據(jù)生成的而不是序列化之后的值。
往流中寫入一個無效的對象
o = SimpleObject('digest does not match')
pickled_data = pickle.dumps(o)
digest = make_digest(b'not the pickled data at all')
header = b'%s %d\n' % (digest, len(pickled_data))
print('\nWRITING: {}'.format(header))
out_s.write(header)
out_s.write(pickled_data)
out_s.flush()記住數(shù)據(jù)是在 BytesIO 緩沖池中的,它可以再次被讀出。首先讀取帶有摘要和數(shù)據(jù)長度的行。然后使用長度值讀取剩下的數(shù)據(jù)。pickle.load() 可以直接從流中讀取數(shù)據(jù),但是它假設(shè)一個可信任的數(shù)據(jù)流,而且這個數(shù)據(jù)還不足夠可信能夠反序列化它。從流中讀取序列化值為字符串,而不實際反序列化更安全。
使用 BytesIO 模擬可讀的 socket 或者管道
in_s = io.BytesIO(out_s.getvalue())
讀取數(shù)據(jù)
while True:
first_line = in_s.readline()
if not first_line:
break
incoming_digest, incoming_length = first_line.split(b' ')
incoming_length = int(incoming_length.decode('utf-8'))
print('\nREAD:', incoming_digest, incoming_length)一旦序列化數(shù)據(jù)被讀取到內(nèi)存,摘要值可以被重新計算,并且使用 compare_digest() 同傳遞過來的數(shù)據(jù)比較。如果摘要匹配,證明它是安全的去信任數(shù)據(jù)并且反序列化它。
incoming_pickled_data = in_s.read(incoming_length)
actual_digest = make_digest(incoming_pickled_data)
print('ACTUAL:', actual_digest)
if hmac.compare_digest(actual_digest, incoming_digest):
obj = pickle.loads(incoming_pickled_data)
print('OK:', obj)
else:
print('WARNING: Data corruption')輸出表示第一個對象被驗證通過,第二個被視為「損壞」。
$ python3 hmac_pickle.py
WRITING: b'f49cd2bf7922911129e8df37f76f95485a0b52ca 69\n'
WRITING: b'b01b209e28d7e053408ebe23b90fe5c33bc6a0ec 76\n'
READ: b'f49cd2bf7922911129e8df37f76f95485a0b52ca' 69
ACTUAL: b'f49cd2bf7922911129e8df37f76f95485a0b52ca'
OK: digest matches
READ: b'b01b209e28d7e053408ebe23b90fe5c33bc6a0ec' 76
ACTUAL: b'2ab061f9a9f749b8dd6f175bf57292e02e95c119'
WARNING: Data corruption
可以在定時攻擊中使用簡單的字符串或字節(jié)比較來比較兩個摘要,以通過傳遞不同長度的摘要來暴露部分或全部秘密密鑰。compare_digest() 實現(xiàn)了一個快速但是常量時間的比較函數(shù)去防止定時攻擊。
到此這篇關(guān)于Python中HMAC加密算法的應(yīng)用的文章就介紹到這了,更多相關(guān)Python HMAC內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python?matplotlib繪圖時使用鼠標(biāo)滾輪放大/縮小圖像
Matplotlib是Python程序員可用的事實上的繪圖庫,雖然它比交互式繪圖庫在圖形上更簡單,但它仍然可以一個強(qiáng)大的工具,下面這篇文章主要給大家介紹了關(guān)于Python?matplotlib繪圖時使用鼠標(biāo)滾輪放大/縮小圖像的相關(guān)資料,需要的朋友可以參考下2022-05-05
Python 正則表達(dá)式 re.match/re.search/re.sub的使用解析
今天小編就為大家分享一篇Python 正則表達(dá)式 re.match/re.search/re.sub的使用解析,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-07-07
機(jī)器學(xué)習(xí)之?dāng)?shù)據(jù)清洗及六種缺值處理方式小結(jié)
本文主要介紹了機(jī)器學(xué)習(xí)之?dāng)?shù)據(jù)清洗及六種缺值處理方式小結(jié),包括刪除空行、填充平均值、中位數(shù)、眾數(shù)、線性插值和隨機(jī)森林填充,具有一定的參考價值,感興趣的可以了解一下2025-03-03
opencv-python+yolov3實現(xiàn)目標(biāo)檢測
因為最近的任務(wù)有用到目標(biāo)檢測,快速地了解了目標(biāo)檢測這一任務(wù),并且實現(xiàn)了使用opencv進(jìn)行目標(biāo)檢測。感興趣的可以了解一下2021-06-06
python?dowhy數(shù)據(jù)估計因果分析功能探索
這篇文章主要為大家介紹了python?dowhy數(shù)據(jù)估計因果分析功能實例探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-02-02
分位數(shù)回歸模型quantile regeression應(yīng)用詳解及示例教程
這篇文章主要為大家介紹了介紹了分位數(shù)回歸quantile regeression的概念詳解及代碼示例教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-11-11

