Coder Social home page Coder Social logo

tgalal / dissononce Goto Github PK

View Code? Open in Web Editor NEW
45.0 6.0 15.0 665 KB

A python implementation for Noise Protocol Framework

License: MIT License

Python 100.00%
cryptography crypto-library handshake-protocol noise-protocol noise-protocol-framework

dissononce's Introduction

Dissononce

Build Status PyPI

Dissononce is a python implementation for Noise Protocol Framework. A main goal of this project is to provide a simple, easy to read and understand practical reference for Noise enthusiasts, implementers and users. Therefore this project attempts to stick to the following guidelines:

  • Syntax that resembles as closely as possible definitions and pseudo code mentioned in Noise Specs.
  • As minimal python "magic" as possible (explicit is better than implicit).
  • Code that is simple, easy to read, follow and understand.
  • Flexibility to easily adopt future changes to Noise specifications.
  • Deviations from Noise Specs (additions, opinionated specs and API changes..etc) are isolated from original implementation/API and are optional to use.
  • Deviations from Noise Specs do not influence adjustments to original implementation/API that conflict with Noise Specs.

META-INF

dissononce version: 0.34.3
noise revision: 34
released: 2019-04-24
requires:
- python>=2.5,<=3.7
- cryptography>=2.5
uses:
- transitions==0.6.9

Contents

Installation

From source:

python setup.py install

Using Pip:

pip install dissononce

Usage

Crypto Functions

Each set of Crypto functions (DH, Cipher, Hash) is enclosed inside an own base class, where an implementation subclasses that base class to implement the methods.

  • DH-functions base class: dissononce.dh.dh.DH
  • Cipher-functions base class: dissononce.cipher.cipher.Cipher
  • Hash-functions base class: dissononce.hash.hash.Hash

Example instantiating objects for X25519 DH, AESGCM Cipher and SHA256 Hash:

from dissononce.cipher.aesgcm import AESGCMCipher
from dissononce.dh.x25519.x25519 import X25519DH
from dissononce.hash.sha256 import SHA256Hash

cipher = AESGCMCipher()
dh = X25519DH()
hash = SHA256Hash()

Implementations for each set of crypto functions are organized according to their support level:

See Appendices for available Crypto functions.

Processing

HandshakeState, SymmetricState and CipherState should ideally be constructed in a composition-manner, where Crypto-functions dependencies are also to be instantiated before passing them to their dependants.

  • A CipherState requires a Cipher object
  • A SymmetricState requires a CipherState and a Hash object.
  • A HandshakeState requires a SymmetricState and a DH object.
from dissononce.processing.impl.handshakestate import HandshakeState
from dissononce.processing.impl.symmetricstate import SymmetricState
from dissononce.processing.impl.cipherstate import CipherState
from dissononce.cipher.chachapoly import ChaChaPolyCipher
from dissononce.dh.x448.x448 import X448DH
from dissononce.hash.sha512 import SHA512Hash


handshakestate = HandshakeState(
    SymmetricState(
        CipherState(
            ChaChaPolyCipher()
        ),
        SHA512Hash()
    ),
    X448DH()
)

See Extras for alternative methods of construction.

Handshake Patterns

The HandshakePattern class allows authoring of patterns using a simple syntax, similar to how patterns are described in Noise spec.

  • message_patterns is a tuple/list of tuples of token(s).
  • initiator_pre_messages is a tuple of tokens
  • responder_pre_message_pattern is a tuple of tokens
from dissononce.processing.handshakepatterns.handshakepattern import HandshakePattern

k1k1 = HandshakePattern(
      name='K1K1',
      initiator_pre_messages=('s',),
      responder_pre_message_pattern=('s',),
      message_patterns=(
          ('e',),
          ('e', 'ee', 'es'),
          ('se',)
    )
)

print(k1k1)
K1K1:
  -> s
  <- s
  ...
  -> e
  <- e, ee, es
  -> se

See Appendices for already defined Handshake Patterns.

Modifiers

A Modifier accepts a HandshakePattern and creates a new one with a modified name, and a modified set of message and premessage patterns

Fallback

from dissononce.processing.modifiers.fallback import FallbackPatternModifier
from dissononce.processing.handshakepatterns.interactive.XX import XXHandshakePattern


xx = XXHandshakePattern()
xx_fallback = FallbackPatternModifier().modify(xx)
print(xx_fallback)
XXfallback:
  -> e
  ...
  <- e, ee, s, es
  -> s, se

PSK

from dissononce.processing.modifiers.psk import PSKPatternModifier
from dissononce.processing.handshakepatterns.interactive.NN import NNHandshakePattern


nn = NNHandshakePattern()
nn_psk0 = PSKPatternModifier(0).modify(nn)
nn_psk02 = PSKPatternModifier(2).modify(nn_psk0)
print(nn_psk02)
NNpsk0+psk2:
  -> psk, e
  <- e, ee, psk

As usual, the modified HandshakePattern is used to (re)initialize a HandshakeState:

handshakestate.initialize(
    handshake_pattern=nn_psk02,
    initiator=True,
    prologue=b'',
    psks=(psk0, psk2)
)

Extras

Classes and functions that are not part of Noise Protocol specification but are part of this implementation are referred to as "Extras" or "Deviations". Examples for Extras are helpers, classes that simplify usage of the library, wrappers that enforce some rules or design patterns, or crypto functions that are not part of Noise Spec. Extras should be decoupled as much as possible from the base spec implementation and never referenced from there.

meta: Crypto-functions by name:

As an alternative to directly instantiating the Crypto-functions objects, they could also be created by name using a factory designated to each type of Crypto-functions:

from dissononce.extras.meta.hash.factory import HashFactory
from dissononce.extras.meta.dh.factory import DHFactory
from dissononce.extras.meta.cipher.factory import CipherFactory


cipher = CipherFactory().get_cipher('AESGCM')
hash = HashFactory().get_hash('SHA256')
dh = DHFactory().get_dh('25519')

Note that creating by name supports stable/official algorithms only at the moment.

meta: Protocol by name:

A Noise Protocol, that is:

  • DH, Cipher, Hash instance
  • CipherState instance
  • SymmetricState instance
  • HandshakeState instance
  • HandshakePattern

can be created by name. Use NoiseProtocolFactory to get a a NoiseProtocol instance which encloses instances of DH, Cipher, Hash, HandshakePattern, and exposes methods for creating CipherState, SymmetricState, and HandshakeState.

from dissononce.extras.meta.protocol.factory import NoiseProtocolFactory

protocol = NoiseProtocolFactory().get_noise_protocol('Noise_XX_25519_AESGCM_SHA256')
handshakestate = protocol.create_handshakestate()

Note that creating by name supports stable/official algorithms only at the moment.

processing: GuardedHandshakeState

from dissononce.extras.processing.handshakestate_guarded import GuardedHandshakeState

guarded = GuardedHandshakeState(handshakestate)
guarded.read_message(b'', bytearray())
> AssertionError: Cannot read_message while in initialize phase.

GuardedHandshakeState wraps an existing HandshakeState to enforce a correct flow of the handshake process. This includes making sure the HandshakeState is initialized before usage, and that the flow order of write_message and read_message invocations match the HandshakePattern being used. A violation will result in an AssertionError getting raised.

processing: SwitchableHandshakeState

from dissononce.extras.processing.handshakestate_switchable import SwitchableHandshakeState
from dissononce.processing.handshakepatterns.interactive.XX import XXHandshakePattern
from dissononce.processing.modifiers.fallback import FallbackPatternModifier
from dissononce.extras.meta.protocol.factory import NoiseProtocolFactory

protocol = NoiseProtocolFactory().get_noise_protocol('Noise_IK_25519_AESGCM_SHA256')
switchable = SwitchableHandshakeState(protocol.create_handshakestate())

## Begin IK, then fallback to XX if necessary using:

switchable.switch(
    handshake_pattern=FallbackPatternModifier().modify(XXHandshakePattern()),
    initiator=True,
    prologue=b''
)

SwitchableHandshakeState facilitates transforming an ongoing Handshake into using a different pattern. Given the newHandshakePattern, it analyses the required initiator and responder pre-messages, and maintains them across the transformation for use in the new Handshake. This is typically used for example when doing a IK handshake then switching to XXfallback where re is to be used as a initiator pre-message.

Examples

Inside examples directory there are examples for some Noise protocols carrying out a handshake and transporting some messages for demonstration.

Testing

Test Vectors

Vectors used for testing are found under test/vectors. The data is of JSON type, and is formatted according to Noise Test Vectors Specification. At the moment there are 2 Test Vectors files:

Logging

Enable debug-level logging for a detailed insight of a handshake process. The debug output syntax and formatting is intended to be as close as possible to the language used in Noise specs. This might be useful for when using dissononce as a reference implementation where one wants to understand what's going on internally and to easily relate to Noise specs.

>>> import dissononce, logging
>>> dissononce.logger.setLevel(logging.DEBUG)
>>> handshakestate.initialize(XXHandshakePattern(), True, b'', X448DH().generate_keypair())

I dissononce.processing.impl.handshakestate - Derived Noise Protocol name Noise_XX_448_ChaChaPoly_SHA512
XX:
  -> e
  <- e, ee, s, es
  -> s, se

>>> handshakestate.write_message(b'',bytearray())

I dissononce.processing.impl.handshakestate - WriteMessage(payload, message_buffer)
D dissononce.processing.impl.handshakestate -     Processing token 'e'
D dissononce.processing.impl.handshakestate -         e=GENERATE_KEYPAIR()
D dissononce.processing.impl.handshakestate -         message_buffer.append(e.public_key)
D dissononce.processing.impl.handshakestate -         MixHash(e.public_key)
D dissononce.processing.impl.handshakestate -     buffer.append(EncryptAndHash(payload))

Appendices

Cipher functions

Stable:

Hash functions

Stable:

DH functions

Stable:

Handshake Patterns

Interactive:

Oneway:

Deferred:

Modifiers

References

dissononce's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

dissononce's Issues

GuardedhandshakeState might throw an error on py2 if future is installed

On python2 if 'future' was globally installed or accessible by dissononce, transitions lib will successfully do a from builtins import object eventhough it seems intended for py3 only. This imported object in py2 already has a next() method, causing a conflict with 'next' that is defined as a state action/transition and raises a TypeError: newobject is not an iterator

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.