Module documentation for 0.6.0
This library implements the Noise protocol.
Import the modules for the kind of handshake you’d like to use.
For example, if you want to use
Noise_IK_25519_AESGCM_SHA256, your imports would be:
import Crypto.Noise.Cipher.AESGCM import Crypto.Noise.Curve.Curve25519 import Crypto.Noise.Hash.SHA256 import Crypto.Noise.Handshake import Crypto.Noise.HandshakePatterns (noiseIK)
Define the functions that will be called during various stages of the handshake.
writeMsg :: ByteString -> IO () readMsg :: IO ByteString payloadIn :: Plaintext -> IO () payloadOut :: IO Plaintext staticIn :: PublicKey d -> IO Bool
readMsgwill typically be functions that write to and read from a socket.
payloadOutfunctions are called when payloads are received and needed.
staticInfunction is called when a static key is received from the remote peer. If this function returns
False, the handshake is immediately aborted. Otherwise, it continues normally. See the documentation of
If you don’t need to use payloads and want to accept all remote static keys, do the following:
let hc = HandshakeCallbacks (writeMsg socket) (readMsg socket) (\_ -> return ()) (return "") (\_ -> return True)
Create the handshake state.
Select a handshake pattern to use. Patterns are defined in the
Crypto.Noise.HandshakePatternsmodule. Ensure that you provide the keys which are required by the handshake pattern you choose. For example, the
Noise_IKpattern requires that the initiator provides a local static key and a remote static key. Remote keys are communicated out-of-band.
let initiatorState = handshakeState $ HandshakeOpts noiseIK "prologue" (Just "pre-shared-key") (Just local_static_key) Nothing -- local ephemeral key (Just remote_static_key) -- communicated out-of-band Nothing -- remote ephemeral key True -- we are the initiator
let responderState = handshakeState $ HandshakeOpts noiseIK "prologue" (Just "pre-shared-key") (Just local_static_key) Nothing -- local ephemeral key Nothing -- we don't know their static key yet Nothing -- remote ephemeral key False -- we are the responder
Run the handshake:
(encryptionCipherState, decryptionCipherState) <- runHandshake initiatorState hc
(encryptionCipherState, decryptionCipherState) <- runHandshake responderState hc
Send and receive transport messages:
let (cipherText, encryptionCipherState') = encryptPayload "hello world" encryptionCipherState
let (Plaintext pt, decryptionCipherState') = decryptPayload msg decryptionCipherState
Ensure that you never re-use a cipher state.
An echo-server and echo-client are located within the
examples/ directory. The binary protocol is as follows:
C -> S: [pattern byte] [cipher byte] [curve byte] [hash byte] C -> S: [num bytes (uint16 big endian)] [message] S -> C: [num bytes (uint16 big endian)] [message] ...
message is any raw Noise handshake or message data.
Added ability to abort handshakes based on the remote party’s public key
Factored out ScrubbedBytes utilities to separate module
Added echo-server and echo-client example
Renamed HandshakeStateParams to HandshakeOpts
Added Curve448 support
Major refactoring and API changes A DSL was created to represent handshake patterns.
Added GHC 7.10.3 to unit tests
Added basic benchmarks
Added better exception handling
Improved handshakeState API
Added psk2 functionality
Unit test cleanup
Renamed symmetricHandshake to symmetricState
Added BLAKE2, SHA512, AESGCM support
- Brought API up to date with current version of spec (17)
Added support for one-way handshakes
Added helper functions for ScrubbedBytes / ByteString conversion
- First version.