{"id":17965245,"url":"https://github.com/jlouis/enacl","last_synced_at":"2025-05-16T12:08:51.549Z","repository":{"id":23926830,"uuid":"27307575","full_name":"jlouis/enacl","owner":"jlouis","description":"Erlang bindings for NaCl / libsodium","archived":false,"fork":false,"pushed_at":"2024-07-29T21:00:50.000Z","size":497,"stargazers_count":196,"open_issues_count":17,"forks_count":63,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-04-02T05:52:40.403Z","etag":null,"topics":["cryptography","enryption","erlang","erlang-bindings","erlang-quickcheck","libsodium"],"latest_commit_sha":null,"homepage":null,"language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jlouis.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-11-29T16:20:05.000Z","updated_at":"2025-02-24T16:48:46.000Z","dependencies_parsed_at":"2024-06-18T18:34:37.735Z","dependency_job_id":"2facf7dd-e8dd-48c7-acab-e4508aefd692","html_url":"https://github.com/jlouis/enacl","commit_stats":{"total_commits":330,"total_committers":28,"mean_commits":"11.785714285714286","dds":"0.21212121212121215","last_synced_commit":"46e2754a50f4d9192ebf008bf80ea8242e7f7986"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jlouis%2Fenacl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jlouis%2Fenacl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jlouis%2Fenacl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jlouis%2Fenacl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jlouis","download_url":"https://codeload.github.com/jlouis/enacl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247994119,"owners_count":21030050,"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","enryption","erlang","erlang-bindings","erlang-quickcheck","libsodium"],"created_at":"2024-10-29T12:10:37.929Z","updated_at":"2025-04-09T07:04:43.969Z","avatar_url":"https://github.com/jlouis.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Erlang bindings for NaCl/libsodium\n\nThis library provides bindings for the libsodium cryptographic library\nfor Erlang. Originally called NaCl by Bernstein, Lange and Schwabe[0],\nFrank Denis took the source and made it far more portable in the\nlibsodium library. The enacl project is somewhat misnamed, as it uses\nlibsodium as the underlying driver.\n\n## INSTALL/Requirements\n\n* New-ish Erlang installation. Tested back to version 22.3, but version 21 *may*\n  work as well.\n* *Requires* the libsodium library, and has been tested with version\n  1.0.18. Lower versions might work, or they might fail to compile,\n  due to missing functionality. In particular, this means your libsodium installation\n  must be fairly recent as well.\n\n*Note:* If installing on systems which cuts packages into\nsubpackages, make sure you also get the \"-dev\" package containing\nthe header files necessary in order to compile software linking to\nlibsodium.\n\nTo build the software execute:\n\n  make\n\nor\n\n  rebar compile\n\nTo build and run licensed eqc test execute:\n\n  make eqc_run\n\nTo build and run eqc-mini version of test execute:\n\n  make eqc_mini_run\n\n## Features\n\n* Complete NaCl library, implementing all default functionality.\n* Implements a large set of additional functionality from libsodium.\n  Most notably access to a proper CSPRNG random source\n* Tests created by aggressive use of Erlang QuickCheck.\n* NaCl is a very fast cryptographic library. That is,\n  crypto-operations runs quickly on modern CPUs, with ample security\n  margins. This makes it highly useful on the server-side, where\n  simultaneous concurrent load on the system means encryption can have\n  a considerable overhead.\n* Is tested on Linux, FreeBSD and Illumos (Omnios)\n\nThis package draws heavy inspiration from \"erlang-nacl\" by Tony\nGarnock-Jones, and started its life with a gently nod in that\ndirection. However, it is a rewrite and it alters lots of code from\nTony's original work.\n\nIn addition, I would like to thank Steve Vinoski, Rickard Green, and\nSverker Eriksson for providing the Dirty Scheduler API in the first\nplace.\n\n## Usage\n\nIn general, consult the libsodium documentation at [Libsodium documentation](https://download.libsodium.org/doc/)\n\nThe original NaCl documentation is nowadays largely superceded by the\nlibsodium documentation, but it is still worth a visit [NaCl website](https://nacl.cr.yp.to)\n\nbut also note that our interface has full Edoc documentation,\ngenerated by executing\n\n  rebar3 doc\n\n## Hints\n\nIn general, the primitives provided by NaCl are intermediate-level\nprimitives. Rather than you having to select a cipher suite, it is\nselected for you, and primitives are provided at a higher level.\nHowever, their correct use is still needed in order to be secure:\n\n* Always make sure you obey the scheme of *nonce* values. If you ever\n  reuse a nonce, and an attacker figures this out, the system will\n  leak the XOR difference of messages sent with the same nonce. Given\n  enough guessing, this can in turn leak the encryption stream of bits\n  and every message hereafter, sent on the same keypair combination\n  and reusing that nonce, will be trivially breakable.\n* Use the beforenm/afternm primitives if using the `box` public-key\n  encryption scheme. Precomputing the Curve25519 operations yields\n  much faster operation in practice for a stream. Consult the `bench`\n  directory for benchmarks in order to see how much faster it is for\n  your system. The authors Core i7-4900MQ can process roughly 32\n  Kilobyte data on the stream in the time it takes to do the\n  Curve25519 computations. While NaCl is *fast*, this can make it even\n  faster in practice.\n* Encrypting very large blocks of data, several megabytes for\n  instance, is problematic for two reasons. First, while the library\n  attempts to avoid being a memory hog, you need at least a from-space\n  and a to-space for the data, meaning you need at least double the\n  memory for the operation. Furthermore, while such large blocks are\n  executed on the dirty schedulers, they will never yield the DS for\n  another piece of work. This means you end up blocking the dirty\n  schedulers in turn. It is often better to build a framing scheme and\n  encrypt data in smaller chunks, say 64 or 128 kilobytes at a time.\n  In any case, it is important to measure. Especially for latency.\n* The library should provide correct success type specifications. This\n  means you can use the dialyzer on your code and get hints for\n  incorrect usage of the library.\n* Note that every \"large\" input to the library accepts `iodata()`\n  rather than `binary()` data. The library itself will convert\n  `iodata()` to binaries internally, so you don't have to do it at\n  your end. It often yields simpler code since you can just build up\n  an iolist of your data and shove it to the library. Key material,\n  nonces and the like are generally *not* accepted as `iodata()`\n  however but requires you to input binary data. This is a deliberate\n  choice since most such material is not supposed to be broken up and\n  constructed ever (except perhaps for the Nonce construction).\n* The `enacl:randombytes/1` function provides portable access to the\n  CSPRNG of your kernel. It is an *excellent* source of CSPRNG random\n  data. If you need PRNG data with a seed for testing purposes, use\n  the `rand` module of Erlang. The other alternative is the `crypto`\n  module, which are bindings to OpenSSL with all its blessings and/or\n  curses.\n* Beware of timing attacks against your code! A typical area is string\n  comparison, where the comparator function exits early. In that case,\n  an attacker can time the response in order to guess at how many\n  bytes where matched. This in turn enables some attacks where you use\n  a foreign system as an oracle in order to learn the structure of a\n  string, breaking the cryptograhic system in the process.\n\n## Versions\n\nSee CHANGELOG.md\n\n## Overview\n\nThe NaCl cryptographic library provides a number of different\ncryptographic primitives. In the following, we split up the different\ngeneric primitives and explain them briefly.\n\n*A note on Nonces:* The crypto API makes use of \"cryptographic\nnonces\", that is arbitrary numbers which are used only once. For these\nprimitives to be secure it is important to consult the NaCl\ndocumentation on their choice. They are large values so generating\nthem randomly ensures security, provided the random number generator\nuses a sufficiently large period. If you end up using, say, the nonce\n`7` every time in communication while using the same keys, then the\nsecurity falls.\n\nThe reason you can pick the nonce values is because some uses are\nbetter off using a nonce-construction based on monotonically\nincreasing numbers, while other uses do not. The advantage of a\nsequence is that it can be used to reject older messages in the stream\nand protect against replay attacks. So the correct use is up to the\napplication in many cases.\n\n## Public Key cryptography\n\nThis implements standard Public/Secret key cryptography. The\nimplementation roughly consists of two major sections:\n\n* *Authenticated encryption:* provides a `box` primitive which\n  encrypts and then also authenticates a message. The reciever is only\n  able to open the sealed box if they posses the secret key and the\n  authentication from the sender is correct.\n* *Signatures:* allows one party to sign a message (not encrypting it)\n  so another party can verify the message has the right origin.\n\n## Secret key cryptography\n\nThis implements cryptography where there is a shared secret key between parties.\n\n* *Authenticated encryption:* provides a `secret box` primitive in\n  which we can encrypt a message with a shared key `k`. The box also\n  authenticates the message, so a message with an invalid key will be\n  rejected as well. This protects against the application obtaining\n  garbage data.\n* *Encryption:* provides streams of bytes based on a Key and a Nonce.\n  These streams can be used to `XOR` with a message to encrypt it. No\n  authentication is provided. The API allows for the system to `XOR`\n  the message for you while producing the stream.\n* *Authentication:* Provides an implementation of a Message\n  Authentication Code (MAC).\n* *One Time Authentication:* Authenticate a message, but do so\n  one-time. That is, a sender may *never* authenticate several\n  messages under the same key. Otherwise an attacker can forge\n  authenticators with enough time. The primitive is simpler and faster\n  than the MAC authenticator however, so it is useful in some\n  situations.\n\n## Low-level functions\n\n* *Hashing:* Cryptographically secure hashing\n* *String comparison:* Implements guaranteed constant-time string\n  comparisons to protect against timing attacks.\n\n## Rationale\n\nDoing crypto right in Erlang is not that easy. For one, the crypto\nsystem has to be rather fast, which rules out Erlang as the main\nvehicle. Second, cryptographic systems must be void of timing attacks.\nThis mandates we write the code in a language where we can avoid such\ntiming attacks, which leaves only C as a contender, more or less. The\nobvious way to handle this is by the use of NIF implementations, but\nmost C code will run to its conclusion once set off for processing.\nThis is a major problem for a system which needs to keep its latency\nin check. The solution taken by this library is to use the new Dirty\nScheduler API of Erlang in order to provide a safe way to handle the\nlong-running cryptographic processing. It keeps the cryptographic\nprimitives on the dirty schedulers and thus it avoids the major\nproblem.\n\nFocus has first and foremost been on the correct use of dirty\nschedulers, without any regard for speed. The plan is to extend the\nunderlying implementation, while keeping the API stable. We can\nprecompute keys for some operations for instance, which will yield a\nspeedup.\n\nAlso, while the standard `crypto` bindings in Erlang does a great job\nat providing cryptographic primitives, these are based on OpenSSL,\nwhich is known to be highly problematic in many ways. It is not as\neasy to use the OpenSSL library correctly as it is with these\nbindings. Rather than providing a low-level cipher suite, NaCl\nprovides intermediate level primitives constructed as to protect the\nuser against typical low-level cryptographic gotchas and problems.\n\n## Scheduler handling\n\nTo avoid long running NIFs, the library switches to the use of dirty\nschedulers for large encryption tasks. We investigated the Dirty\nScheduler switch overhead with DTrace on FreeBSD and found it to be\nroughly 5μs in typical cases. Thus, we target calls taking at least\n35μs is being easier to run directly on the dirty scheduler, as the\noverhead for switching is thus going to be less than 15%. This means\nvery small operations are run directly on the BEAM scheduler, but as\nsoon as the operation takes a little longer, the switch overhead is\nnot large enough to warrant the current schedulers involvement.\n\nIn turn, some operations are *always* run on the dirty scheduler\nbecause they take a long time in every case. This setup is far simpler\nfor most operations, unless the operation is performance sensitive and\nallows small messages.\n\nThe tests were conducted on a Core 2 Duo machine, with newer machines\nperhaps being able to switch faster. There are plans to rerun these\ntests on OSX and Illumos as well, in order to investigate the numbers\non more platforms.\n\n## Testing\n\nEvery primitive has been stress-tested through the use of Erlang\nQuickCheck with both *positive* and *negative* testing. This has been\nused to check against memory leaks as well as correct invocation.\nPlease report any error so we can extend the test cases to include a\nrandomized test which captures the problem so we generically catch\nevery problem in a given class of errors.\n\nPositive and negative testing refers to Type I and Type II errors in\nstatistical testing. This means false positives—given a *valid* input\nthe function rejects it; as well as false negatives—given an *invalid*\ninput the functions fails to reject that input.\n\nThe problem however, is that while we are testing the API level, we\ncan't really test the strength of the cryptographic primitives. We can\nverify their correctness by trying different standard correctness\ntests for the primitives, verifying that the output matches the\nexpected one given a specific input. But there is no way we can show\nthat the cryptographic primitive has the strength we want. Thus, we\nopted to mostly test the API and its invocation for stability.\n\nAlso, in addition to correctness, testing the system like this makes\nsure we have no memory leaks as they will show themselves under the\nextensive QuickCheck test cases we run. It has been verified there are\nno leaks in the code.\n\n## Notes\n\n[0] Other people have worked on bits and pieces of NaCl. These are\njust the 3 main authors. Please see the page [NaCl](http://nacl.cr.yp.to)\nfor the full list of authors.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjlouis%2Fenacl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjlouis%2Fenacl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjlouis%2Fenacl/lists"}