picky/http/
mod.rs

1//! Signing HTTP Messages
2//!
3//! This module provides an implementation of a subset of
4//! [draft-cavage-http-signatures-12 RFC](https://tools.ietf.org/html/draft-cavage-http-signatures-12).
5//!
6//! # Example
7//! ```
8//! use picky::{
9//!     http::http_signature::{HttpSignatureBuilder, HttpSignature},
10//!     signature::SignatureAlgorithm,
11//!     hash::HashAlgorithm,
12//!     key::PrivateKey,
13//!     pem::parse_pem,
14//! };
15//! use http::{request, header::{self, HeaderName}, method::Method};
16//!
17//! // all you need to generate a http signature
18//!
19//! let private_rsa_key: &str = "-----BEGIN RSA PRIVATE KEY-----\n\
20//!     MIIEpgIBAAKCAQEApDx0MjvRzmxYXKfqHy0gN1znX6rSU2EnsDTbZaU1UcsMmRNx\n\
21//!     L+FqDNzwNutCSQlkujzR37+bHGTxOnRvvSG3lwRvDBZepYWPum9WDqa9T5gTS/Cj\n\
22//!     luq/oSsOyt/tUDO/GcNPTTfUQlgtOZ+zRo6FA0rpAQ8CrQm7XzGQ0DMoDU1SVNnu\n\
23//!     tFJowlece9Y4NtAfhA+kJ5IEmcE9AgwxJY/iCyCxUEBUe7biwbUafLdtA3+3S8Bu\n\
24//!     hBXAr+1BING3qS0vl08+3eaFq5q7f7VwcYOhUmH13itqSGwDznCk4oDQl+qn9DQZ\n\
25//!     X9/09KtsgxuIcozxj0RwGKX8qkz4TlAGJw+oNwIDAQABAoIBAQCN9IrimH3iFBfU\n\
26//!     Dnb4d4KvF6gNMpMU6pbpYOZ51vBdQEolTX65yfZmI9mlPndOtcXQi51D7lNdmYo/\n\
27//!     4kBqk2giKfzpz7QDEYyHspAJnelnkKStMNPVMBZucc8ZX6+5cOCunfg/YBAhQCHm\n\
28//!     +rh0Nd+WVvtKpPTFJ/JCd48Zxf3KcDZD+AsWTjPt4zte8KdcwxiD3MrFunxgeujX\n\
29//!     n0U0/f7hvX/7JBQ20gu2tD9whEaS2Gn8E4WpEV8wC6Ah1pU9mZNZ0u8clW9SV0de\n\
30//!     ay0mHw8y/Wx6rkEMvrecK6mWbwSQGfRq+crI9PCwA5wn/EZmpQrQs9r5MLtDKVsQ\n\
31//!     r9axQrSRAoGBANB53u3mxY9ByiYGT5Ge/33+BjANXxmIPG0TWgV1D8MhwFiaiHF+\n\
32//!     tiEzoz4vi23Q+GeHyoM1wxw8VurDX+vcIJbZ0dyGOM/6F0eago7ZAtvHMdUdahAO\n\
33//!     X+klqG8kIysgFXSzaU2w76816iIaXiZlDZUghrnd3wmgu9jhl3HCUlltAoGBAMms\n\
34//!     2uufuk26nssF+woQuy017lgLUNFCRrO9F3iwIiyY5R/q372gsx8HVzjYGKY8CF6v\n\
35//!     m6JFfxogp44ZcafYOeu+iXbqoCAK4BTdbFB7/D3rX7WgidaxUlLGoXsNFIUIVubR\n\
36//!     jaRA7l3tl3fkpdqUAye6zosMKp2oybQLyX5hLAWzAoGBAJKhVUIA8W1cOaFbCPYE\n\
37//!     XfExDQsZLI1ZvB5/4O47srVtdMsdDeC93b4mgqfHawr3UvAGm1KEKtIeQofmmP3c\n\
38//!     mvNfCvNPWIA3h84uB6wPSKpqRUt+382hPqZOfVSGl1HKxCyL0AH78+lJQ39vCk94\n\
39//!     /f+om/n46tnrupPFv+4cXi1VAoGBALzSSmYxtozwHZyYjOJvp9A8nltwvMov82J1\n\
40//!     uHQW9OgsftnTXoh83Tg/9zoRmYKK0otUf7L+vnIIANjamb88g35ldu8P3bwicosW\n\
41//!     hUMV0qVmqsWy+Vs5yooVzzsWlA+6LyMNMECJSqRGv3pRabesvQeFr7wgOAZE8hTQ\n\
42//!     tGbPNBhhAoGBAIkXxIJT0OMKSt/A7wDE9wd3dtC8mbkqr5aZTvwiuD6OvNDdXb/J\n\
43//!     i03ns56mIflifVLPYVmCEXdYIzSv7HfeR4d78bAvqiMFfnQ2PF3tuoKMSvQM0m8/\n\
44//!     f3VhEFFMrUTTRMX/9PR0ITQtnZlWIDfBVgXPmWqTqCGOMYsRPv70LGse\n\
45//!     -----END RSA PRIVATE KEY-----";
46//! let pem = parse_pem(private_rsa_key).expect("couldn't parse pem");
47//! let private_key = PrivateKey::from_pem(&pem).expect("couldn't parse private key");
48//!
49//! let req = request::Builder::new()
50//!     .method(Method::GET)
51//!     .uri("/foo")
52//!     .header("Host", "example.org")
53//!     .header(header::DATE, "Tue, 07 Jun 2014 20:51:35 GMT")
54//!     .header("X-Example", " Example header       with some whitespace.   ")
55//!     .header("X-EmptyHeader", "")
56//!     .header(header::CACHE_CONTROL, "max-age=60")
57//!     .header(header::CACHE_CONTROL, "must-revalidate")
58//!     .body(())
59//!     .expect("couldn't build request");
60//!
61//! let (parts, _) = req.into_parts();
62//!
63//! // generate http signature
64//!
65//! let http_signature = HttpSignatureBuilder::new()
66//!     .key_id("my-rsa-key")
67//!     .signature_method(&private_key, SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_224))
68//!     // `picky::http::http_request::HttpRequest` trait is implemented for `http::request::Parts`
69//!     // for `http` crate with `http_trait_impl` feature gate
70//!     .generate_signing_string_using_http_request(&parts)
71//!     .request_target()
72//!     .created(1402170695)
73//!     .http_header("host")
74//!     .http_header(header::DATE.as_str())
75//!     .http_header(header::CACHE_CONTROL.as_str())
76//!     .http_header("x-emptyheader")
77//!     .http_header("X-EXAMPLE")
78//!     .build()
79//!     .expect("couldn't generate http signature");
80//!
81//! let http_signature_str = http_signature.to_string();
82//!
83//! assert_eq!(
84//!     http_signature_str,
85//!     "Signature keyId=\"my-rsa-key\",algorithm=\"rsa-sha224\",created=1402170695,\
86//!      headers=\"(request-target) (created) host date cache-control x-emptyheader x-example\",\
87//!      signature=\"QwuxxMSuvCdA5a2cDOjg+1WFEEGa/gD8fWwKm7gah4IUCssrie+bA5sp9wH7Jz8TQYh/XNDRUHKc\
88//!                  0oziBAIy1CsfDQWGRM+pAonfXEJufdt07v/i0OFhj5rBJfoOWPUcJ0cXzu0gs6svNhvimS3h2g30\
89//!                  gsnw1+Qjgv0+5HFwqZH4i+bHzaj0r9vIZZnnk3ecg8O2uOLuG5jCszJU9SBA0ug8l/NrQPJXMhCO\
90//!                  X59HkNVCkT4TPOovNZHyJQwu8IDhba0evPTCIvrzULpN4qY+ZAua2i3wGwWqFUgbm4eBJS2pwjWr\
91//!                  XyRusoELK0BjJ8a0KdOegmbEViIxy/Uqu0L2yQ==\""
92//! );
93//!
94//! // parse a http signature and verify it
95//!
96//! let parsed_http_signature = http_signature_str.parse::<HttpSignature>()
97//!     .expect("couldn't parse http signature");
98//!
99//! assert_eq!(parsed_http_signature, http_signature);
100//!
101//! parsed_http_signature.verifier()
102//!     .signature_method(&private_key.to_public_key(), SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_224))
103//!     .generate_signing_string_using_http_request(&parts)
104//!     .now(1402170695)
105//!     .verify()
106//!     .expect("couldn't verify signature");
107//!
108//! // alternatively you can provide a pre-generated signing string
109//!
110//! let signing_string =
111//!     "get /foo\n\
112//!      (created): 1402170695\n\
113//!      host: example.org\n\
114//!      date: Tue, 07 Jun 2014 20:51:35 GMT\n\
115//!      cache-control: max-age=60, must-revalidate\n\
116//!      x-emptyheader:\n\
117//!      x-example: Example header       with some whitespace.";
118//!
119//! let http_signature_pre_generated = HttpSignatureBuilder::new()
120//!     .key_id("my-rsa-key")
121//!     .signature_method(&private_key, SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_224))
122//!     .pre_generated_signing_string(signing_string)
123//!     .build()
124//!     .expect("couldn't generate http signature using pre-generated signing string");
125//!
126//! let http_signature_pre_generated_str = http_signature_pre_generated.to_string();
127//!
128//! assert_eq!(http_signature_pre_generated, http_signature);
129//! assert_eq!(http_signature_pre_generated_str, http_signature_str);
130//!
131//! parsed_http_signature.verifier()
132//!     .signature_method(&private_key.to_public_key(), SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_224))
133//!     .pre_generated_signing_string(signing_string)
134//!     .now(1402170695)
135//!     .verify()
136//!     .expect("couldn't verify signature using pre-generated signing string");
137//! ```
138
139pub mod http_request;
140pub mod http_signature;
141
142pub use http_request::HttpRequest;
143pub use http_signature::HttpSignature;