diff --git a/examples/basic_sign.rs b/examples/basic_sign.rs index 90c9fbe..7dd7c99 100644 --- a/examples/basic_sign.rs +++ b/examples/basic_sign.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use bytes::BytesMut; use http_sign::*; -use http_sign::message::{BorrowedHttpMessage, Method}; +use http_sign::message::{BorrowedHttpRequest, Method}; use ring::{rand::SystemRandom, signature::RsaKeyPair}; static KEY: &'static [u8] = include_bytes!("example-rsa-2048-key.pk8"); @@ -12,7 +12,7 @@ static KEY: &'static [u8] = include_bytes!("example-rsa-2048-key.pk8"); fn main() { let mut headers = HashMap::new(); headers.insert("x-foo".to_string(), "bar".to_string()); - let mut request = http_sign::message::OwnedHttpMessage::new( + let mut request = http_sign::message::OwnedHttpRequest::new( Method::Get, "/foo/bar".to_string(), Some("foo=bar".to_string()), diff --git a/src/algorithm.rs b/src/algorithm.rs index d172dfe..05c95f1 100644 --- a/src/algorithm.rs +++ b/src/algorithm.rs @@ -22,10 +22,15 @@ pub trait SignatureAlgorithm { pub mod hs { use std::io::Write; - use ring::{hmac::Key, rand::SecureRandom, signature::{RsaEncoding, RsaKeyPair}}; + use ring::{hmac::Key, rand::SecureRandom, signature::RsaKeyPair}; use super::SignatureAlgorithm; + /// The "hs2019" [signature algorithm](super::SignatureAlgorithm). This is the only + /// non-deprecated algorithm. Unlike the other algorithms, the hash and digest + /// functions are not implied by the choice of this signature algorithm. Instead, the + /// hash and digest functions are chosen based on the key used. RSA, HMAC, and ECDSA + /// keys are all supported. pub struct Hs2019(Inner); enum Inner { @@ -118,6 +123,7 @@ pub mod hs { } } +#[allow(deprecated)] pub mod rsa { use std::fmt::Debug; use std::io::Write; @@ -126,6 +132,8 @@ pub mod rsa { use super::SignatureAlgorithm; + /// The "rsa-sha256" [signature algorithm](super::SignatureAlgorithm). Deprecated by + /// the standard because it reveals which hash and digest algorithm is used. #[deprecated] pub struct RsaSha256 { key_id: String, @@ -176,14 +184,17 @@ pub mod rsa { } } +#[allow(deprecated)] pub mod hmac { use std::fmt::Debug; use std::io::Write; - use ring::{rand::SecureRandom, hmac::Key}; + use ring::hmac::Key; use super::SignatureAlgorithm; + /// The "hmac-sha256" [signature algorithm](super::SignatureAlgorithm). Deprecated by + /// the standard because it reveals which hash and digest algorithm is used. #[deprecated] pub struct HmacSha256 { key_id: String, @@ -204,7 +215,7 @@ pub mod hmac { impl SignatureAlgorithm for HmacSha256 { fn name(&self) -> &str { - "rsa-sha256" + "hmac-sha256" } fn key_id(&self) -> &str { @@ -231,6 +242,7 @@ pub mod hmac { } } +#[allow(deprecated)] pub mod ecdsa { use std::fmt::Debug; use std::io::Write; @@ -239,6 +251,8 @@ pub mod ecdsa { use super::SignatureAlgorithm; + /// The "ecdsa-sha256" [signature algorithm](super::SignatureAlgorithm). Deprecated by + /// the standard because it reveals which hash and digest algorithm is used. #[deprecated] pub struct EcdsaSha256 { key_id: String, diff --git a/src/lib.rs b/src/lib.rs index cbe9c0c..0b53a31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ mod algorithm; pub mod message; mod signature; +#[allow(deprecated)] pub use algorithm::{ SignatureAlgorithm, hs::Hs2019, diff --git a/src/message.rs b/src/message.rs index f349e11..4a077bb 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,22 +1,21 @@ -/// This trait exposes all of the information about a HTTP message that is required to -/// produce the signature header. This trait can represent both HTTP requests and -/// responses. +/// This trait exposes all of the information about a HTTP request that is required to +/// produce the signature header. /// -/// The [OwnedHttpMessage] and [BorrowedHttpMessage] types are provided for simple use -/// cases where you do not have preexisting structs representing HTTP requests and responses -/// that you can use. In addition to those two convenience types, support for other common -/// community crates can be enabled by turning on the following **features**, all of which are -/// off by default. +/// The [OwnedHttpRequest] and [BorrowedHttpRequest] types are provided for simple use +/// cases where you do not have preexisting structs representing HTTP requests that you +/// can use. In addition to those two convenience types, support for other common +/// community crates can be enabled by turning on the following **features**, all of which +/// are off by default. /// - `http`: Enables support for the [http](https://crates.io/crates/http) crate's /// Request and HeaderMap types. -pub trait HttpMessage { +pub trait HttpRequest { /// The type of HTTP headers object. type Headers: Headers; - /// Returns a shared reference to the HTTP message headers. + /// Returns a shared reference to the HTTP request headers. fn headers(&self) -> &Self::Headers; - /// Returns a unique reference to the HTTP message headers. This is used by the + /// Returns a unique reference to the HTTP request headers. This is used by the /// [sign](super::sign) function to insert the signature header according to the /// chosen [algorithm](super::SignatureAlgorithm). fn headers_mut(&mut self) -> &mut Self::Headers; @@ -30,15 +29,15 @@ pub trait HttpMessage { /// The HTTP method. fn method(&self) -> Method; - /// The body data. If the message does not contain a body, this function should return + /// The body data. If the request does not contain a body, this function should return /// a 0-length slice. fn body(&self) -> &[u8]; } -/// This is a simple implementation of [HttpMessage] that does not depend on any external -/// library. It owns all of the message data. +/// This is a simple implementation of [HttpRequest] that does not depend on any external +/// library. It owns all of the request data. #[derive(Debug)] -pub struct OwnedHttpMessage { +pub struct OwnedHttpRequest { headers: H, path: String, query_string: Option, @@ -46,8 +45,8 @@ pub struct OwnedHttpMessage { body: Vec } -impl OwnedHttpMessage { - /// Build a new [OwnedHttpMessage] from owned components. +impl OwnedHttpRequest { + /// Build a new [OwnedHttpRequest] from owned components. pub fn new( method: Method, path: String, @@ -64,7 +63,7 @@ impl OwnedHttpMessage { } } -impl HttpMessage for OwnedHttpMessage { +impl HttpRequest for OwnedHttpRequest { type Headers = H; fn headers(&self) -> &Self::Headers { @@ -93,24 +92,24 @@ impl HttpMessage for OwnedHttpMessage { } -/// This is a simple implementation of [HttpMessage] that does not depend on any external -/// library. It borrows all of the message data. -pub struct BorrowedHttpMessage<'message, H> { - headers: &'message mut H, - path: &'message str, - query_string: Option<&'message str>, +/// This is a simple implementation of [HttpRequest] that does not depend on any external +/// library. It borrows all of the request data. +pub struct BorrowedHttpRequest<'request, H> { + headers: &'request mut H, + path: &'request str, + query_string: Option<&'request str>, method: Method, - body: &'message [u8] + body: &'request [u8] } -impl<'message, H> BorrowedHttpMessage<'message, H> { - /// Build a new [BorrowedHttpMessage] from borrowed components. +impl<'request, H> BorrowedHttpRequest<'request, H> { + /// Build a new [BorrowedHttpRequest] from borrowed components. pub fn new( method: Method, - path: &'message str, - query_string: Option<&'message str>, - headers: &'message mut H, - body: &'message [u8]) -> Self { + path: &'request str, + query_string: Option<&'request str>, + headers: &'request mut H, + body: &'request [u8]) -> Self { Self { headers, path, @@ -121,7 +120,7 @@ impl<'message, H> BorrowedHttpMessage<'message, H> { } } -impl<'message, H: Headers> HttpMessage for BorrowedHttpMessage<'message, H> { +impl<'request, H: Headers> HttpRequest for BorrowedHttpRequest<'request, H> { type Headers = H; fn headers(&self) -> &Self::Headers { @@ -181,7 +180,7 @@ impl Method { } /// This trait allows the signature generation logic both read and write access to the -/// HTTP headers contained within a [HTTP message](HttpMessage). +/// HTTP headers contained within a [HTTP request](HttpRequest). pub trait Headers { /// Iterator over header names. This library can only work with header names that are /// valid UTF-8 (and by extension, all ASCII-only headers). @@ -190,10 +189,10 @@ pub trait Headers { /// strings in any encoding. type ValueIter<'a> : Iterator; - /// Returns an iterator over all the header names defined for the HTTP message. + /// Returns an iterator over all the header names defined for the HTTP request. fn header_names<'this>(&'this self) -> Self::NameIter<'this>; - /// Returns true if the HTTP message contains a header with the given `name`, or false + /// Returns true if the HTTP request contains a header with the given `name`, or false /// if no such header is present. It is up to the implementor of this trait whether /// header names are case sensitive. fn contains_header(&self, name: &str) -> bool; @@ -309,16 +308,16 @@ mod btree_map { } /// Adds support for using types from the [http](https://crates.io/crates/http) crate -/// as implementations of [HttpMessage] and [Headers]. +/// as implementations of [HttpRequest] and [Headers]. /// /// Requires the `http` feature to be enabled. #[cfg(feature = "http")] mod http { use http::{HeaderMap, HeaderValue, header::HeaderName}; - use super::{HttpMessage, Method}; + use super::{HttpRequest, Method}; - impl> HttpMessage for ::http::Request { + impl> HttpRequest for ::http::Request { type Headers = ::http::HeaderMap; fn headers(&self) -> &Self::Headers { diff --git a/src/signature.rs b/src/signature.rs index 9fe9f8c..3261ccd 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -3,14 +3,14 @@ use std::time::SystemTime; use bytes::{BufMut, BytesMut}; -use crate::{algorithm::SignatureAlgorithm, message::{Headers, HttpMessage}}; +use crate::{algorithm::SignatureAlgorithm, message::{Headers, HttpRequest}}; /// An element that contributes to the signature calculation. Standard HTTP headers may /// be included in the signature, as well as special non-header fields such as /// `(request-target)`, `(created)`, and `(expires)`. The list of signature elements -/// determines which parts of the HTTP message are protected by the signature. The order -/// of signature elements that is chosen is also important in that it determines the -/// order in which the signature input string is formed. +/// passed to the [sign] function determines which parts of the HTTP message are protected +/// by the signature. The order of signature elements that is chosen is also important in +/// that it determines the order in which the signature input string is formed. #[derive(Debug, Eq, PartialEq)] pub enum SignatureElement<'a> { /// The `(request-target)` special field. Results in the concatenation of the lowercase @@ -95,7 +95,7 @@ pub fn sign<'sig_elems, SigAlg, Msg>( ) -> Result<(), SignError> where SigAlg: SignatureAlgorithm, - Msg: HttpMessage, + Msg: HttpRequest, { validate_signature_elements(sig_alg, message, signature_elements)?; let now = SystemTime::now(); @@ -106,7 +106,7 @@ pub fn sign<'sig_elems, SigAlg, Msg>( .map_err(|_err| SignError::Internal("Unable to determine (expires) Unix timestamp"))? .as_secs(); let signature_input = build_canonical_signature_input( - temporary_buffer, sig_alg, message, created, expires, signature_elements)?; + temporary_buffer, message, created, expires, signature_elements)?; let encoded_signature = get_encoded_signature(temporary_buffer, sig_alg, signature_input)?; let signature_header = build_final_header(temporary_buffer, scheme, sig_alg, encoded_signature, created, expires, signature_elements)?; match scheme { @@ -116,7 +116,7 @@ pub fn sign<'sig_elems, SigAlg, Msg>( Ok(()) } -fn validate_signature_elements( +fn validate_signature_elements( sig_alg: &SigAlg, message: &mut Msg, signature_elements: &[SignatureElement<'_>], @@ -158,17 +158,15 @@ fn validate_signature_elements( Ok(()) } -fn build_canonical_signature_input<'sig_elems, SigAlg, Msg>( +fn build_canonical_signature_input<'sig_elems, Msg>( temporary_buffer: &mut BytesMut, - sig_alg: &SigAlg, message: &mut Msg, created: u64, expires: u64, signature_elements: &[SignatureElement<'_>], ) -> Result where - SigAlg: SignatureAlgorithm, - Msg: HttpMessage, + Msg: HttpRequest, { temporary_buffer.clear(); for element in signature_elements { @@ -223,7 +221,7 @@ fn build_canonical_signature_input<'sig_elems, SigAlg, Msg>( fn get_encoded_signature( temporary_buffer: &mut BytesMut, sig_alg: &SigAlg, - mut signature_input: BytesMut, + signature_input: BytesMut, ) -> Result { temporary_buffer.clear(); sig_alg.sign(&signature_input, &mut temporary_buffer.writer())