Liking cljdoc? Tell your friends :D

geheimnis

Clojars Project cljdoc badge

Portable cryptography for Clojure and ClojureScript (browser + Node) — one API, native on each platform.


⚠️ Security status — read this first

v1 (geheimnis.aes, geheimnis.rsa, geheimnis.md5) is deprecated and NOT safe for new use. It provides unauthenticated AES-CBC (no integrity — a tampered ciphertext is undetectable), textbook RSA (no padding — malleable, unsafe), and an empty MD5. Do not use these for anything security-sensitive.

v2 (org.replikativ.geheimnis.*) is a ground-up modern rewrite in progress — authenticated encryption (AES-256-GCM), Ed25519 signatures, X25519 key agreement, HMAC/HKDF, a CSPRNG-only randomness source, portable across JVM / browser / Node. Status below.


v2 status

The full v2 surface — synchronous foundation, AES-256-GCM (AEAD), Ed25519 signatures, and X25519 key agreement — is landed and verified on JVM and Node against NIST/RFC vectors and JVM↔Node interop KATs.

namespaceprovidessync?status
…geheimnis.corerandom-bytes (CSPRNG), ct-equal?sync
…geheimnis.codecbase64url / hex / utf8, byte-array utilssync
…geheimnis.hashhmac-sha256, hkdf; sha256/sha512 (via hasch)sync
…geheimnis.aeadAES-256-GCM authenticated encryptionasync
…geheimnis.signEd25519 sign / verifyasync
…geheimnis.dhX25519 key agreementasync

Design principle — sync where possible, async only where forced. Hashing, HMAC and HKDF are synchronous on both platforms (goog.crypt / java.security), so token verification (HS256) needs no async. Only AEAD and the elliptic curves use the async tier (Web Crypto on CLJS, java.security on the JVM), returning core.async channels.

Randomness is CSPRNG-onlySecureRandom on the JVM, crypto.getRandomValues in the browser/Node; it throws loudly rather than fall back to Math.random.

Raw SHA digests live in hasch (the content-hashing library) and are re-exported here — geheimnis owns the keyed / secret crypto, hasch owns unkeyed content hashing.

Usage

;; deps.edn
org.replikativ/geheimnis {:mvn/version "…"}
(require '[org.replikativ.geheimnis.core :as g]
         '[org.replikativ.geheimnis.hash :as h]
         '[org.replikativ.geheimnis.codec :as codec])

(g/random-bytes 32)                 ; 32 CSPRNG bytes
(h/hmac-sha256 key msg)             ; HMAC-SHA-256
(h/hkdf ikm salt info 32)           ; derive 32 bytes (RFC 5869)
(codec/bytes->b64url some-bytes)    ; unpadded base64url

A byte value is a JVM byte[] / CLJS Uint8Array; the codec helpers convert.

Development

# JVM
clj -M:test -e "(require 'org.replikativ.geheimnis.v2-hash-test) \
                (clojure.test/run-tests 'org.replikativ.geheimnis.v2-hash-test)"
# CLJS on Node
npx shadow-cljs compile node-test && node target/node-test.js
# format
clj -M:format   # check   ·   clj -M:ffix   # fix

License

Copyright © 2016-2026 Christian Weilbach, Konrad Kühne

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this software except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. See the LICENSE and NOTICE files for details.

Can you improve this documentation? These fine people already did:
Christian Weilbach & Konrad Kühne
Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close