15个版本
0.0.15 | 2024年4月12日 |
---|---|
0.0.14 | 2024年3月14日 |
0.0.8 | 2024年2月29日 |
#333 in 密码学
392每月下载量
用于 httpsig-hyper
92KB
2K SLoC
httpsig-rs
工作进度
IETF RFC 9421的http消息签名的实现。
这个crate提供了一个基本的库httpsig以及其扩展,用于hyper
的http库。目前,我们的库只能为hyper
的请求和响应消息进行签名和验证。
支持的签名算法
- 使用SHA-256的HMAC
- Ed25519
- 使用SHA-256的ECDSA-P256
- 使用SHA-384的ECDSA-P384
- [ ] 使用SHA-512的RSASSA-PSS
- [ ] 使用SHA-256的RSASSA-PKCS1-v1_5
由于与非恒定时间操作相关的问题,即Mervin攻击,目前我们没有任何计划支持RSA签名。
对hyper
(httpsig-hyper
)的扩展使用
这是一个使用非对称加密(如EdDSA)生成的签名的签名和验证的示例,其中PUBLIC_KEY_STRING
和SECRET_KEY_STRING
分别是PEM格式的公钥和私钥。还支持通过对称加密(HMAC-SHA256)生成和验证MAC。
签名和验证请求
use http::Request;
use http_body_util::Full;
use httpsig_hyper::{prelude::*, *};
type SignatureName = String;
const COVERED_COMPONENTS: &[&str] = &["@method", "date", "content-type", "content-digest"];
/// Signer function that generates a request with a signature
async fn signer<B>(&mut req: Request<B>) -> HttpSigResult<()> {
// build signature params that indicates objects to be signed
let covered_components = COVERED_COMPONENTS
.iter()
.map(|v| message_component::HttpMessageComponentId::try_from(*v))
.collect::<Result<Vec<_>, _>>()
.unwrap();
let mut signature_params = HttpSignatureParams::try_new(&covered_components).unwrap();
// set signing/verifying key information, alg and keyid
let secret_key = SecretKey::from_pem(SECRET_KEY_STRING).unwrap();
signature_params.set_key_info(&secret_key);
req
.set_message_signature(&signature_params, &secret_key, Some("custom_sig_name"))
.await
}
/// Validation function that verifies a request with a signature
async fn verifier<B>(req: &Request<B>) -> HttpSigResult<SignatureName> {
let public_key = PublicKey::from_pem(PUBLIC_KEY_STRING).unwrap();
let key_id = public_key.key_id();
// verify signature with checking key_id
req.verify_message_signature(&public_key, Some(&key_id)).await
}
#[tokio::main]
async fn main() {
let mut request_from_sender = ...;
let res = signer(request_from_sender).await;
assert!(res.is_ok())
// receiver verifies the request with a signature
let verified_message = receiver(&request_from_sender).await;
assert!(verification_res.is_ok());
// if needed, content-digest can be verified separately
let verified_request = request_from_sender.verify_content_digest().await;
assert!(verified_request.is_ok());
}
签名和验证响应
use http::{Request, Response};
use http_body_util::Full;
use httpsig_hyper::{prelude::*, *};
type SignatureName = String;
/// This includes the method of the request corresponding to the request (the second element)
const COVERED_COMPONENTS: &[&str] = &["@status", "\"@method\";req", "date", "content-type", "content-digest"];
/// Signer function that generates a response with a signature from response itself and corresponding request
async fn signer<B>(&mut res: Response<B>, corresponding_req: &Request<B>) -> HttpSigResult<()> {
// build signature params that indicates objects to be signed
let covered_components = COVERED_COMPONENTS
.iter()
.map(|v| message_component::HttpMessageComponentId::try_from(*v))
.collect::<Result<Vec<_>, _>>()
.unwrap();
let mut signature_params = HttpSignatureParams::try_new(&covered_components).unwrap();
// set signing/verifying key information, alg and keyid
let secret_key = SecretKey::from_pem(SECRET_KEY_STRING).unwrap();
signature_params.set_key_info(&secret_key);
req
.set_message_signature(&signature_params, &secret_key, Some("custom_sig_name"), Some(corresponding_req))
.await
}
/// Validation function that verifies a response with a signature from response itself and sent request
async fn verifier<B>(res: &Response<B>, sent_req: &Request<B>) -> HttpSigResult<SignatureName> {
let public_key = PublicKey::from_pem(PUBLIC_KEY_STRING).unwrap();
let key_id = public_key.key_id();
// verify signature with checking key_id
res.verify_message_signature(&public_key, Some(&key_id), Some(sent_req)).await
}
示例
有关使用hyper
扩展的详细示例,请参阅./httpsig-hyper/examples。
依赖关系
~8MB
~146K SLoC