Implementing NoiseProtocol (WIP), binding crypto

noise/noise_protocol.py - added maps of cryptofunctions that will be
used, finished protocol name splitting

noise/patterns.py - added map of patterns

requirements.txt - switching to pycryptodome as a source of cipher and
hashing functions, and ed25519 package for that curve
This commit is contained in:
Piotr Lizonczyk
2017-08-09 23:55:32 +02:00
parent 5cb448369c
commit de73505ac3
3 changed files with 79 additions and 6 deletions

View File

@@ -1,19 +1,72 @@
from functools import partial
from .patterns import patterns_map
from .constants import MAX_PROTOCOL_NAME_LEN
from Crypto.Cipher import AES, ChaCha20
from Crypto.Hash import BLAKE2b, BLAKE2s, SHA256, SHA512
import ed25519
dh_map = {
'25519': ed25519.create_keypair,
'448': None # TODO implement
}
cipher_map = {
'AESGCM': partial(AES.new, mode=AES.MODE_GCM),
'ChaChaPoly': lambda key: ChaCha20.new(key=key)
}
hash_map = {
'BLAKE2b': BLAKE2b, # TODO PARTIALS
'BLAKE2s': BLAKE2s, # TODO PARTIALS
'SHA256': SHA256, # TODO PARTIALS
'SHA512': SHA512 # TODO PARTIALS
}
class NoiseProtocol(object):
methods = {
'pattern': patterns_map,
'dh': dh_map,
}
def __init__(self, protocol_name: bytes):
if len(protocol_name) > MAX_PROTOCOL_NAME_LEN:
raise Exception('Protocol name too long, has to be at most {} chars long'.format(MAX_PROTOCOL_NAME_LEN))
raise ValueError('Protocol name too long, has to be at most {} chars long'.format(MAX_PROTOCOL_NAME_LEN))
self.pattern = None
self.name = protocol_name
data_dict = self._split_protocol_name()
self.pattern = patterns_map[data_dict['pattern']]
self.pattern_modifiers = None
self.dh = None
self.dh_modifiers = None
self.cipher = None
self.cipher_modifiers = None
self.hash = None
self.hash_modifiers = None
def _split_protocol_name(self):
unpacked = self.name.split('_')
if unpacked[0] != 'Noise':
raise ValueError(f'Noise protocol name shall begin with Noise! Provided: {self.name}')
pattern = ''
modifiers_str = None
for i, char in enumerate(unpacked[1]):
if char.isupper():
pattern += char
else:
modifiers_str = unpacked[1][i+1:] # Will be empty string if it exceeds string size
break
modifiers = modifiers_str.split('+') if modifiers_str else []
data = {'pattern': 'Pattern' + pattern,
'dh': unpacked[2],
'cipher': unpacked[3],
'hash': unpacked[4],
'pattern_modifiers': modifiers}
# Validate if we know everything that Noise Protocol is supposed to use
# TODO validation
return data
class KeyPair(object):

View File

@@ -168,3 +168,22 @@ class PatternIX(Pattern):
[TOKEN_E, TOKEN_S],
[TOKEN_E, TOKEN_EE, TOKEN_SE, TOKEN_S, TOKEN_ES]
]
patterns_map = {
'PatternN': PatternN,
'PatternK': PatternN,
'PatternX': PatternN,
'PatternNN': PatternNN,
'PatternKN': PatternKN,
'PatternNK': PatternNK,
'PatternKK': PatternKK,
'PatternNX': PatternNX,
'PatternKX': PatternKX,
'PatternXN': PatternXN,
'PatternIN': PatternIN,
'PatternXK': PatternXK,
'PatternIK': PatternIK,
'PatternXX': PatternXX,
'PatternIX': PatternIX,
}

View File

@@ -1,2 +1,3 @@
pytest
pynacl
pycryptodome
ed25519