Python套件 – 加密演算法 – hashlib

hashlib提供不同的安全雜湊/安全雜湊(Secure Hash Algorithm)和 資訊摘要演算法(Message Digest Algorithm),hashlib模組支援業界主流常見的一些加密演算法,如md5、sha1、sha256、sha384、sha 512、hmac加密等。

hash

雜湊(Hash)算法是一種用在資料編碼中的技術。

EX: SecTools.tw -> hash generator -> 302e5748216d79c3dc6e37bcd2eeccbf

hash function

雜湊函式(英語:Hash function)又稱雜湊演算法,是一種從任何一種資料中建立小的數字「指紋」的方法。雜湊函式把訊息或資料壓縮成摘要,使得資料量變小,將資料的格式固定下來。該函式將資料打亂混合,重新建立一個叫做雜湊值(hash values,hash codes,hash sums,或hashes)的指紋。雜湊值通常用一個短的隨機字母和數字組成的字串來代表。[1]好的雜湊函式在輸入域中很少出現雜湊衝突。在雜湊表資料處理中,不抑制衝突來區別資料,會使得資料庫記錄更難找到。

如今,雜湊演算法也被用來加密存在資料庫中的密碼(password)字串,由於雜湊演算法所計算出來的雜湊值(Hash Value)具有不可逆(無法逆向演算回原本的數值)的性質,因此可有效的保護密碼。 – 取自維基百科

hashlib 支援演算法

sha()、sha224()、sha256()、sha384()、sha512()、blake2b()、sha3_224()、sha3_256()、sha3_384()、sha3_512()、shake_128()、shake_256()。

Hashlib現在使用來自OpenSSL 1.1.1和更高版本的SHA3和SHAKE。

訊息摘要

Secure Hash Algorithm(SHA)能計算出一個數位訊息所對應到,長度固定的字串(又稱訊息摘要)的演算法,計算出來的數位訊息是一個固定長度字串。

import hashlib
m = hashlib.sha256()
m.update(b"SecTools.tw is best platform")
print(m.digest())

得到的結果會是

b'\x05!I\xf0\xb6\x94.t\x96\xfc\xaaK\xf55\x86,>\xb2"s\xeb@\xdb\xb7\x01I\x89\xf5\x98\xe3$\x0f'

計算一下訊息摘要長度

print(m.digest_size) #32
print(m.block_size)  #64

這時同時對不同的明文進行加密,會發現兩者產生的字串長度是相同的。

import hashlib
m = hashlib.sha256()
m.update(b"SecTools.tw is best platform")
print(m.digest_size)
print(m.block_size)

m = hashlib.sha256()
m.update(b"SecTools.tw is the best")
print(m.digest_size)
print(m.block_size)

方法

hashlib.new(name, [data, ]*usedforsecurity=True)

選擇一個演算法。

h = hashlib.new('sha512_256')

hashlib.algorithms_guaranteed

顯示平台可用的hash演算法集合。

{'blake2s', 'shake_256', 'sha224', 'md5', 'shake_128', 'sha1', 'sha384', 'sha3_384', 'sha3_512', 'sha3_256', 'sha512', 'sha256', 'sha3_224', 'blake2b'}

hashlib.algorithms_available

當前python環境可用的演算法。 SecTools.tw 寫這篇文章時的環境是 Python 3.9.2

{'sha3_512', 'sha384', 'sm3', 'blake2s', 'ripemd160', 'md4', 'mdc2', 'sha3_384', 'sha512_224', 'shake_128', 'whirlpool', 'sha3_224', 'sha1', 'sha224', 'shake_256', 'sha512', 'sha3_256', 'sha256', 'md5-sha1', 'sha512_256', 'blake2b', 'md5'}

hash.digest_size

hash的大小。

hash.block_size

hash的內部塊大小。

屬性

hash.update(data)

將字串更新至hash目標。 data => “要加密的字串” 、 update 可以去做字串組合。

hash.update("SecTools.tw")
hash.update(" Ryan.Chen")
#實際上的結果是 "SecTools.tw Ryan.Chen"

hash.digest()

傳回當前數據的訊息摘要。

hash.hexdigest()

傳回當前數據的16進位制訊息摘要。

更多訊息可參考 https://docs.python.org/3/library/hashlib.html

hash可以用在哪?

因為不可逆的特性,可用於儲存用戶的密碼。 ( 存明碼的密碼在資料庫的話,開發者一點意識都沒有)

usernamepassword
Wutone10adc3949ba59abbeza6147f20f883e
Ryan123ef96e86145580cxxc87f0410ad153
SecTools.tw99b1c2188dza5sd2e403b1536010c2c9

實戰演練

keygenme-py

 | 30 pointsTags: Category: Reverse Engineering

AUTHOR: SYREAL

Description

keygenme-trial.py

解法

Flag只給一半,實際上是由靜態的字串組合動態變數產生。

key_full_template_trial = key_part_static1_trial + key_part_dynamic1_trial + key_part_static2_trial

動態金鑰

def check_key(key, username_trial):

    global key_full_template_trial

    if len(key) != len(key_full_template_trial):
        return False
    else:
        # Check static base key part --v
        i = 0
        for c in key_part_static1_trial:
            if key[i] != c:
                return False

            i += 1

        # TODO : test performance on toolbox container
        # Check dynamic part --v
        if key[i] != hashlib.sha256(username_trial).hexdigest()[4]:
            return False
        else:
            i += 1

        if key[i] != hashlib.sha256(username_trial).hexdigest()[5]:
            return False
        else:
            i += 1

        if key[i] != hashlib.sha256(username_trial).hexdigest()[3]:
            return False
        else:
            i += 1

        if key[i] != hashlib.sha256(username_trial).hexdigest()[6]:
            return False
        else:
            i += 1

        if key[i] != hashlib.sha256(username_trial).hexdigest()[2]:
            return False
        else:
            i += 1

        if key[i] != hashlib.sha256(username_trial).hexdigest()[7]:
            return False
        else:
            i += 1

        if key[i] != hashlib.sha256(username_trial).hexdigest()[1]:
            return False
        else:
            i += 1

        if key[i] != hashlib.sha256(username_trial).hexdigest()[8]:
            return False

        return True

簡單來說就是檢查第一部分是否正確,長度有沒有夠。之後動態金鑰hexdigest()[x]

x是數字,是不是跟我們前面提到的hexdigest()方法一樣,所以我們記錄數字。

分別是 4,5,3,6,2,7,1,8

知道原理後,開始寫solve.py

import hashlib
import base64


key_part_static1_trial = "picoCTF{1n_7h3_|<3y_of_"
key_part_dynamic1_trial = "xxxxxxxx"
key_part_static2_trial = "}"
key_full_template_trial = key_part_static1_trial + key_part_dynamic1_trial + key_part_static2_trial

username_trial = b"PRITCHARD"

potential_dynamic_key = ""

# where our input begins:
offset = 23

# positions in username_trial
positions = [4,5,3,6,2,7,1,8]

for p in positions:
	potential_dynamic_key += hashlib.sha256(username_trial).hexdigest()[p]

key = key_part_static1_trial + potential_dynamic_key + key_part_static2_trial
print(key)
print(len(key))

成果取得Flag且正確~。

Back To Top
error: 內容被保護 !!