# branca-erl

[![Build Status](](

An Erlang implementation of the [Branca specification] for authenticated and encrypted tokens.

These are symmetrically encrypted, tamper-proof strings of arbitrary contents that can be safely exposed.

## Installation

Add this to your `rebar.config` file to install the library through

{deps, [
    {branca_erl, "0.1.1"}

## Basic Usage

1> Secret = soda:rand(32). % the spec mandates that secret keys must be exactly 32 bytes long.

2> Message = erlang:term_to_binary({foo, bar, baz, [1,2,3]}).

3> Token = branca:encode(Message, Secret).

4> {ok, Message} = branca:decode(Token, Secret).

## API

### `branca:encode/2`

Uses `Secret` to turn `PlainText` into a Branca token using the current Unix time as the [timestamp]. Returns the token as an Erlang binary.

### `branca:encode/3`

Same as above, but using a custom timestamp. If used, it must be greater than 0 and less than 2^32 (4 bytes long).

### `branca:decode/2`

Uses `Secret` to turn a Branca token into the original `PlainText`. Returns a two-valued tuple for each possible outcome:

- `{ok, PlainText}` -> successful token decryption.
- `{error, bad_encoding}` -> `CipherText` contains at least one non-base62 character.
- `{error, invalid_token}` -> `CipherText` is base62, but it does not have the [layout] of a valid Branca token.
- `{error, invalid_sig}` -> the `Secret` used to decrypt the token is incorrect, or the token has been tampered.

### `branca:decode/3`

Same as above, but using a `TTL` to determine if the token has to be considered stale. Might return any of the above tuples, plus:

- `{expired, PlainText}` -> the token was successfully decrypted, but it expired (i.e. it was minted more than `TTL` seconds ago).

## Testing

The library includes EUnit and PropEr test suites.

These can be run with the usual rebar3 commands (`rebar3 eunit` and `rebar3 proper`).

## Caveats

- The base62 encoding and decoding is based on an O(n^2) algorithm involving arithmetic division and is _dog slow_.
  On my development laptop encoding 1KB of random data takes about 100ms, and 5KB jumps to 2.5s.
  Future releases might try to mitigate this problem by implementing `branca_transcoder` as a NIF, or replace
  the base62 algorithm altogether (though that would make the tokens incompatible with the Branca spec
  and the ones produced by other implementations).


- [X] Travis CI build
- [X] Timestamp expiration
- [ ] Spec annotations for Dialyzer
- [ ] Improve all modules documentation

[Branca specification]: