'''
# System --> Windows & Python3.8.0
# File ----> SHA-1.py
# Author --> Illusionna
# Create --> 2024/05/06 23:42:06
'''
# -*- Encoding: UTF-8 -*-


import os
import platform

def cls() -> None:
    os.system('')
    try:
        os.system(
            {'Windows': 'cls', 'Linux': 'clear'}[platform.system()]
        )
    except:
        print('\033[H\033[J', end='')
cls()

def SHA1(message:bytes) -> str:
    """SHA-1 摘要压缩算法.

    Args:
        message (bytes): 输入字节流.

    Returns:
        str: 长度为 40 的十六进制字符串.
    """
    # -------------------------------------------
    # 定义循环左移函数.
    L = lambda X, s:    ((X << s) | (X >> (32 - s))) & 0xffffffff
    # -------------------------------------------
    # 初始化五个幻数.
    H0 = 0x67452301
    H1 = 0xefcdab89
    H2 = 0x98badcfe
    H3 = 0x10325476
    H4 = 0xc3d2e1f0
    # -------------------------------------------
    # 零比特填充.
    N = len(message)    # 字节流长度.
    message = message + b'\x80'     # 尾部添加十六进制 80, 也就是十进制 128, 二进制 10000000.
    while (len(message) % 64) != 56:
        message = message + b'\x00'
    # -------------------------------------------
    # 有效信息比特流长度填充.
    """
    e.g.
        >>> N = 3
        >>> bytes = (N * 8).to_bytes(8, 'big')
        >>> bytes
        b'\x00\x00\x00\x00\x00\x00\x00\x18'
    十六进制 \x18 是十进制的 24, 也就是 24 比特位.
    big 是大端字节序, 字节按从最高有效位到最低有效位的顺序排列.
    """
    message = message + (N * 8).to_bytes(8, 'big')
    # -------------------------------------------
    # 加密迭代.
    for i in range(0, len(message), 64):
        W = [0 for __ in zip(range(0, 80, 1))]
        for j in range(0, 16, 1):
            W[j] = int.from_bytes(message[(i + j * 4):(i + j * 4 + 4)], 'big')
        for j in range(16, 80, 1):
            W[j] = L(W[j - 3] ^ W[j - 8] ^ W[j - 14] ^ W[j - 16], 1)
        a = H0; b = H1; c = H2; d = H3; e = H4
        for j in range(0, 80, 1):
            if 0 <= j <= 19:
                y = (b & c) | ((~b) & d)
                k = 0x5a827999
            elif 20 <= j <= 39:
                y = b ^ c ^ d
                k = 0x6ed9eba1
            elif 40 <= j <= 59:
                y = (b & c) | (b & d) | (c & d)
                k = 0x8f1bbcdc
            else:
                y = b ^ c ^ d
                k = 0xca62c1d6
            (a, b, c, d, e) = ((L(a, 5) + y + e + k + W[j]) & 0xffffffff, a, L(b, 30), c, d)
        H0 = (H0 + a) & 0xffffffff
        H1 = (H1 + b) & 0xffffffff
        H2 = (H2 + c) & 0xffffffff
        H3 = (H3 + d) & 0xffffffff
        H4 = (H4 + e) & 0xffffffff
    return '%08x%08x%08x%08x%08x' % (H0, H1, H2, H3, H4)


if __name__ == '__main__':
    print(SHA1(b'Ark'))
    import hashlib
    print(hashlib.sha1(b'Ark').hexdigest())