Poly1305 is a fast Carter-Wegman MAC algorithm created by Daniel J. Bernstein. It requires a 32-byte secret key, a 16-byte nonce, and a symmetric cipher. The MAC tag is always 16 bytes long.
Originally, Poly1305 was defined in combination with ../cipher/aes
, but it is now most frequently seen used in combination with ../cipher/chacha20
.
This is an example showing how to generate a MAC tag (note how the nonce is automatically generated at random):
>>> from Crypto.Hash import Poly1305
>>> from Crypto.Cipher import AES
>>>
>>> secret = b'Thirtytwo very very secret bytes'
>>> mac = Poly1305.new(key=secret, cipher=AES)
>>> mac.update(b'Hello')
>>> print("Nonce: ", mac.nonce.hex())
>>> print("MAC: ", mac.hexdigest())
This is an example showing how to validate the MAC above:
>>> from Crypto.Hash import Poly1305
>>> from Crypto.Cipher import AES
>>> from binascii import unhexlify
>>>
>>> # We have received a message 'msg' together
>>> # with its MAC 'mac_tag_hex' and the nonce 'nonce_hex'
>>>
>>> secret = b'Thirtytwo very very secret bytes'
>>> nonce = unhexlify(nonce_hex)
>>> mac = Poly1305.new(key=secret, nonce=nonce, cipher=AES, data=msg)
>>> try:
>>> mac.hexverify(mac_tag_hex)
>>> print("The message '%s' is authentic" % msg)
>>> except ValueError:
>>> print("The message or the key is wrong")
Note that you can get the MAC tag in one line:
>>> binary_tag = Poly1305.new(key=secret, cipher=AES, data=b'Hello').digest()
Or, for a hexadecimal string:
>>> hex_tag = Poly1305.new(key=secret, cipher=AES, data=b'Hello').hexdigest()
Equivalently, you can verify a tag with a single line:
>>> Poly1305.new(key=secret, cipher=AES, data=b'Hello').verify(binary_tag)
or:
>>> Poly1305.new(key=secret, cipher=AES, data=b'Hello').hexverify(hex_tag)
Crypto.Hash.Poly1305