40 lines
972 B
Python
40 lines
972 B
Python
def clamp(r):
|
|
r = bytearray(r)
|
|
r[3] &= 15
|
|
r[7] &= 15
|
|
r[11] &= 15
|
|
r[15] &= 15
|
|
r[4] &= 252
|
|
r[8] &= 252
|
|
r[12] &= 252
|
|
return r
|
|
|
|
def ceildiv(a, b):
|
|
return a // b if a % b == 0 else a // b + 1
|
|
|
|
def leu(b):
|
|
n = 0
|
|
for i in range(len(b)):
|
|
n |= b[i] << (i * 8)
|
|
return n
|
|
|
|
def unleu128(n):
|
|
return bytes((n >> i) & 0xff for i in range(0, 128, 8))
|
|
|
|
def poly1305(message, key):
|
|
r = leu(clamp(key[:16]))
|
|
s = leu(key[16:])
|
|
P = 2**130 - 5
|
|
acc = 0
|
|
for i in range(ceildiv(len(message), 16)):
|
|
num = leu(message[i*16:i*16 + 16] + b'\x01')
|
|
# WARNING: This is most likely not timing-safe
|
|
acc = ((acc + num) * r) % P
|
|
acc += s
|
|
return unleu128(acc)
|
|
|
|
if __name__ == '__main__':
|
|
key = bytes.fromhex('85:d6:be:78:57:55:6d:33:7f:44:52:fe:42:d5:06:a8:01:03:80:8a:fb:0d:b2:fd:4a:bf:f6:af:41:49:f5:1b'.replace(':', ''))
|
|
message = b'Cryptographic Forum Research Group'
|
|
print(poly1305(message, key).hex() == 'a8:06:1d:c1:30:51:36:c6:c2:2b:8b:af:0c:01:27:a9'.replace(':', ''))
|