Branca - A secure alternative token format to JWT

Branca is a secure alternative token format to JWT

Crate Documentation License CI

. This implementation is written in pure Rust and uses the XChaCha20-Poly1305 AEAD (Authenticated Encryption with Associated Data) stream cipher for generating authenticated and encrypted tamper-proof tokens. More information about the Branca token specification can be found here in branca-spec.

Security

NOTE: Branca uses orion for its cryptographic primitives and due to orion not receiving any formal security audit, the same security risks that orion has also applies to this Branca implementation if one uses it in production. For a better understanding about the security risks involved, see the orion wiki.

⚠️ Use at your own risk. ⚠️

Requirements

  • Rust 1.51
  • Cargo

Installation

Add this line into your Cargo.toml under the dependencies section:

[dependencies]
branca = "^0.10.0"
getrandom = "^0.2.3"

Then you can import the crate into your project with these lines:

extern crate getrandom;
extern crate branca;
use branca::{Branca, encode, decode};

Example Usage

The simplest way to use this crate is to use Branca::new() in this example below:

    let mut key = [0u8; 32];
    getrandom::getrandom(&mut key).unwrap();

    let mut token = Branca::new(&key).unwrap();
    let ciphertext = token.encode(b"Hello World!").unwrap();

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

See more examples of setting fields in the Branca struct and in the Documentation section.

Direct usage without Branca builder.

Encoding:

let mut key = [0u8; 32];
getrandom::getrandom(&mut key).unwrap();

let message = b"Hello world!";
let timestamp = 123206400;
let branca_token = encode(message, &key, timestamp).unwrap();

// branca_token = 875GH233T7.......

Decoding:

let ciphertext = branca_token.as_str();
let ttl = 0; // The ttl can be used to determine if the supplied token has expired or not.
let decoded = decode(ciphertext, &key, ttl);

if decoded.is_err() {
    // Error
} else {
    let msg = decoded.unwrap(); 
    // msg = "Hello world!"
}

Encode/Decode arbitrary data structures with Serde.

Since Branca is able to work with any format of data in the payload, it is possible for the payload to be anything from a JSON object, plaintext, raw bytes, protocol buffers or even a JWT.

Here is a example of using Branca to encode/decode a typical JSON object with serde_json.

Add the following into your Cargo.toml file:

[dependencies]
branca = "^0.10.0"
serde_json = "^1.0"
serde_derive = "1.0.97"

#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate branca;
extern crate getrandom;

use branca::{encode, decode};

#[derive(Serialize, Deserialize, Debug)]
struct User {
    user: String,
    scope: Vec<String>,
}

fn main(){

    let message = json!({
        "user" : "[email protected]",
        "scope":["read", "write", "delete"],
    }).to_string();

    let mut key = [0u8; 32];
    getrandom::getrandom(&mut key).unwrap();
    
    let mut token = Branca::new(&key).unwrap();
    
    // Encode Message
    let branca_token = token.encode(message.as_bytes()).unwrap();
    
    // Decode Message
    let payload = token.decode(branca_token.as_str(), 0).unwrap();

    let json: User = serde_json::from_str(payload.as_str()).unwrap();

    println!("{}", branca_token);
    println!("{}", payload);
    println!("{:?}", json);
}

Branca uses Orion to generate secure random nonces when using the encode() and builder methods. By default, Branca does not allow setting the nonce directly since that there is a risk that it can be reused by the user which is a foot-gun.

The nonce generated must be 24 bytes in length. Keys must be 32 bytes in length.

Building

cargo build

Testing

cargo test

Contributing

Contributions and patches are welcome! Fork this repository, add your changes and send a PR.

Before you send a PR, make sure you run cargo test first to check if your changes pass the tests.

If you would like to fix a bug or add a enhancement, please do so in the issues section and provide a short description about your changes.

License

MIT

Issues

Collection of the latest Issues

brycx

brycx

0

The ttl field of the Branca struct is never used. Instead, decode() takes a separate TTL. Maybe the ttl field should be removed?

brycx

brycx

0

key(), nonce(), ttl() and timestamp() all consume self. This means the builders instance needs to be cloned if a user wants to continue using it after calling any of the above getters. This seems unintentional. I suggest they all take &self instead of self.

Versions

Find the latest versions by id

v0.10.1 - Feb 01, 2022

  • Update Orion to 0.17 which includes Poly1305 implementation based on formally verified arithmetic from fiat-crypto (@brycx).
  • Test implementation with now standardized test vectors from the spec (@brycx).
  • Bump MSRV to 1.52 (@brycx).
  • Enable Dependabot to automatically check for updates for dependencies (@brycx).

v0.10.0 - Nov 29, 2020

v0.9.2 - Aug 31, 2020

v0.9.1 - May 10, 2020

  • Fix Invalid ExpiredToken error logic (#3)
  • Update orion to v0.15 (#4) (Now 0.15.1)
  • Change summary of TTL in documentation.
  • Update branca dependencies.
  • Migrate to GitHub Actions from Travis.

v0.9.0 - Jul 22, 2019

  • Replaced Ring and chacha20-poly1305 crates with Orion by @brycx (#1)
    • Brings Unofficial Windows / WSL Support. (A Windows CI will be added to support this.)
    • Secret key comparison runs in constant-time with manual PartialEq implementation.
    • Also removes the internal hChaCha20 implementation.
  • (Breaking Change) Removed set_nonce() API.
  • Examples and tests now integrated into library.
  • Various Documentation fixes (Rustdoc friendly).

v0.8.0 - Jan 11, 2019

  • Added Branca::new() interface to simplify generating Branca tokens.
  • Migrated Key and Nonce fields from Vec to &[u8] in exception to the Branca struct.
  • Self variable in Branca struct is now borrowed rather than owned.
  • hChaCha20 module is now a private module. (Only needed internally by the encode/decode) methods.
  • Branca now uses Ring for nonce generation
  • Added Documentation to all fields.

v0.5.0 - Dec 29, 2018

  • Implementation is now written in Pure Rust (Zero unsafe code or FFI usage)
    • Migrated to chacha-poly1305-aead crate with in-tree hchacha20 implementation by @tarcieri
  • Message data type changed from String --> &str.
  • Removed sodiumoxide.
  • Switched from chrono --> std::time for timestamps.
  • Added more tests and examples.
  • Typical bug fixes and bounds checks for the keys and nonces.

v0.2.0 - Dec 02, 2018

  • Now uses sodiumxide for XChaCha20-Poly1305 cryptography functions.
  • Switched Key type to using a Vec instead of a String.
  • Added Travis CI.

v0.1.1 - Nov 26, 2018

Initial release.

Information - Updated May 13, 2022

Stars: 50
Forks: 8
Issues: 4

Repositories & Extras

A (mostly) pure-Rust implementation of various common cryptographic algorithms

Rust-Crypto seeks to create practical, auditable, pure-Rust implementations of common cryptographic

A (mostly) pure-Rust implementation of various common cryptographic algorithms

Orion is a cryptography library written in pure Rust

It aims to provide easy and usable crypto while trying to minimize the use of unsafe code

Orion is a cryptography library written in pure Rust

Rustls is a modern TLS library written in Rust

ring for cryptography and rustls-pemfile crate

Rustls is a modern TLS library written in Rust

Mundane is a Rust cryptography library backed by BoringSSL that is difficult

to misuse, ergonomic, and performant (in that order)

Mundane is a Rust cryptography library backed by BoringSSL that is difficult

Rustls is a modern TLS library written in Rust

ring for cryptography and rustls-pemfile crate

Rustls is a modern TLS library written in Rust

A (mostly) pure-Rust implementation of various common cryptographic algorithms

Rust-Crypto seeks to create practical, auditable, pure-Rust implementations of common cryptographic

A (mostly) pure-Rust implementation of various common cryptographic algorithms

This repository holds a Rust port of Google's Tink cryptography library

This repository holds a Rust port of Google's RustCrypto crates – this repo focuses on making

This repository holds a Rust port of Google's Tink cryptography library

A cryptography library that is mainly implemented in Rust

I aim to implement bindings to other languages such as C/C++ and Python

A cryptography library that is mainly implemented in Rust

Libsm is an open source pure rust library of China Cryptographic Algorithm Standards

It is completed by a collaborative effort between the Cryptape Technology LLC

Libsm is an open source pure rust library of China Cryptographic Algorithm Standards

Cryptographic algorithms in pure Rust

The main interface to these crates is the RustCrypto traits

Cryptographic algorithms in pure Rust

A collection of cryptography functions written in Rust

rustup -- curl --proto '=https' --tlsv1

A collection of cryptography functions written in Rust
Facebook Instagram Twitter GitHub Dribbble
Privacy