Bronco provides authenticated and encrypted API tokens.
IETF XChaCha20-Poly1305 AEAD symmetric encryption is used to create the tokens. The encrypted token is base64-encoded, using the url-safe Base64 variant (without padding). Branca uses Base62 to ensure url safety, but since the url-safe variant of Base64 encoding is more common, we use that instead.
I provide absolutely no security guarantees whatsoever.
I am not a cryptographer. This is not an audited implementation. This does not follow the Branca specification 100%.
This a library I wrote to better understand AEAD primitives and authenticated/encrypted API tokens. I do use it in my own project, pasta6 knowing full well that I probably made some trivial mistakes.
sodiumoxide to your dependencies:
bronco = "0.1.1" sodiumoxide = "0.2.6"
use bronco::encode; use sodiumoxide::crypto::aead::xchacha20poly1305_ietf::gen_key; sodiumoxide::init(); let key = gen_key(); let message: &str = "hello, world!"; let token: String = encode(message, key.as_ref()).unwrap();
use bronco::decode; // let token: &str = ...; // let key: &[u8] = ...; let ttl: u32 = 60; // token is valid for 1 minute let message = decode(token, key, ttl).unwrap(); assert_eq!(message, "hello, world!");
Tokens have a header, ciphertext, and authentication tag. The header has a version, timestamp, and nonce. Overall the token structure is:
Version (1B) || Timestamp (4B) || Nonce (24B) || Ciphertext (*B) || Tag (16B)
The ciphertext can be arbitrarily long, and will be exactly the length of the plaintext message.
The string representation of the binary token uses Base64 (URL-safe variant) encoding, with the following character set:
More details can be found in the Branca specification.
Keys must be 32 bytes in length.
Any 32 byte slice can be used as a key, but it is highly recommended you use sodiumoxide's
sodiumoxide::crypto::aead::xchacha20poly1305_ietf::gen_key function to generate truly random keys.
This module has several significant changes from the Branca specification.
First, the binary token is encoded as a string using Base64 (URL-safe variant), not Base62.
Second, token payloads are assumed to be valid UTF-8. This module only allows encoding of valid UTF-8 strings, so this should never be a problem. A custom implementation could allow the encoding of arbitrary bytes into a token, so to handle non UTF-8 payloads we do a lossy UTF-8 conversion when parsing the payload. Invalid characters are replaced with the UTF-8 replacement character.
TTL is enforced for tokens, unless set to
0 at decoding time.
When a token's timestamp is more than
ttl seconds in the past,
it is treated as a decoding error. It is not possible to specify an infinite TTL, but
you can set arbitrarily large
NOTE: TTLs which result in an integer overflow when added to the UNIX epoch timestamp are treated as invalid.
Decodes a Bronco
Encodes an arbitrary