#token #jwt #authorization #branca

amora-rs

Amora是一个受JWT和Branca启发的安全令牌,但在某些方面有所增强。

3个不稳定版本

0.2.1 2024年3月8日
0.2.0 2024年3月8日
0.1.0 2024年1月7日

#170身份验证

Download history 11/week @ 2024-04-04 4/week @ 2024-04-11 2/week @ 2024-04-25 4/week @ 2024-05-16 4/week @ 2024-05-23 2/week @ 2024-05-30 11/week @ 2024-06-06 14/week @ 2024-06-13

每月106次下载

MPL-2.0 许可证

25KB
379

Amora

Amora是一个受JWTBranca启发的安全令牌,但在某些方面有所增强。

主要功能

  • 可以包含任何类型的有效负载:JSON、msgpack、cbor等等...
  • 始终使用XChaCha20-Poly1305算法加密和认证。
  • Amora有两个版本
    • Amora zero:使用32字节对称密钥加密。
    • Amora one:使用32字节非对称密钥加密。
  • 使用url-safe base64编码。
  • 始终包含令牌生成时间和TTL。

Amora结构

  • 头部(Amora zero为4字节;Amora one为36字节)
    • 版本标记:0xa0或0xa1(1字节)
    • TTL(3字节;小端格式)
    • 随机生成的公钥(32字节;仅Amora one)
  • nonce(24字节)
    • 令牌生成时间(前4字节;小端格式)
    • 随机生成的20字节
  • 有效负载(任何长度)
  • 消息认证码(4字节)

令牌生成时间(TGT)+ TTL

TGT是一个无符号32位整数。它是从1970年1月1日UTC的Unix纪元开始的秒数。这意味着Amora令牌将正确工作到2106年。

TTL是一个无符号24位整数。这意味着每个令牌的有效期最长为194天。

非对称加密

使用X25519函数计算共享密钥。它需要两对私钥/公钥。第一对必须是已知的。第二对为每个令牌随机生成。

代码示例

从字节生成对称密钥

let key = [
	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,
];
let amora = Amora::amora_zero(&key);
let payload = "sample_payload_just_for_testing";
let token = amora.encode(&payload.as_bytes(), 1);
let decoded = amora.decode(&token, true).unwrap_or("".into());
let decoded = std::str::from_utf8(&decoded).unwrap_or("");

从字符串生成对称密钥

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

从字节生成非对称密钥

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

从字符串生成非对称密钥

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

从令牌中获取元数据

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

依赖项

~2.5-4MB
~77K SLoC