3个不稳定版本
0.2.1 | 2024年3月8日 |
---|---|
0.2.0 | 2024年3月8日 |
0.1.0 | 2024年1月7日 |
#170 在 身份验证
每月106次下载
25KB
379 行
Amora
Amora是一个受JWT和Branca启发的安全令牌,但在某些方面有所增强。
主要功能
- 可以包含任何类型的有效负载: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