Package tlslite :: Package utils :: Module chacha20_poly1305
[hide private]
[frames] | no frames]

Source Code for Module tlslite.utils.chacha20_poly1305

 1  # Copyright (c) 2015, Hubert Kario 
 2  # 
 3  # See the LICENSE file for legal information regarding use of this file. 
 4  """Pure Python implementation of ChaCha20/Poly1305 AEAD cipher 
 5   
 6  Implementation that follows RFC 7539 and draft-ietf-tls-chacha20-poly1305-00 
 7  """ 
 8   
 9  from __future__ import division 
10  from .chacha import ChaCha 
11  from .poly1305 import Poly1305 
12  import struct 
13 14 -class CHACHA20_POLY1305(object):
15 16 """Pure python implementation of ChaCha20/Poly1305 AEAD cipher""" 17
18 - def __init__(self, key, implementation):
19 """Set the initial state for the ChaCha20 AEAD""" 20 if len(key) != 32: 21 raise ValueError("Key must be 256 bit long") 22 if implementation != "python": 23 raise ValueError("Implementations other then python unsupported") 24 25 self.isBlockCipher = False 26 self.isAEAD = True 27 self.nonceLength = 12 28 self.tagLength = 16 29 self.implementation = implementation 30 self.name = "chacha20-poly1305" 31 self.key = key
32 33 @staticmethod
34 - def poly1305_key_gen(key, nonce):
35 """Generate the key for the Poly1305 authenticator""" 36 poly = ChaCha(key, nonce) 37 return poly.encrypt(bytearray(32))
38 39 @staticmethod
40 - def pad16(data):
41 """Return padding for the Associated Authenticated Data""" 42 if len(data) % 16 == 0: 43 return bytearray(0) 44 else: 45 return bytearray(16-(len(data)%16))
46
47 - def seal(self, nonce, plaintext, data):
48 """ 49 Encrypts and authenticates plaintext using nonce and data. Returns the 50 ciphertext, consisting of the encrypted plaintext and tag concatenated. 51 """ 52 if len(nonce) != 12: 53 raise ValueError("Nonce must be 96 bit large") 54 55 otk = self.poly1305_key_gen(self.key, nonce) 56 57 ciphertext = ChaCha(self.key, nonce, counter=1).encrypt(plaintext) 58 59 mac_data = data + self.pad16(data) 60 mac_data += ciphertext + self.pad16(ciphertext) 61 mac_data += struct.pack('<Q', len(data)) 62 mac_data += struct.pack('<Q', len(ciphertext)) 63 tag = Poly1305(otk).create_tag(mac_data) 64 65 return ciphertext + tag
66
67 - def open(self, nonce, ciphertext, data):
68 """ 69 Decrypts and authenticates ciphertext using nonce and data. If the 70 tag is valid, the plaintext is returned. If the tag is invalid, 71 returns None. 72 """ 73 if len(nonce) != 12: 74 raise ValueError("Nonce must be 96 bit long") 75 76 if len(ciphertext) < 16: 77 return None 78 79 expected_tag = ciphertext[-16:] 80 ciphertext = ciphertext[:-16] 81 82 otk = self.poly1305_key_gen(self.key, nonce) 83 84 mac_data = data + self.pad16(data) 85 mac_data += ciphertext + self.pad16(ciphertext) 86 mac_data += struct.pack('<Q', len(data)) 87 mac_data += struct.pack('<Q', len(ciphertext)) 88 tag = Poly1305(otk).create_tag(mac_data) 89 90 if tag != expected_tag: 91 return None 92 93 return ChaCha(self.key, nonce, counter=1).decrypt(ciphertext)
94