13个稳定版本 (4个主要版本)

5.0.0 2024年1月26日
4.0.0 2022年5月5日
3.2.1 2020年7月27日
3.1.0 2020年1月14日
1.0.2 2017年7月3日

#251 in 密码学

Download history 465/week @ 2024-03-14 628/week @ 2024-03-21 583/week @ 2024-03-28 697/week @ 2024-04-04 361/week @ 2024-04-11 569/week @ 2024-04-18 906/week @ 2024-04-25 776/week @ 2024-05-02 941/week @ 2024-05-09 819/week @ 2024-05-16 459/week @ 2024-05-23 854/week @ 2024-05-30 697/week @ 2024-06-06 508/week @ 2024-06-13 378/week @ 2024-06-20 468/week @ 2024-06-27

2,252 每月下载量
5 个crate中使用了(2个直接使用)

MPL-2.0 许可证

96KB
2K SLoC

Hawk认证的Rust实现

这是Hawk的Rust实现。


lib.rs:

hawk crate提供了对Hawk认证的支持。这是一个低级crate,由高级crate用于与各种Rust HTTP库集成。例如,hyper-hawk将Hawk与Hyper集成。

示例

Hawk客户端

客户端可以通过向Request实例提供凭证来向请求附加Hawk授权头,这将生成该头。

use hawk::{RequestBuilder, Credentials, Key, SHA256, PayloadHasher};
use std::time::{Duration, UNIX_EPOCH};

// provide the Hawk id and key
let credentials = Credentials {
    id: "test-client".to_string(),
    key: Key::new(vec![99u8; 32], SHA256).unwrap(),
};

let payload_hash = PayloadHasher::hash("text/plain", SHA256, "request-body").unwrap();

// provide the details of the request to be authorized
 let request = RequestBuilder::new("POST", "example.com", 80, "/v1/users")
    .hash(&payload_hash[..])
    .request();

// Get the resulting header, including the calculated MAC; this involves a random
// nonce, so the MAC will be different on every request.
let header = request.make_header(&credentials).unwrap();

// the header would the be attached to the request
assert_eq!(header.id.unwrap(), "test-client");
assert_eq!(header.mac.unwrap().len(), 32);
assert_eq!(header.hash.unwrap().len(), 32);

希望使用bewit(URL参数)的客户端可以这样操作

use hawk::{RequestBuilder, Credentials, Key, SHA256, Bewit};
use std::time::Duration;
use std::borrow::Cow;

let credentials = Credentials {
    id: "me".to_string(),
    key: Key::new("tok", SHA256).unwrap(),
};

let client_req = RequestBuilder::new("GET", "mysite.com", 443, "/resource").request();
let client_bewit = client_req
    .make_bewit_with_ttl(&credentials, Duration::from_secs(10))
    .unwrap();
let request_path = format!("/resource?bewit={}", client_bewit.to_str());
// .. make the request

Hawk服务器

要作为服务器,请从请求中解析Hawk授权头,生成一个新的Request实例,并使用该请求来验证头。

use hawk::{RequestBuilder, Header, Key, SHA256};
use hawk::mac::Mac;
use std::time::{Duration, UNIX_EPOCH};

let mac = Mac::from(vec![7, 22, 226, 240, 84, 78, 49, 75, 115, 144, 70,
                         106, 102, 134, 144, 128, 225, 239, 95, 132, 202,
                         154, 213, 118, 19, 63, 183, 108, 215, 134, 118, 115]);
// get the header (usually from the received request; constructed directly here)
let hdr = Header::new(Some("dh37fgj492je"),
                      Some(UNIX_EPOCH + Duration::new(1353832234, 0)),
                      Some("j4h3g2"),
                      Some(mac),
                      Some("my-ext-value"),
                      Some(vec![1, 2, 3, 4]),
                      Some("my-app"),
                      Some("my-dlg")).unwrap();

// build a request object based on what we know
let hash = vec![1, 2, 3, 4];
let request = RequestBuilder::new("GET", "localhost", 443, "/resource")
    .hash(&hash[..])
    .request();

let key = Key::new(vec![99u8; 32], SHA256).unwrap();
let one_week_in_secs = 7 * 24 * 60 * 60;
if !request.validate_header(&hdr, &key, Duration::from_secs(5200 * one_week_in_secs)) {
    panic!("header validation failed. Is it 2117 already?");
}

验证bewit的服务器看起来像这样

use hawk::{RequestBuilder, Credentials, Key, SHA256, Bewit};
use std::time::Duration;
use std::borrow::Cow;

let credentials = Credentials {
    id: "me".to_string(),
    key: Key::new("tok", SHA256).unwrap(),
};

// simulate the client generation of a bewit
let client_req = RequestBuilder::new("GET", "mysite.com", 443, "/resource").request();
let client_bewit = client_req
    .make_bewit_with_ttl(&credentials, Duration::from_secs(10))
    .unwrap();
let request_path = format!("/resource?bewit={}", client_bewit.to_str());

let mut maybe_bewit = None;
let server_req = RequestBuilder::new("GET", "mysite.com", 443, &request_path)
    .extract_bewit(&mut maybe_bewit).unwrap()
    .request();
let bewit = maybe_bewit.unwrap();
assert_eq!(bewit.id(), "me");
assert!(server_req.validate_bewit(&bewit, &credentials.key));

特性

默认情况下,启用了use_ring特性,这意味着此crate将使用ring对所有加密操作。

或者,可以通过配置crate的use_openssl特性来使用openssl crate。

如果没有启用任何特性,则必须向set_cryptographer函数提供hawk::crypto::Cryptographer trait的自定义实现,否则加密操作将引发恐慌。

尝试同时配置use_ringuse_openssl特性将导致构建错误。

依赖关系

~2–12MB
~171K SLoC