{"id":20904848,"url":"https://github.com/haskell-cryptography/cacophony","last_synced_at":"2025-12-11T23:15:49.094Z","repository":{"id":39645354,"uuid":"43552493","full_name":"haskell-cryptography/cacophony","owner":"haskell-cryptography","description":"A Haskell library implementing the Noise protocol.","archived":false,"fork":false,"pushed_at":"2021-03-20T00:39:15.000Z","size":6816,"stargazers_count":94,"open_issues_count":7,"forks_count":16,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-04-26T19:02:42.435Z","etag":null,"topics":["cryptography","haskell"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/haskell-cryptography.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-10-02T12:49:41.000Z","updated_at":"2024-03-07T14:30:13.000Z","dependencies_parsed_at":"2022-09-17T08:51:06.789Z","dependency_job_id":null,"html_url":"https://github.com/haskell-cryptography/cacophony","commit_stats":null,"previous_names":["centromere/cacophony"],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haskell-cryptography%2Fcacophony","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haskell-cryptography%2Fcacophony/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haskell-cryptography%2Fcacophony/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haskell-cryptography%2Fcacophony/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/haskell-cryptography","download_url":"https://codeload.github.com/haskell-cryptography/cacophony/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253882795,"owners_count":21978548,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography","haskell"],"created_at":"2024-11-18T13:19:20.794Z","updated_at":"2025-12-11T23:15:49.042Z","avatar_url":"https://github.com/haskell-cryptography.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cacophony\n\n[![Build Status](https://travis-ci.org/centromere/cacophony.svg?branch=master)](https://travis-ci.org/centromere/cacophony)\n[![Haskell](http://b.repl.ca/v1/language-haskell-blue.png)](http://www.haskell.org)\n\nThis library implements the [Noise](https://noiseprotocol.org) protocol.\n\n## Basic Usage\n\n1. Import the modules for the kind of handshake you'd like to use.\n\n   For example, if you want to use `Noise_IK_25519_AESGCM_SHA256`, your imports would be:\n\n   ```haskell\n   import Crypto.Noise\n   import Crypto.Noise.Cipher.AESGCM\n   import Crypto.Noise.DH -- Used to generate and manipulate keys\n   import Crypto.Noise.DH.Curve25519\n   import Crypto.Noise.Hash.SHA256\n   import Crypto.Noise.HandshakePatterns (noiseIK)\n   ```\n\n2. Set the handshake parameters.\n\n   Ensure that you provide the keys which are required by the handshake pattern you choose. For example,\n   the `Noise_IK` pattern requires that the initiator provides a local static key and a remote static key,\n   while the responder is only responsible for a local static key. You can use `defaultHandshakeOpts` to\n   return a default set of options in which all keys are set to `Nothing`. The initiator must set a\n   local ephemeral key for all handshake patterns. The responder must set a local ephemeral key for all\n   interactive (i.e. not one-way) patterns.\n\n   ```haskell\n   -- Initiator\n   localEphemeralKey \u003c- dhGenKey :: IO (KeyPair Curve25519)\n\n   let dho = defaultHandshakeOpts InitiatorRole \"prologue\" :: HandshakeOpts Curve25519\n       iho = setLocalStatic      (Just localStaticKey)\n             . setLocalEphemeral (Just localEphemeralKey)\n             . setRemoteStatic   (Just remoteStaticKey) -- communicated out-of-band\n             $ dho\n\n   -- Responder\n   localEphemeralKey \u003c- dhGenKey :: IO (KeyPair Curve25519)\n\n   let dho = defaultHandshakeOpts ResponderRole \"prologue\" :: HandshakeOpts Curve25519\n       rho = setLocalStatic      (Just localStaticKey)\n             . setLocalEphemeral (Just localEphemeralKey)\n             $ dho\n   ```\n\n3. Create the Noise state.\n\n   ```haskell\n   -- Initiator\n   let ins = noiseState iho noiseIK :: NoiseState AESGCM Curve25519 SHA256\n\n   -- Responder\n   let rns = noiseState rho noiseIK :: NoiseState AESGCM Curve25519 SHA256\n   ```\n\n4. Send and receive messages.\n\n   ```haskell\n   -- Initiator\n   let writeResult = writeMessage \"They must find it difficult -- those who have taken authority as the truth, rather than truth as the authority.\" ins\n   case writeResult of\n     NoiseResultMessage ciphertext ins' -\u003e ...\n     NoiseResultNeedPSK   _ -\u003e error \"something terrible happened\" -- will never happen in Noise_IK\n     NoiseResultException _ -\u003e error \"something terrible happened\"\n\n   -- Responder\n   let readResult = readMessage ciphertext rns\n   case readResult of\n     NoiseResultMessage plaintext rns' -\u003e ...\n     NoiseResultNeedPSK   _ -\u003e error \"something terrible happened\"\n     NoiseResultException _ -\u003e error \"something terrible happened\"\n   ```\n\n   **Ensure that you never re-use a NoiseState to send more than one message.**\n\n   Decrypted messages are stored internally as `ScrubbedBytes` and will be wiped from memory when they are\n   destroyed.\n\n### Helper Functions\n\nThe following functions are found in `Crypto.Noise.DH` and are used to manipulate keys:\n\n  * `dhGenKey` -- Generate a fresh (private, public) key pair\n  * `dhPubToBytes` -- Convert a public key to `ScrubbedBytes`\n  * `dhBytesToPub` -- Convert `ScrubbedBytes` to a public key\n  * `dhSecToBytes` -- Convert a private key to `ScrubbedBytes`\n  * `dhBytesToPair` -- Convert `ScrubbedBytes` to a (private, public) key pair\n\nThe following functions are found in `Crypto.Noise`:\n\n  * `remoteStaticKey` -- For handshake patterns where the remote party's static key is transmitted, this function\n    can be used to retrieve it. This allows for the creation of public key-based access-control lists.\n\n  * `handshakeComplete` -- Returns `True` if the handshake is complete.\n\n  * `processPSKs` -- This function repeatedly applies PSKs to a NoiseState until the list of PSKs becomes empty\n    or the handshake pattern stops asking for PSKs.\n\n  * `handshakeHash` -- Retrieves the `h` value associated with the conversation's SymmetricState. This value is\n    intended to be used for channel binding. For example, the initiator might cryptographically sign this value\n    as part of some higher-level authentication scheme. See section 11.2 of the protocol for details.\n\n  * `rekeySending` and `rekeyReceiving` -- Rekeys the given NoiseState according to section 11.3 of the protocol.\n\n## Supported Features\n\nAll combinations of the following handshake parameters are officially supported and covered by the unit tests:\n\n* Patterns\n  * NN\n  * KN\n  * NK\n  * KK\n  * NX\n  * KX\n  * XN\n  * IN\n  * XK\n  * IK\n  * XX\n  * IX\n  * N\n  * K\n  * X\n  * NNpsk0\n  * NNpsk2\n  * NKpsk0\n  * NKpsk2\n  * NXpsk2\n  * XNpsk3\n  * XKpsk3\n  * XXpsk3\n  * KNpsk0\n  * KNpsk2\n  * KKpsk0\n  * KKpsk2\n  * KXpsk2\n  * INpsk1\n  * INpsk2\n  * IKpsk1\n  * IKpsk2\n  * IXpsk2\n  * Npsk0\n  * Kpsk0\n  * Xpsk1\n  * NK1\n  * NX1\n  * X1N\n  * X1K\n  * XK1\n  * X1K1\n  * X1X\n  * XX1\n  * X1X1\n  * K1N\n  * K1K\n  * KK1\n  * K1K1\n  * K1X\n  * KX1\n  * K1X1\n  * I1N\n  * I1K\n  * IK1\n  * I1K1\n  * I1X\n  * IX1\n  * I1X1\n\n* Ciphers\n  * AESGCM\n  * ChaChaPoly1305\n\n* Curves\n  * Curve25519\n  * Curve448\n\n* Hashes\n  * BLAKE2b\n  * BLAKE2s\n  * SHA256\n  * SHA512\n\n## Vectors\n\nTest vectors can be generated and verified using the `vectors` program. It accepts no arguments. When run,\nit will check for the existence of `vectors/cacophony.txt` within the current working directory. If it is not\nfound, it is generated. If it is found, it is verified. All files within the `vectors/` directory (regardless\nof their name) are also verified. Note that this program can only generate and verify vectors whose handshake\npatterns are pre-defined in this library.\n\n## Custom Handshakes\n\nIf the built-in handshake patterns are insufficient for your application, you can define your own. Note that\nthis should be done with care.\n\nExample:\n\n```haskell\nnoiseFOOpsk0 :: HandshakePattern\nnoiseFOOpsk0 = handshakePattern \"FOOpsk0\" $\n  preInitiator s            *\u003e\n  preResponder s            *\u003e\n  initiator (psk *\u003e e *\u003e es *\u003e ss) *\u003e\n  responder (e *\u003e ee *\u003e se)\n```\n\n## Handshake Validation\n\n`HandshakePattern`s can be validated for compliance as described in sections 7.1 and 9.3 of the protocol:\n\n```\nλ\u003e let noiseBAD = handshakePattern \"BAD\" $ preResponder ss *\u003e initiator (e *\u003e se *\u003e e)\n[DHInPreMsg (0,0),InitMultipleETokens (1,2),InitSecretNotRandom (1,3)]\n\nλ\u003e validateHandshakePattern noiseKKpsk0\n[]\n```\n\nSee the `Crypto.Noise.Validation` module for details.\n\n## Tools\n\n### format-vectors.py\n\nVectors generated by the vector program are formatted as minified JSON. This python script takes the path\nto a vector file as an argument and reformats it so that it conforms to\n[the style](https://github.com/noiseprotocol/noise_wiki/wiki/Test-vectors) specified on the Noise Wiki.\n\n### noise-repl\n\nThis program acts as a kind of REPL for Noise messages. It supports sending and receiving messages via UDP\nor via a pipe to a shell command.\n\nAll messages transmitted via a pipe are expected to be prepended by a two byte big-endian length.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhaskell-cryptography%2Fcacophony","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhaskell-cryptography%2Fcacophony","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhaskell-cryptography%2Fcacophony/lists"}