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 import Crypto.Noise.Cipher.AESGCM import Crypto.Noise.DH -- Used to generate and manipulate keys import Crypto.Noise.DH.Curve25519 import Crypto.Noise.Hash.SHA256 import Crypto.Noise.HandshakePatterns (noiseIK)
Set the handshake parameters.
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, while the responder is only responsible for a local static key. You can use
defaultHandshakeOptsto return a default set of options in which all keys are set to
Nothing. The initiator must set a local ephemeral key for all handshake patterns. The responder must set a local ephemeral key for all interactive (i.e. not one-way) patterns.
-- Initiator localEphemeralKey <- dhGenKey :: IO (KeyPair Curve25519) let dho = defaultHandshakeOpts InitiatorRole "prologue" :: HandshakeOpts Curve25519 iho = setLocalStatic (Just localStaticKey) . setLocalEphemeral (Just localEphemeralKey) . setRemoteStatic (Just remoteStaticKey) -- communicated out-of-band $ dho -- Responder localEphemeralKey <- dhGenKey :: IO (KeyPair Curve25519) let dho = defaultHandshakeOpts ResponderRole "prologue" :: HandshakeOpts Curve25519 rho = setLocalStatic (Just localStaticKey) . setLocalEphemeral (Just localEphemeralKey) $ dho
Create the Noise state.
-- Initiator let ins = noiseState iho noiseIK :: NoiseState AESGCM Curve25519 SHA256 -- Responder let rns = noiseState rho noiseIK :: NoiseState AESGCM Curve25519 SHA256
Send and receive messages.
-- Initiator let writeResult = writeMessage "They must find it difficult -- those who have taken authority as the truth, rather than truth as the authority." ins case writeResult of NoiseResultMessage ciphertext ins' -> ... NoiseResultNeedPSK _ -> error "something terrible happened" -- will never happen in Noise_IK NoiseResultException _ -> error "something terrible happened" -- Responder let readResult = readMessage ciphertext rns case readResult of NoiseResultMessage plaintext rns' -> ... NoiseResultNeedPSK _ -> error "something terrible happened" NoiseResultException _ -> error "something terrible happened"
Ensure that you never re-use a NoiseState to send more than one message.
Decrypted messages are stored internally as
ScrubbedBytesand will be wiped from memory when they are destroyed.
The following functions are found in
Crypto.Noise.DH and are used to manipulate keys:
dhGenKey– Generate a fresh (private, public) key pair
dhPubToBytes– Convert a public key to
ScrubbedBytesto a public key
dhSecToBytes– Convert a private key to
ScrubbedBytesto a (private, public) key pair
The following functions are found in
remoteStaticKey– For handshake patterns where the remote party’s static key is transmitted, this function can be used to retrieve it. This allows for the creation of public key-based access-control lists.
Trueif the handshake is complete.
processPSKs– This function repeatedly applies PSKs to a NoiseState until the list of PSKs becomes empty or the handshake pattern stops asking for PSKs.
handshakeHash– Retrieves the
hvalue associated with the conversation’s SymmetricState. This value is intended to be used for channel binding. For example, the initiator might cryptographically sign this value as part of some higher-level authentication scheme. See section 11.2 of the protocol for details.
rekeyReceiving– Rekeys the given NoiseState according to section 11.3 of the protocol.
All combinations of the following handshake parameters are officially supported and covered by the unit tests:
Test vectors can be generated and verified using the
vectors program. It accepts no arguments. When run,
it will check for the existence of
vectors/cacophony.txt within the current working directory. If it is not
found, it is generated. If it is found, it is verified. All files within the
vectors/ directory (regardless
of their name) are also verified. Note that this program can only generate and verify vectors whose handshake
patterns are pre-defined in this library.
If the built-in handshake patterns are insufficient for your application, you can define your own. Note that this should be done with care.
noiseFOOpsk0 :: HandshakePattern noiseFOOpsk0 = handshakePattern "FOOpsk0" $ preInitiator s *> preResponder s *> initiator (psk *> e *> es *> ss) *> responder (e *> ee *> se)
HandshakePatterns can be validated for compliance as described in sections 7.1 and 9.3 of the protocol:
λ> let noiseBAD = handshakePattern "BAD" $ preResponder ss *> initiator (e *> se *> e) [DHInPreMsg (0,0),InitMultipleETokens (1,2),InitSecretNotRandom (1,3)] λ> validateHandshakePattern noiseKKpsk0 
Crypto.Noise.Validation module for details.
Vectors generated by the vector program are formatted as minified JSON. This python script takes the path to a vector file as an argument and reformats it so that it conforms to the style specified on the Noise Wiki.
This program acts as a kind of REPL for Noise messages. It supports sending and receiving messages via UDP or via a pipe to a shell command.
All messages transmitted via a pipe are expected to be prepended by a two byte big-endian length.
Set default GHC version to 8.4
Support GHC > 8.0.2
Parse pattern names more efficiently in unit tests
Use preferred Curve448 module from cryptonite
Add list of supported handshake parameters to README
Completely refactored API
Added rev32 support
Removed examples because they are difficult to maintain
Added noise-repl tool
- Added ability to export raw symmetric keys
Enabled llvm flag support on executables
Removed deepseq library dependency
Disallowed reserved nonce (2^64 - 1)
Fixed problem with CipherState count not incrementing
Removed secondary key support (rev 31)
Renamed dh tokens (rev 31)
Added Noise-C vectors
Regenerated test vectors
Now using IsString instance of ScrubbedBytes from memory package
Exceptions are now provided by the safe-exceptions package (breaking API change)
Added Noise_XXfallback pattern
Minor improvements to handshake pattern definition
Updated non-standard handshake patterns to conform with rev 30
Fixed bug which caused echo-server to read wrong public key
Major API overhaul and refactoring
Added test vector support
Added secondary symmetric key support
Added GHC 8.0.2 to unit tests
General code cleanup and other minor tweaks
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.