Liking cljdoc? Tell your friends :D

User Guide

Branca homepage describes Branca as follows:

Branca is a secure easy to use token format which makes it hard to shoot yourself in the foot. It uses IETF XChaCha20-Poly1305 AEAD symmetric encryption to create encrypted and tamperproof tokens. The encrypted token is base62 encoded which makes it URL safe. Payload itself is an arbitrary sequence of bytes.

clj-branca is a Clojure implementation of encoding and decoding Branca tokens. It is built on Lazysodium cryptography library.


Add clj-branca to your project’s dependencies:

{miikka/clj-branca {:mvn/version "0.1.0"}}
[miikka/clj-branca "0.1.0"]

Basic usage

The main namespace of clj-branca is clj-branca.core. It is recommended to be required with the alias branca.

(require '[clj-branca.core :as branca])

You can encode payload into a token with branca/encode. The payload can be a byte array, a string, or anything else that can be converted into a byte array by the byte-streams library. The tokens is returned as a string.

(def secret-key "supersecretkeyyoushouldnotcommit")
(def message "Hello, world!")

(branca/encode secret-key message)
;; "XZ69WpRTqZgEOqCJqaOK4iOKGLkg505VSASQ8MMGWs3mn1p6U81FvB5rSLpKlIjkZTUIBC6KiHIboz"

To decode the token, use branca/decode. It takes the token as a string and returns the payload as a byte array.

(String. (branca/decode secret-key "XZ69WpRTqZgEOqCJqaOK4iOKGLkg505VSASQ8MMGWs3mn1p6U81FvB5rSLpKlIjkZTUIBC6KiHIboz"))
;; "Hello, world!"

The encryption key used is 32 bytes. It can be a byte array or anything that can be converted into a byte array. You can generate a new key with clj-branca.crypto/generate-key.

(require '[clj-branca.crypto])
;; #object["[B" 0x7e00ed0f "[B@7e00ed0f"]

Token timestamp and time to live

Branca tokens contain a timestamp that indicates when the token was issued. To limit token lifetime, you can give :ttl in seconds in the options map when calling branca/decode. For example, to limit token lifetime to an hour:

(branca/decode secret-key token {:ttl 3600})

If the token is expired, branca/decode throws an exception. If you need to implement more complex TTL logic, you can get the token timestamp along the payload by calling branca/decode*.

(branca/decode* secret-key "XZ69WpRTqZgEOqCJqaOK4iOKGLkg505VSASQ8MMGWs3mn1p6U81FvB5rSLpKlIjkZTUIBC6KiHIboz")
;; {:version -70,
;;  :timestamp 1602348074,
;;  :nonce #object["[B" 0x37d81587 "[B@37d81587"],
;;  :payload #object["[B" 0x7f3e9acc "[B@7f3e9acc"]}

The return value includes the token version and the nonce as well. You probably won’t need them for anything, but they’re included for the sake of completeness.

There is only one Branca version, 0xBA. This is represented as a single-byte value. Because JVM bytes are signed, the value is printed as -70 and not as 186 as you might expect.

Error handling

Whenever clj-branca encouters an error, such as a malformed or a tampered token, it throws a clojure.lang.ExceptionInfo exception. The exception data contains the key :type to indicate that the exception was thrown by clj-branca.

:type explanation


The key must be a 32-byte byte array.


Encryption failed.


Decoding token failed.

Can you improve this documentation?Edit on sourcehut

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close