Useage
// util
// 生成随机数,如
let salt = util::generate_nonce_ascii_str(32);
// crypt
// 封装好的一些加密工具,如生成ed25519和X25519密钥对,aes-256-gcm加解密等
let peer: ([u8; 32], [u8; 32]) = crypt::gen_ed25519()?;
println!("{},{}", crypt::b64(&peer.0)?, crypt::b64(&peer.1)?);
// client
// 从注册中心获取配置,并重载到ENV中
if let Err(_) = client::load_config().await {};
// http_header
// 构建客户端的authorization,兼容大部分主流V3版本,如aliyun、腾讯云、aws、yunli
struct YunLiUtcHeaderV3;
impl UtcHeaderV3 for YunLiUtcHeaderV3 {
fn host(&self) -> &'static str {
"pass.lellm.com:8883"
//"localhost:8080"
}
fn alg(&self) -> &'static str {
//"YUN3-HMAC-SHA256"
"YUN3-ED25519"
}
fn canonical(&self, action: String, _hashed_payload: &[u8], map: &mut BTreeMap<&str, String>) {
let utc = self.datetime_ymd();
map.insert("x-yun-action", action);
map.insert("x-yun-date", utc.0);
map.insert("x-yun-timestamp", utc.1);
map.insert("x-yun-nonce", utc.2);
}
fn sign(&self, key: &[u8], hashed_canonical: &[u8], _btm: &BTreeMap<&str, String>) -> Result<String> {
crypt::b64(&crypt::sign_ed25519(hashed_canonical, key)?)
}
}
let (app_key, token) = app_key(&envs).await?;
let req = RequestV3::new(&action, &json, app_id.to_string(), app_key);
let auth_header = AuthorizationHeader::new(YunLiUtcHeaderV3, req);
let mut headers = auth_header.authorization()?;
// 解析服务端的authorization,验证签名
fn auth_headers<'a>(
authorization: Option<&'a str>,
headers: &'a HeaderMap<HeaderValue>,
) -> Result<(u32, &'a str, &'a str, &'a str, BTreeMap<&'a str, &'a str>), StatusCode> {
let auth_str = authorization.ok_or(StatusCode::UNAUTHORIZED)?;
let (key_id, alg, _credential, signed_header, sign) =
yunli::http_header::parse_auth_yun3(auth_str).ok_or(StatusCode::UNAUTHORIZED)?;
let key_id: u32 = key_id.parse().map_err(|_| StatusCode::UNAUTHORIZED)?;
let signed_headers_map = yunli::http_header::signed_headers_map(signed_header, headers);
Ok((key_id, alg, signed_header, sign, signed_headers_map))
}
async fn auth_signature<'a>(
key_id: u32,
alg: &str,
sign: &str,
signed_headers: &str,
signed_headers_map: &BTreeMap<&'a str, &'a str>,
uri: &str,
payload_bytes: Bytes,
) -> Result<(), StatusCode> {
let key_bytes = cache::key::get().await.sign_verify_key(key_id).await.map_err(|e| {
warn!("key_bytes err, {}", e);
StatusCode::UNAUTHORIZED
})?;
let reqv3 = RequestV3::new_post(uri, payload_bytes, key_id.to_string(), key_bytes, alg, sign)
.map_err(|_| StatusCode::UNAUTHORIZED)?;
let valid = yunli::http_header::valid_auth_yun3(&reqv3, signed_headers, signed_headers_map)
.map_err(|_| StatusCode::UNAUTHORIZED)?;
if !valid {
warn!("sign err, uri:{}, sign:{}", uri, sign);
return Err(StatusCode::UNAUTHORIZED);
}
Ok(())
}