[][src]Crate branca

Branca - Authenticated and Encrypted API tokens using modern cryptography.

This crate is a Pure-Rust implementation of Branca which allows generating authenticated and encrypted tamper-proof tokens. The Branca specification is based on the Fernet specification and is also similar in its token format but it differs from the cipher that it uses for encryption and decryption and the encoding format of the token. Branca uses IETF XChaCha20-Poly1305 AEAD for encryption and decryption and uses Base62 instead of Base64 for encoding the tokens to be URL safe.

A Branca token is encrypted then encoded into Base62, and looks like this:

875GH233T7IYrxtgXxlQBYiFobZMQdHAT51vChKsAIYCFxZtL1evV54vYqLyZtQ0ekPHt8kJHQp0a

The internal format of a Branca token looks like this:

Version (1B) || Timestamp (4B) || Nonce (24B) || Ciphertext (*B) || Tag (16B)

The payload/ciphertext size can be of any arbitrary length, this means that contents of the payload can be anything from Text, JSON, MessagePacks, JWTs, URLs, etc. This allows a Branca Token to be a secure alternative to JWT, since it is authenticated and encrypted by default and supports only one cipher as the standard; unlike JWT.

This blog post explains in more detail on using Branca tokens as an alternative to JWTs.

Also see: branca-spec for more information about the token specification.

Examples

A straightforward example of generating these tokens using the Branca::new() builder:

extern crate branca;

use branca::Branca;

fn main() {
    let key = b"supersecretkeyyoushouldnotcommit".to_vec();
    let token = Branca::new(&key).unwrap();
    let ciphertext = token.encode("Hello World!").unwrap();

    let payload = token.decode(ciphertext.as_str(), 0).unwrap();
    println("{}", payload); // "Hello World!"
}

You can also decide to set the other fields in the token before encoding it if you want to since this is a builder method.

...
let ciphertext = token
                .set_timestamp(1234567890)
                .set_nonce(&nonce)
                .set_key(&key)
                .encode("Hello World!").unwrap();
...

It is also possible to directly encode and decode functions without using the builder function. In this example I'm using ring for random number generation. You can use alternative CSRNG crates such as the rand crate or sodiumoxide.

extern crate ring;

use branca::{encode, decode};
use ring::rand::SystemRandom;
...
let key = b"supersecretkeyyoushouldnotcommit".to_vec();
let mut nonce = vec![0; 24];
SystemRandom::new().fill(nonce.as_mut()).unwrap();

let token = encode("Hello World!", &keygen, &nonce, 123206400).unwrap(); 
// token = "875G...p0a"

let ttl = 3600; 
// The token will expire at timestamp + ttl
let payload = decode(token.as_str(), &keygen, 0).unwrap();

println!({}, payload);  
// payload = "Hello World!".
...

Modules

errors

Structs

Branca

The Branca defines the structure of a Branca token for encoding and decoding.

Functions

decode

Decodes a Branca token and returns the plaintext as a String.

encode

Encodes the message and returns a Branca Token as a String.