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