1
2
3
4 """Implementation of Poly1305 authenticator for RFC 7539"""
7
8 """Poly1305 authenticator"""
9
10 P = 0x3fffffffffffffffffffffffffffffffb
11
12 @staticmethod
14 """Convert a number from little endian byte format"""
15 ret = 0
16 for i in range(len(data) - 1, -1, -1):
17 ret <<= 8
18 ret += data[i]
19 return ret
20
21 @staticmethod
23 """Convert number to 16 bytes in little endian format"""
24 ret = [0]*16
25 for i, _ in enumerate(ret):
26 ret[i] = num & 0xff
27 num >>= 8
28 return bytearray(ret)
29
30 @staticmethod
32 """Integer division with rounding up"""
33 quot, r = divmod(divident, divisor)
34 return quot + int(bool(r))
35
37 """Set the authenticator key"""
38 if len(key) != 32:
39 raise ValueError("Key must be 256 bit long")
40 self.acc = 0
41 self.r = self.le_bytes_to_num(key[0:16])
42 self.r &= 0x0ffffffc0ffffffc0ffffffc0fffffff
43 self.s = self.le_bytes_to_num(key[16:32])
44
46 """Calculate authentication tag for data"""
47 for i in range(0, self.divceil(len(data), 16)):
48 n = self.le_bytes_to_num(data[i*16:(i+1)*16] + b'\x01')
49 self.acc += n
50 self.acc = (self.r * self.acc) % self.P
51 self.acc += self.s
52 return self.num_to_16_le_bytes(self.acc)
53