import string import t, c # ============================================== # SHA1 哈希算法 # ============================================== SHA1_BLOCK_LEN: t.CDefine = 64 SHA1_DIGEST_LEN: t.CDefine = 20 def sha1_rotl(x: t.CUInt32T, n: t.CInt) -> t.CUInt32T: return (x << n) | (x >> (32 - n)) # 三轮逻辑函数 def sha1_f1(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: return (b & c) | (~b & d) def sha1_f2(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: return b ^ c ^ d def sha1_f3(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: return (b & c) | (b & d) | (c & d) # SHA1 上下文 @t.Object class sha1: state: t.CArray[t.CUInt32T, 5] count: t.CUInt64T buf: t.CArray[t.CUInt8T, SHA1_BLOCK_LEN] def __init__(self): memset(self.buf, 0, SHA1_BLOCK_LEN) self.state[0] = 0x67452301 self.state[1] = 0xefcdab89 self.state[2] = 0x98badcfe self.state[3] = 0x10325476 self.state[4] = 0xc3d2e1f0 self.count = 0 # 单分组压缩 def transform(self, block: t.CUInt8T | t.CPtr): w: t.CArray[t.CUInt32T, 80] data: t.CUInt8T | t.CPtr = block # 前16个字 for i in range(16): w[i] = (((t.CUInt32T(data[i * 4 + 0])) << 24) | ((t.CUInt32T(data[i * 4 + 1])) << 16) | ((t.CUInt32T(data[i * 4 + 2])) << 8) | ((t.CUInt32T(data[i * 4 + 3])) << 0)) # 扩展到80个字 for i in range(16, 80): w[i] = sha1_rotl(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16],1) a: t.CUInt32T = self.state[0] b: t.CUInt32T = self.state[1] c: t.CUInt32T = self.state[2] d: t.CUInt32T = self.state[3] e: t.CUInt32T = self.state[4] k: t.CUInt32T tmp: t.CUInt32T # 4轮迭代 for i in range(0, 20): k = 0x5a827999 tmp = sha1_rotl(a,5) + sha1_f1(b, c, d) + e + k + w[i] e = d; d = c c = sha1_rotl(b, 30) b = a; a = tmp for i in range(20, 40): k = 0x6ed9eba1 tmp = sha1_rotl(a,5) + sha1_f2(b, c, d) + e + k + w[i] e = d; d = c c = sha1_rotl(b, 30) b = a; a = tmp for i in range(40, 60): k = 0x8f1bbcdc tmp = sha1_rotl(a,5) + sha1_f3(b, c, d) + e + k + w[i] e = d; d = c c = sha1_rotl(b, 30) b = a; a = tmp for i in range(60, 80): k = 0xca62c1d6 tmp = sha1_rotl(a,5) + sha1_f2(b, c, d) + e + k + w[i] e = d; d = c c = sha1_rotl(b, 30) b = a; a = tmp self.state[0] += a self.state[1] += b self.state[2] += c self.state[3] += d self.state[4] += e def update(self, s: str): data: t.CUInt8T | t.CPtr = t.CUInt8T(s, t.CPtr) length: t.CSizeT = len(s) idx: t.CSizeT = self.count % SHA1_BLOCK_LEN self.count += length if idx > 0: left: t.CSizeT = SHA1_BLOCK_LEN - idx if length >= left: memcpy(self.buf + idx, data, left) self.transform(self.buf) data += left length -= left idx = 0 while length >= SHA1_BLOCK_LEN: self.transform(data) data += SHA1_BLOCK_LEN length -= SHA1_BLOCK_LEN if length > 0: memcpy(self.buf + idx, data, length) def final(self, out: t.CArray[t.CUInt8T, SHA1_DIGEST_LEN]): idx: t.CSizeT = self.count % SHA1_BLOCK_LEN self.buf[idx] = 0x80 idx += 1 if idx > SHA1_BLOCK_LEN - 8: memset(self.buf + idx, 0, SHA1_BLOCK_LEN - idx) self.transform(self.buf) idx = 0 memset(self.buf + idx,0,SHA1_BLOCK_LEN-8-idx) bits: t.CUInt64T = self.count << 3 # SHA1 大端写入长度 for i in range(8): self.buf[SHA1_BLOCK_LEN - 8 + i] = (bits >> (56 - i * 8)) & 0xFF self.transform(self.buf) # 大端输出摘要 for i in range(5): out[i * 4 + 0] = (self.state[i] >> 24) & 0xFF out[i * 4 + 1] = (self.state[i] >> 16) & 0xFF out[i * 4 + 2] = (self.state[i] >> 8) & 0xFF out[i * 4 + 3] = (self.state[i] >> 0) & 0xFF