mirror of
https://github.com/morgan9e/noiseprotocol
synced 2026-04-14 00:14:05 +09:00
Prepare for public release
- Added readme - Updated setup.py - Removed pytest from requirements, added version of cryptography package - Small improvements in code: noise/noise_protocol.py: * removed unused one_way variable noise/patterns.py * fixed has_pre_messages - no longer a variable, but method - and now works properly noise/state.py * SymmetricState now holds reference to CipherState.
This commit is contained in:
99
README.md
99
README.md
@@ -1,2 +1,97 @@
|
||||
Noise-python
|
||||
============
|
||||
noiseprotocol
|
||||
=============
|
||||
|
||||
This repository contains source code of **noiseprotocol** - a Python 3 implementation of [Noise Protocol Framework](http://www.noiseprotocol.org/).
|
||||
|
||||
### Warning
|
||||
This package shall not be used (yet) for production purposes. There was little to none peer review done so far.
|
||||
Use common sense while using - until this package becomes stable.
|
||||
|
||||
## Installation and prerequisites
|
||||
For now, only Python 3.6 is supported.
|
||||
|
||||
Install via pip:
|
||||
```
|
||||
pip install noiseprotocol
|
||||
```
|
||||
*noiseprotocol* depends on [Cryptography](https://github.com/pyca/cryptography/) package (and its' pre-packaged OpenSSL v1.1) as a source of crypto-primitives.
|
||||
|
||||
## Usage
|
||||
|
||||
#### Basic usage
|
||||
NoiseBuilder class provides highest level of abstraction for the package. You can access full functionality of the package
|
||||
through this class' interfaces. An example for setting up NoiseBuilder could look like this:
|
||||
|
||||
```python
|
||||
from noise.builder import NoiseBuilder
|
||||
|
||||
# Create instance of NoiseBuilder, set up to use NN handshake pattern, Curve25519 for
|
||||
# elliptic curve keypair, ChaCha20Poly1305 as cipher function and SHA256 for hashing.
|
||||
proto = NoiseBuilder.from_name('Noise_NN_25519_ChaChaPoly_SHA256')
|
||||
|
||||
# Set role in this connection as initiator
|
||||
proto.set_as_initiator()
|
||||
# Enter handshake mode
|
||||
proto.start_handshake()
|
||||
|
||||
# Perform handshake - as we are the initiator, we need to generate first message.
|
||||
# We don't provide any payload (although we could, but it would be cleartext for this pattern).
|
||||
message = proto.write_message()
|
||||
# Send the message to the responder - you may simply use sockets or any other way
|
||||
# to exchange bytes between communicating parties.
|
||||
# For clarity - we omit socket creation in this example.
|
||||
sock.send(message)
|
||||
# Receive the message from the responder
|
||||
received = sock.recv()
|
||||
# Feed the received message into noise
|
||||
payload = proto.read_message(received)
|
||||
|
||||
# As of now, the handshake should be finished (as we are using NN pattern).
|
||||
# Any further calls to write_message or read_message would raise NoiseHandshakeError exception.
|
||||
# We can use encrypt/decrypt methods of NoiseBuilder now for encryption and decryption of messages.
|
||||
encrypted_message = proto.encrypt('This is an example payload')
|
||||
|
||||
ciphertext = sock.recv()
|
||||
plaintext = proto.decrypt(ciphertext)
|
||||
```
|
||||
|
||||
#### Wireguard integration example
|
||||
In *examples* directory, there is an example of interoperation of this package with Wireguard VPN solution. Please refer to [README.md](examples/wireguard/README.md) of that example for details.
|
||||
|
||||
----
|
||||
## Bug reports
|
||||
This software was tested only on Linux. It may or may not work on Windows, explicit support for this system will be added in future.
|
||||
|
||||
Please file any bug reports in project's [issue tracker](https://github.com/plizonczyk/noiseprotocol/issues).
|
||||
|
||||
## Development & contributing
|
||||
The only additional package that may be useful during development is pytest - for unit testing.
|
||||
Installation:
|
||||
|
||||
```
|
||||
pip install pytest
|
||||
```
|
||||
|
||||
Running tests (from root directory):
|
||||
```
|
||||
pytest
|
||||
```
|
||||
|
||||
### Todo-list for the project:
|
||||
|
||||
- [ ] fallback patterns support
|
||||
- [ ] documentation on Read the Docs and more extensive readme
|
||||
- [ ] scripts for keypair generation (+ console entry points)
|
||||
- [ ] "echo" (noise-c like) example
|
||||
- [ ] extensive logging
|
||||
- [ ] bringing back Python 3.5 support and supporting Python 3.7 (dependent on Cryptography package updates)
|
||||
- [ ] move away from custom ed448 implementation
|
||||
- [ ] implement countermeasures for side-channel attacks
|
||||
- [ ] **get peer review of the code**
|
||||
|
||||
You are more than welcome to propose new things to this list and/or implement them and file a merge request.
|
||||
|
||||
Contact the author: plizonczyk.public [at] gmail.com
|
||||
|
||||
## License
|
||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||
|
||||
@@ -50,7 +50,6 @@ class NoiseProtocol(object):
|
||||
|
||||
self.prologue = None
|
||||
self.initiator = None
|
||||
self.one_way = False
|
||||
self.handshake_hash = None
|
||||
|
||||
self.handshake_state = Empty()
|
||||
|
||||
@@ -20,10 +20,12 @@ class Pattern(object):
|
||||
self.tokens = []
|
||||
|
||||
self.name = ''
|
||||
self.has_pre_messages = any(map(lambda x: len(x) > 0, self.pre_messages))
|
||||
self.one_way = False
|
||||
self.psk_count = 0
|
||||
|
||||
def has_pre_messages(self):
|
||||
return any(map(lambda x: len(x) > 0, self.pre_messages))
|
||||
|
||||
def get_initiator_pre_messages(self) -> list:
|
||||
return self.pre_messages[0].copy()
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ class SymmetricState(object):
|
||||
self.h = None
|
||||
self.ck = None
|
||||
self.noise_protocol = None
|
||||
self.cipher_state = None
|
||||
|
||||
@classmethod
|
||||
def initialize_symmetric(cls, noise_protocol: 'NoiseProtocol') -> 'SymmetricState':
|
||||
@@ -103,9 +104,9 @@ class SymmetricState(object):
|
||||
instance.ck = instance.h
|
||||
|
||||
# Calls InitializeKey(empty).
|
||||
cipher_state = CipherState(noise_protocol)
|
||||
cipher_state.initialize_key(Empty())
|
||||
noise_protocol.cipher_state_handshake = cipher_state
|
||||
instance.cipher_state = CipherState(noise_protocol)
|
||||
instance.cipher_state.initialize_key(Empty())
|
||||
noise_protocol.cipher_state_handshake = instance.cipher_state
|
||||
|
||||
return instance
|
||||
|
||||
@@ -121,7 +122,7 @@ class SymmetricState(object):
|
||||
temp_k = temp_k[:32]
|
||||
|
||||
# Calls InitializeKey(temp_k).
|
||||
self.noise_protocol.cipher_state_handshake.initialize_key(temp_k)
|
||||
self.cipher_state.initialize_key(temp_k)
|
||||
|
||||
def mix_hash(self, data: bytes):
|
||||
"""
|
||||
@@ -139,7 +140,7 @@ class SymmetricState(object):
|
||||
if self.noise_protocol.hash_fn.hashlen == 64:
|
||||
temp_k = temp_k[:32]
|
||||
# Calls InitializeKey(temp_k).
|
||||
self.noise_protocol.cipher_state_handshake.initialize_key(temp_k)
|
||||
self.cipher_state.initialize_key(temp_k)
|
||||
|
||||
def encrypt_and_hash(self, plaintext: bytes) -> bytes:
|
||||
"""
|
||||
@@ -148,7 +149,7 @@ class SymmetricState(object):
|
||||
:param plaintext: bytes sequence
|
||||
:return: ciphertext bytes sequence
|
||||
"""
|
||||
ciphertext = self.noise_protocol.cipher_state_handshake.encrypt_with_ad(self.h, plaintext)
|
||||
ciphertext = self.cipher_state.encrypt_with_ad(self.h, plaintext)
|
||||
self.mix_hash(ciphertext)
|
||||
return ciphertext
|
||||
|
||||
@@ -159,7 +160,7 @@ class SymmetricState(object):
|
||||
:param ciphertext: bytes sequence
|
||||
:return: plaintext bytes sequence
|
||||
"""
|
||||
plaintext = self.noise_protocol.cipher_state_handshake.decrypt_with_ad(self.h, ciphertext)
|
||||
plaintext = self.cipher_state.decrypt_with_ad(self.h, ciphertext)
|
||||
self.mix_hash(ciphertext)
|
||||
return plaintext
|
||||
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
pytest>=3.2.2
|
||||
cryptography==2.0.3
|
||||
|
||||
18
setup.py
18
setup.py
@@ -8,13 +8,13 @@ with open(path.join(here, 'README.md'), encoding='utf-8') as f:
|
||||
long_description = f.read()
|
||||
|
||||
setup(
|
||||
name='noise-python',
|
||||
name='noiseprotocol',
|
||||
version='0.1.0',
|
||||
description='A sample Python project', # TODO
|
||||
description='Implementation of Noise Protocol Framework',
|
||||
long_description=long_description,
|
||||
url='https://github.com/plizonczyk/',
|
||||
url='https://github.com/plizonczyk/noiseprotocol',
|
||||
author='Piotr Lizonczyk',
|
||||
author_email='piotr.lizonczyk@gmail.com',
|
||||
author_email='plizonczyk.public@gmail.com',
|
||||
license='MIT',
|
||||
classifiers=[
|
||||
'Development Status :: 3 - Alpha',
|
||||
@@ -22,10 +22,12 @@ setup(
|
||||
'Topic :: Security :: Cryptography',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
# 'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
# 'Programming Language :: Python :: 3.7',
|
||||
],
|
||||
keywords='', # TODO
|
||||
packages=find_packages(exclude=['contrib', 'docs', 'tests']),
|
||||
install_requires=[], # TODO
|
||||
keywords='cryptography noiseprotocol noise security',
|
||||
packages=find_packages(exclude=['contrib', 'docs', 'tests', 'examples']),
|
||||
install_requires=['cryptography==2.0.3'],
|
||||
python_requires='~=3.6',
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user