/ python-oneliners / SHA1 / sha1.py
sha1.py
 1  def left_rotate(n: int, b: int) -> int:
 2      return ((n << b) | (n >> (32 - b))) & 0xffffffff
 3  
 4  
 5  def sha1(data: bytes) -> bytes:
 6      h = [
 7          0x67452301,
 8          0xEFCDAB89,
 9          0x98BADCFE,
10          0x10325476,
11          0xC3D2E1F0
12      ]
13      message = data + b'\x80'
14      message += b'\x00' * ((56 - len(message) % 64) % 64)
15      message += (len(data) * 8).to_bytes(8, 'big')
16      for i_ in range(len(message) // 64):
17          chunk = message[i_ * 64:(i_ + 1) * 64]
18          w = [int.from_bytes(chunk[i * 4:(i + 1) * 4], 'big') for i in range(16)]
19          for i in range(64):
20              w.append(left_rotate(w[-3] ^ w[-8] ^ w[-14] ^ w[-16], 1))
21          a, b, c, d, e = h
22          for i in range(80):
23              if i < 20:
24                  f = d ^ (b & (c ^ d))
25                  k = 0x5A827999
26              elif i < 40:
27                  f = b ^ c ^ d
28                  k = 0x6ED9EBA1
29              elif i < 60:
30                  f = (b & c) | (b & d) | (c & d)
31                  k = 0x8F1BBCDC
32              else:
33                  f = b ^ c ^ d
34                  k = 0xCA62C1D6
35              a, b, c, d, e = (left_rotate(a, 5) + f + e + k + w[i]) & 0xffffffff, a, left_rotate(b, 30), c, d
36          h = [(x + y) & 0xffffffff for x, y in zip(h, [a, b, c, d, e])]
37      return b''.join([x.to_bytes(4, 'big') for x in h])