Skip to content

Poly1305

Poly1305

  • Bernstein's one-time authenticator
  • Uses a 128 bit nonce, 256 bit secret key and produces a tag 128 bits long.
  • is not random-key robust

Implementation

from cryptopals_lib import * 

#Info from http://loup-vaillant.fr/tutorials/poly1305-design
def poly1305_hash(key, message, output_size=16):
	#Set the mod p = 2^130-5
	p = 0x3fffffffffffffffffffffffffffffffb

	#Set some bits for r from spec and convert to little endian
	random = bytes_to_int(key[:16], False) & 0x0ffffffc0ffffffc0ffffffc0fffffff

	#Set secret part and convert to little endian
	secret = bytes_to_int(key[16:], False)

	hash_output = 0

	#Chunk the message into 128-bit ints
	for message_block in to_blocks(message, 16):
		#Set the first bit to 1 and convert to little endian
		message_int = bytes_to_int(message_block + bytes([1]), False)
		# Add the message into the hash accumulator
		hash_output += message_int
		# Multiply the hash by the random value taken from the input key
		hash_output *= random
		# Mod the value by 2^130-5 
		hash_output %= p
	
	#Finalize the hash by adding the secret derived from the key
	hash_output += secret
	#Set the output configurable size
	hash_output &= ((1 << output_size*8) -1)

	#Convert the little endian integer back into a bytestring
	return int_to_bytes(hash_output, False)

def poly1305(key, message, iv=None):
	#Generate IV if null
	if iv == None:
		iv = os.urandom(12)

	#Generate the Poly1305 key from the chacha keystream 
	poly_key = chacha_encrypt(iv, key, b'\x00' * 32)

	#Return the Randomly generated IV and message tag
	return iv, poly1305_hash(poly_key, message)

if __name__ == '__main__':

	#From https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
	key = bytes.fromhex("746869732069732033322d62797465206b657920666f7220506f6c7931333035")
	message = bytes.fromhex("0000000000000000000000000000000000000000000000000000000000000000")
	tag = poly1305_hash(key, message)
	print(f"TAG: {tag.hex()}")
	#TAG: 49ec78090e481ec6c26b33b91ccc0307

	#From https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
	key = bytes.fromhex("746869732069732033322d62797465206b657920666f7220506f6c7931333035")
	message = bytes.fromhex("48656c6c6f20776f726c6421")
	tag = poly1305_hash(key, message)
	print(f"TAG: {tag.hex()}")
	#TAG: a6f745008f81c916a20dcc74eef2b2f0