39 lines
1.4 KiB
Python
39 lines
1.4 KiB
Python
import binascii, ctypes, math, struct
|
|
|
|
class sha2_ctx(ctypes.Structure):
|
|
_fields_ = [("state", ctypes.c_uint32 * 8),
|
|
("count", ctypes.c_uint64),
|
|
("buf", ctypes.c_byte * 64)]
|
|
|
|
sodium = ctypes.CDLL("libsodium.so")
|
|
|
|
sodium.crypto_hash_sha256_init.argtypes = [ctypes.POINTER(sha2_ctx)]
|
|
sodium.crypto_hash_sha256_init.restype = ctypes.c_int
|
|
|
|
sodium.crypto_hash_sha256_update.argtypes = [ctypes.POINTER(sha2_ctx), ctypes.c_char_p,
|
|
ctypes.c_size_t]
|
|
sodium.crypto_hash_sha256_update.restype = ctypes.c_int
|
|
|
|
sodium.crypto_hash_sha256_final.argtypes = [ctypes.POINTER(sha2_ctx), ctypes.c_char_p]
|
|
sodium.crypto_hash_sha256_final.restype = ctypes.c_int
|
|
|
|
|
|
def hash_extend(orig_data_len, orig_hash, extend_data):
|
|
if isinstance(orig_hash, str):
|
|
orig_hash = binascii.unhexlify(orig_hash)
|
|
|
|
total_len = math.ceil((orig_data_len + 1 + 8) / 64) * 64
|
|
padding_len = total_len - orig_data_len - 1 - 8
|
|
padding = b"\x80" + (b"\x00" * padding_len) + struct.pack(">Q", orig_data_len*8)
|
|
|
|
ctx = sha2_ctx()
|
|
sodium.crypto_hash_sha256_init(ctx)
|
|
for i in range(8):
|
|
ctx.state[i] = struct.unpack(">I", orig_hash[i*4:(i+1)*4])[0]
|
|
ctx.count = total_len * 8
|
|
out_hash = ctypes.create_string_buffer(32)
|
|
sodium.crypto_hash_sha256_update(ctx, extend_data, len(extend_data))
|
|
sodium.crypto_hash_sha256_final(ctx, out_hash)
|
|
|
|
return padding + extend_data, bytes(out_hash)
|