packages feed

cacophony-0.7.0: README.md

# cacophony

[![Build Status](https://travis-ci.org/centromere/cacophony.svg?branch=master)](https://travis-ci.org/centromere/cacophony)
[![Haskell](http://b.repl.ca/v1/language-haskell-blue.png)](http://www.haskell.org)

This library implements the [Noise](https://github.com/noiseprotocol/noise_spec/blob/master/noise.md) protocol.

## Basic usage

1. 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:
   ```haskell
   import Control.Lens

   import Crypto.Noise
   import Crypto.Noise.Cipher.AESGCM
   import Crypto.Noise.DH
   import Crypto.Noise.DH.Curve25519
   import Crypto.Noise.Hash.SHA256
   import Crypto.Noise.HandshakePatterns (noiseIK)
   ```

2. Set the handshake parameters.

   Select a handshake pattern to use. Patterns are defined in the `Crypto.Noise.HandshakePatterns` module.
   Ensure that you provide the keys which are required by the handshake pattern you choose. For example,
   the `Noise_IK` pattern 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 `defaultHandshakeOpts` to
   return a default set of options in which the prologue is an empty string, PSKs are disabled, and all
   keys are set to `Nothing`. You must set the local ephemeral key for all handshake patterns, and it
   should never be reused.

   Functions for manipulating DH keys can be found in the `Crypto.Noise.DH` module.

   ```haskell
   -- Initiator
   local_ephemeral_key <- dhGenKey :: IO (KeyPair Curve25519)

   let dho = defaultHandshakeOpts noiseIK InitiatorRole :: HandshakeOpts Curve25519
        iho = dho & hoPrologue       .~ "prologue"
                  & hoPreSharedKey   .~ Just pre_shared_key
                  & hoLocalStatic    .~ Just local_static_key
                  & hoLocalEphemeral .~ Just local_ephemeral_key
                  & hoRemoteStatic   .~ Just remote_static_key -- communicated out-of-band

   -- Responder
   local_ephemeral_key <- dhGenKey :: IO (KeyPair Curve25519)

   let dho = defaultHandshakeOpts noiseIK ResponderRole :: HandshakeOpts Curve25519
        rho = dho & hoPrologue       .~ "prologue"
                  & hoPreSharedKey   .~ Just pre_shared_key
                  & hoLocalStatic    .~ Just local_static_key
                  & hoLocalEphemeral .~ Just local_ephemeral_key
   ```

3. Create the Noise state.
   ```haskell
   -- Initiator
   let ins = noiseState iho :: NoiseState AESGCM Curve25519 SHA256

   -- Responder
   let rns = noiseState rho :: NoiseState AESGCM Curve25519 SHA256
   ```

4. Send and receive messages.
   ```haskell
   -- Initiator
   let writeResult         = writeMessage ins "They must find it difficult -- those who have taken authority as the truth, rather than truth as the authority."
        (ciphertext, ins')  = either (error "something terrible happened") id writeResult

   -- Responder
   let readResult          = readMessage rns ciphertext
        (plaintext, rns')   = either (error "something terrible happened") id readResult
   ```

   **Ensure that you never re-use a noise state to send more than one message.**

   Decrypted messages are stored internally as `ScrubbedBytes` and will be wiped from memory when they are
   destroyed. Helper functions for dealing with `ScrubbedBytes` can be found in the `Data.ByteArray.Extend` module.

### Helper functions

The following functions are found in `Crypto.Noise` and can be helpful when designing an application which uses
Noise:

  * `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.

  * `handshakeComplete` -- Returns `True` if the handshake is complete.

  * `handshakeHash` -- Retrieves the `h` value 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 9.4 of the protocol for details.

  * `setSecondaryKey` -- Sets a secondary symmetric key as described in section 9.5 of the protocol.

## Vectors

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.

The generated vectors are minified JSON. There is a small python script within the `tools/` directory that
formats the JSON-blob in to something more readable.

## Example code

An echo-server and echo-client are located within the `examples/` directory. The binary protocol they use to
communicate is as follows:
```
C -> S: [psk byte] [pattern byte] [cipher byte] [dh byte] [hash byte]
C -> S: [num message bytes (uint16 big endian)] [message]
S -> C: [num message bytes (uint16 big endian)] [message]
...
```

where `message` is any raw Noise handshake or message data.

The prologue is set to the 5 header bytes to prevent a MITM attack.

For these example programs, the server chooses the value of the PSK, and the client chooses whether or not
to use a PSK-enabled handshake. Both the server and client expect the PSK file to be base64 encoded. One
way to generate the PSK file is as follows:
```
head -c 32 /dev/random | base64 > psk
```

To include these examples in your build, pass the `-fbuild-examples` flag to Cabal.

### Byte definitions

| byte | psk      | pattern | cipher     | dh    | hash    |
|------|----------|---------|------------|-------|---------|
| 0x00 | disabled | NN      | ChaChaPoly | 25519 | SHA256  |
| 0x01 | enabled  | KN      | AESGCM     | 448   | SHA512  |
| 0x02 |          | NK      |            |       | BLAKE2s |
| 0x03 |          | KK      |            |       | BLAKE2b |
| 0x04 |          | NX      |            |       |         |
| 0x05 |          | KX      |            |       |         |
| 0x06 |          | XN      |            |       |         |
| 0x07 |          | IN      |            |       |         |
| 0x08 |          | XK      |            |       |         |
| 0x09 |          | IK      |            |       |         |
| 0x0a |          | XX      |            |       |         |
| 0x0b |          | IX      |            |       |         |