diff options
Diffstat (limited to 'third_party/rust/hawk/src/lib.rs')
-rw-r--r-- | third_party/rust/hawk/src/lib.rs | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/third_party/rust/hawk/src/lib.rs b/third_party/rust/hawk/src/lib.rs new file mode 100644 index 0000000000..4bde1229e2 --- /dev/null +++ b/third_party/rust/hawk/src/lib.rs @@ -0,0 +1,173 @@ +//! The `hawk` crate provides support for [Hawk](https://github.com/hueniverse/hawk) +//! authentictation. It is a low-level crate, used by higher-level crates to integrate with various +//! Rust HTTP libraries. For example `hyper-hawk` integrates Hawk with Hyper. +//! +//! # Examples +//! +//! ## Hawk Client +//! +//! A client can attach a Hawk Authorization header to requests by providing credentials to a +//! Request instance, which will generate the header. +//! +//! ``` +//! use hawk::{RequestBuilder, Credentials, Key, SHA256, PayloadHasher}; +//! use std::time::{Duration, UNIX_EPOCH}; +//! +//! fn main() { +//! // 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); +//! } +//! ``` +//! +//! A client that wishes to use a bewit (URL parameter) can do so as follows: +//! +//! ``` +//! 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 Server +//! +//! To act as a server, parse the Hawk Authorization header from the request, generate a new +//! Request instance, and use the request to validate the header. +//! +//! ``` +//! use hawk::{RequestBuilder, Header, Key, SHA256}; +//! use hawk::mac::Mac; +//! use std::time::{Duration, UNIX_EPOCH}; +//! +//! fn main() { +//! 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?"); +//! } +//! } +//! ``` +//! +//! A server which validates bewits looks like this: +//! +//! ``` +//! 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)); +//! ``` +//! +//! ## Features +//! +//! By default, the `use_ring` feature is enabled, which means that this crate will +//! use `ring` for all cryptographic operations. +//! +//! Alternatively, one can configure the crate with the `use_openssl` +//! feature to use the `openssl` crate. +//! +//! If no features are enabled, you must provide a custom implementation of the +//! [`hawk::crypto::Cryptographer`] trait to the `set_cryptographer` function, or +//! the cryptographic operations will panic. +//! +//! Attempting to configure both the `use_ring` and `use_openssl` features will +//! result in a build error. + +#[cfg(test)] +#[macro_use] +extern crate pretty_assertions; + +mod header; +pub use crate::header::Header; + +mod credentials; +pub use crate::credentials::{Credentials, DigestAlgorithm, Key}; + +mod request; +pub use crate::request::{Request, RequestBuilder}; + +mod response; +pub use crate::response::{Response, ResponseBuilder}; + +mod error; +pub use crate::error::*; + +mod payload; +pub use crate::payload::PayloadHasher; + +mod bewit; +pub use crate::bewit::Bewit; + +pub mod mac; + +pub mod crypto; + +pub const SHA256: DigestAlgorithm = DigestAlgorithm::Sha256; +pub const SHA384: DigestAlgorithm = DigestAlgorithm::Sha384; +pub const SHA512: DigestAlgorithm = DigestAlgorithm::Sha512; |