{"id":16856685,"url":"https://github.com/lvh/caesium","last_synced_at":"2025-04-04T08:09:09.625Z","repository":{"id":19370173,"uuid":"22610392","full_name":"lvh/caesium","owner":"lvh","description":"Modern cryptography (libsodium/NaCl) for Clojure","archived":false,"fork":false,"pushed_at":"2023-09-15T19:14:04.000Z","size":496,"stargazers_count":180,"open_issues_count":13,"forks_count":28,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-10-14T14:11:43.116Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lvh.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":"AUTHORS"}},"created_at":"2014-08-04T15:58:56.000Z","updated_at":"2024-08-14T04:19:17.000Z","dependencies_parsed_at":"2024-01-08T18:03:37.352Z","dependency_job_id":"a0d241b4-a462-4d79-9de1-45dc83c0a9cd","html_url":"https://github.com/lvh/caesium","commit_stats":{"total_commits":648,"total_committers":22,"mean_commits":"29.454545454545453","dds":"0.13271604938271608","last_synced_commit":"273ccee8173b7844349824eac279342edbeac48e"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lvh%2Fcaesium","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lvh%2Fcaesium/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lvh%2Fcaesium/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lvh%2Fcaesium/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lvh","download_url":"https://codeload.github.com/lvh/caesium/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247142074,"owners_count":20890653,"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":[],"created_at":"2024-10-13T14:05:05.747Z","updated_at":"2025-04-04T08:09:09.604Z","avatar_url":"https://github.com/lvh.png","language":"Clojure","funding_links":[],"categories":["Security"],"sub_categories":[],"readme":"# caesium\n\n![caesium spectral lines](https://raw.githubusercontent.com/lvh/caesium/master/caesium.png)\n\n[![Clojars Project](http://clojars.org/caesium/latest-version.svg)](http://clojars.org/caesium)\n\n[![Build Status](https://github.com/lvh/caesium/workflows/build/badge.svg?branch=master)](https://github.com/lvh/caesium/actions?query=workflow%3Abuild)\n[![codecov](https://codecov.io/gh/lvh/caesium/branch/master/graph/badge.svg)](https://codecov.io/gh/lvh/caesium)\n[![Dependencies Status](https://versions.deps.co/lvh/caesium/status.svg)](https://versions.deps.co/lvh/caesium)\n\ncaesium is a modern cryptography library for Clojure. It is a direct\n[jnr-ffi][jnr-ffi] binding to [libsodium][libsodium], which in turn is\na more convenient fork of the original [NaCl][nacl] library by\n[djb][djb].\n\n[jnr-ffi]: https://github.com/jnr/jnr-ffi\n[nacl]: http://nacl.cr.yp.to/.\n[djb]: http://cr.yp.to/djb.html\n[libsodium]: https://github.com/jedisct1/libsodium\n\n***NOTE:*** Install [libsodium 1.0.18+](https://libsodium.gitbook.io/doc/installation) before trying to use caesium.\n\n## Minimum viable snippet\n\nHere's a sample of how you can use secretbox:\n\n``` clojure\n(ns minimum-viable-secretbox\n  (:require [caesium.crypto.secretbox :as sb]))\n\n(def key (sb/new-key!))\n(def plaintext \"Hello caesium!\")\n(def nonce (sb/int-\u003enonce 0))\n(def ciphertext (sb/encrypt key nonce (.getBytes plaintext)))\n(def roundtrip (String. (sb/decrypt key nonce ciphertext)))\n(assert (= plaintext roundtrip))\n```\n\n## Documentation\n\nThe most important documentation for caesium is actually the\n[documentation for libsodium][libsodiumdocs]. Since it's all just relatively\nsmall wrappers around that, everything in it applies.\n\n[libsodiumdocs]: http://doc.libsodium.org\n\n### Password hashing\n\nHere's an example of how you can use pwhash:\n\n``` clojure\n(ns pwhash-usage\n  (:require [caesium.crypto.pwhash :as pwhash]\n            [caesium.randombytes :as rb]\n            [caesium.byte-bufs :as bb]\n            [caesium.util :as u]\n            [caesium.crypto.secretbox :as sb]))\n\n;; helper function for creating salts from integers. may be useful for deterministic\n;; key derivation, incrementing subkeys from 0.\n(def int-\u003esalt (partial u/n-\u003ebytes pwhash/saltbytes))\n\n;; hashing passwords\n(def password \"example\")\n(def hashed-password (pwhash/pwhash-str password \n                                        pwhash/opslimit-sensitive\n                                        pwhash/memlimit-sensitive))\n(assert (= 0 (pwhash/pwhash-str-verify hashed-password password)))\n\n;; key derivation\n(def salt (rb/randombytes pwhash/saltbytes)) ; changing salt means changed derived key\n(def derived-key (pwhash/pwhash sb/keybytes\n                                password\n                                salt\n                                pwhash/opslimit-sensitive\n                                pwhash/memlimit-sensitive\n                                pwhash/alg-default))\n(def message (.getBytes \"hello, world!\"))\n(def encrypted-message (sb/encrypt derived-key (sb/int-\u003enonce 0) message))\n(def decrypted-message (sb/decrypt derived-key (sb/int-\u003enonce 0) encrypted-message))\n(assert (bb/bytes= message decrypted-message))\n```\n\n### Usage with Github Actions secrets\n\nHere is how you can create or update a repository secret for GitHub actions:\n\n``` clojure\n(require '[caesium.crypto.box])\n(require '[clj-http.client :as http])\n(require '[jsonista.core :as json])\n(import '(java.util Base64))\n\n(def public-key\n  \"The public key of the repository of which you want to create or update a secret\"\n  (let [payload (-\u003e {:request-method :get\n                     :url \"https://api.github.com/repos/{owner}/{repo}/actions/secrets/public-key\"\n                     :basic-auth [\"{user}\" \"{GITHUB_TOKEN}\"]\n                     :headers {\"Content-Type\" \"application/json\"\n                               \"Accept\" \"application/vnd.github.v3+json\"}}\n                    http/request\n                    :body\n                    json/read-value)\n        ^String encoded-key (get payload \"key\")]\n    {:decoded-key (.decode (Base64/getDecoder) (.getBytes encoded-key))\n     :key-id (get payload \"key_id\")}))\n\n(let [{:keys [^String decoded-key ^String key-id]} public-key\n      plaintext \"MY_SECRET_VALUE\"\n      cyphertext (caesium.crypto.box/box-seal\n                   (byte-streams/to-byte-array plaintext)\n                   decoded-key)]\n  (http/request\n    {:request-method :put\n     :url \"https://api.github.com/repos/{owner}/{repo}/actions/secrets/{MY_SECRET}\"\n     :body (json/write-value-as-string\n             {:encrypted_value (.encodeToString (Base64/getEncoder) cyphertext)\n              :key_id key-id})\n     :basic-auth [\"{user}\" \"{GITHUB_TOKEN}\"]\n     :headers {\"Content-Type\" \"application/json\"\n               \"Accept\" \"application/vnd.github.v3+json\"}}))\n```\n\n## Differences with other bindings\n\nInstead of making specific claims about specific libraries which may become\noutdated, here are a few properties you may care about:\n\n* caesium is written by a cryptographer who has experience binding\n  cryptographic libraries.\n* caesium has continuous integration and a fairly extensive test suite with\n  very high form/line coverage.\n* caesium does not provide magic layers on top of libsodium that prevent you\n  from writing secure software because of JVM memory semantics, while not\n  getting in your way if you want the default good-enough behavior.\n* caesium uses jnr-ffi pinning correctly; resulting in zero-copy behavior\n  between JVM and C land at the call site.\n* All APIs take `byte[]` and in some cases `ByteBuffer`, never `String`. This\n  gives you the option of zeroing byte arrays out once you're done. `caesium`\n  doesn't hide the no-magic C APIs from you; but you have to understand\n  libsodium to use them. The upside of that is that this library provides the\n  APIs necessary to use `libsodium` safely; e.g. with locked buffers with\n  canaries, secure memset, et cetera.\n* caesium's APIs match libsodium's behavior. If libsodium hashes a seed to\n  produce a keypair, caesium will hash a seed to produce a keypair. If\n  libsodium uses the default output size of a particular hash function,\n  caesium will use the default output size of that hash function. (These were\n  at time of writing not true for at least 1 other library).\n\ncaesium tries to just give you the libsodium experience from Clojure. C\npseudo-namespaces are mapped to real Clojure namespaces. It usually maps fns to\npredictable names; `sodium_crypto_secretbox_open_easy` will be called\n`caesium.crypto.secretbox/open-easy`. Formally: take the C pseudo-namespace,\nturn it into a real namespace, replace the leading `sodium` with caesium,\nreplace underscores with dashes. Exceptions where this doesn't work out:\n\n* sometimes, the last part of the C pseudo-namespace is repeated. This happens\n  for functions that have the same name as a C pseudo-namespace,\n  e.g. `crypto_generichash` (which is also the pseudo-namespace for\n  e.g. `crypto_generichash_init`). These would be available in the\n  `caesium.crypto.generichash` namespace, as `generichash` and `init`. This is\n  also repeated for some functions where there is a small suffix, e.g. the\n  function name for the \"easy secretbox opener\" is `secretbox-easy-open`, not\n  `easy-open`.\n* some functions map to the same underlying C functions, but have different\n  Java APIs. For example, one of them might cast to `ByteBuffer`, while others\n  assume byte arrays, while others rely on reflection to call the right\n  thing. Other pairs of functions might expect you to produce the output\n  buffer, or manage the output buffer for you. Since these are only JVM-level\n  differences, these often need different names at the JVM/Clojure\n  level. (This is always done as a fairly descriptive suffix.)\n* functions designed to make a `#define` constant available are accessible as\n  values, they don't need to be called. For example, you can access the\n  `crypto_generichash_KEYBYTES_MIN` constant via the `libsodium` `size_t\n  crypto_generichash_keybytes_min(void);` function, but in caesium, it's just\n  `caesium.crypto.generichash/keybytes-min` (not a function you have to call).\n* some families of functions in libsodium are a consequence of C not\n  supporting multi-arity functions; e.g. `scalarmult` in libsodium has two\n  functions: one with the fixed base point and one with an explicit base\n  point; caesium just has one function with two arities.\n* caesium sometimes takes a little artistic license with some of the exposed\n  names when that makes more sense than the original; generally fns will be\n  available under both the \"official\" name and an alias.\n\n## Compatibility\n\ncaesium uses [semver](http://semver.org/).\n\nSince this is a security-sensitive library, I will actively remove functions\nor APIs that have serious security problems, instead of simply documenting the\nproblem.\n\n## License\n\nCopyright © the caesium authors (see AUTHORS)\n\nDistributed under the Eclipse Public License either version 1.0 or (at\nyour option) any later version.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flvh%2Fcaesium","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flvh%2Fcaesium","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flvh%2Fcaesium/lists"}