1
0
Fork
You've already forked amora-rs
0
Amora is a secure token inspired by JWT and Branca, but enhanced a bit in some areas.
  • Rust 100%
Grzegorz Blach af0ff85241
All checks were successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
ci/woodpecker/push/woodpecker/3 Pipeline was successful
ci/woodpecker/tag/woodpecker/1 Pipeline was successful
ci/woodpecker/tag/woodpecker/2 Pipeline was successful
ci/woodpecker/tag/woodpecker/3 Pipeline was successful
Bump version to 0.2.2
2026年06月30日 02:05:18 +02:00
benches Refactor error handling to be compatible with std::error::Error 2025年12月25日 18:06:59 +01:00
src Switch to base64ct 2026年03月05日 21:54:19 +01:00
.editorconfig Initial import 2023年11月17日 15:49:13 +01:00
.gitignore Initial import 2023年11月17日 15:49:13 +01:00
.woodpecker.yml Switch 'environment' from list syntax to map syntax 2025年03月26日 23:42:21 +00:00
Cargo.toml Bump version to 0.2.2 2026年06月30日 02:05:18 +02:00
LICENSE Initial import 2023年11月17日 15:49:13 +01:00
README.md Add metadata fetching example to README.md 2024年03月08日 18:00:24 +01:00

Amora

Amora is a secure token inspired by JWT and Branca, but enhanced a bit in some areas.

Key features:

  • Can contain any type of payload: JSON, msgpack, cbor and so on...
  • Always encrypted and authenticated using XChaCha20-Poly1305 algorithm.
  • There are two versions of Amora:
    • Amora zero: encrypted with a 32-byte symmetric key.
    • Amora one: encrypted with a 32-byte asymmetric key.
  • Encoded using url-safe base64.
  • Always contain token generation time and TTL.

Amora structure

  • header (4 bytes for Amora zero; 36 bytes for Amora one):
    • version marker: 0xa0 or 0xa1 (1 byte)
    • TTL (3 bytes; little-endian)
    • randomly generated public key (32 bytes; Amora one only)
  • nonce (24 bytes)
    • token generation time (first 4 bytes; little-endian)
    • randomly generated 20 bytes
  • payload (any length)
  • message authentication code (4 bytes)

Token generation time (TGT) + TTL

TGT is an unsigned 32-bit int. It's a number of seconds starting from the Unix epoch on January 1, 1970 UTC. This means that Amora tokens will work correctly until the year 2106.

TTL is an unsigned 24-bits int. It means that each token can be valid for a maximum of 194 days.

Asymmetric encryption

The shared key is computed using the X25519 function. It requires two pairs of priv/pub keys. The first pair must be known. The second pair is randomly generated for each token.

Code examples

Symmetric key from bytes

letkey=[0x4f,0x99,0x70,0x66,0x2f,0xac,0xd3,0x7d,0xc3,0x6c,0x0f,0xd1,0xda,0xd0,0x7e,0xaa,0x04,0x7c,0x28,0x54,0x58,0x3c,0x92,0x0f,0x52,0x4b,0x2b,0x01,0xd8,0x40,0x83,0x1a,];letamora=Amora::amora_zero(&key);letpayload="sample_payload_just_for_testing";lettoken=amora.encode(&payload.as_bytes(),1);letdecoded=amora.decode(&token,true).unwrap_or("".into());letdecoded=std::str::from_utf8(&decoded).unwrap_or("");

Symmetric key from string

letkey="4f9970662facd37dc36c0fd1dad07eaa047c2854583c920f524b2b01d840831a";letamora=Amora::amora_zero_from_str(key).unwrap();letpayload="sample_payload_just_for_testing";lettoken=amora.encode(&payload.as_bytes(),1);letdecoded=amora.decode(&token,true).unwrap_or("".into());letdecoded=std::str::from_utf8(&decoded).unwrap_or("");

Asymmetric key from bytes

letsecret_key=StaticSecret::random();letpublic_key=PublicKey::from(&secret_key);letamora=Amora::amora_one(Some(secret_key),Some(public_key));letpayload="sample_payload_just_for_testing";lettoken=amora.encode(&payload.as_bytes(),1);letdecoded=amora.decode(&token,true).unwrap_or("".into());letdecoded=std::str::from_utf8(&decoded).unwrap_or("");

Asymmetric key from string

letsecret_key="778d0b92672b9a25ec4fbe65e3ad2212efa011e8f7035754c1342fe46191dbb3";letpublic_key="5cdd89c1bb6859c927c50b6976712f256cdbf14d7273f723dc121c191f9d6d6d";letamora=Amora::amora_one_from_str(Some(secret_key),Some(public_key)).unwrap();letpayload="sample_payload_just_for_testing";lettoken=amora.encode(&payload.as_bytes(),1);letdecoded=amora.decode(&token,true).unwrap_or("".into());letdecoded=std::str::from_utf8(&decoded).unwrap_or("");

Fetch metadata from the token

lettoken=concat!("oAEAAE_X6GVaC7xve5xaaAaLiW1YPqHX9I1BNGbKnC7A","rMke4GEU9MXCgU2U5jYAkJhDXQBqsO5tadCKyXZmI3mV-bpDFr1aQc1U");letmeta=Amora::meta(token).unwrap();println!("{:?}",meta);