~vpzom/hancock

0871c8a4ea346540ce3bc4fad947427b5d33574d — Colin Reeder 1 year, 5 months ago 6a20e39
offer create_legacy
1 files changed, 56 insertions(+), 5 deletions(-)

M src/lib.rs
M src/lib.rs => src/lib.rs +56 -5
@@ 93,7 93,7 @@ impl<'a> Signature<'a> {
        request_method: &http::method::Method,
        request_path_and_query: &str,
        lifetime_secs: u64,
        headers: &mut http::header::HeaderMap,
        headers: &http::header::HeaderMap,
        sign: impl FnOnce(Vec<u8>) -> Result<Vec<u8>, E>,
    ) -> Result<Self, SignError<E>> {
        use std::io::Write;


@@ 151,6 151,59 @@ impl<'a> Signature<'a> {
        })
    }

    pub fn create_legacy<E: std::fmt::Debug>(
        key_id: &'a str,
        request_method: &http::method::Method,
        request_path_and_query: &str,
        headers: &http::header::HeaderMap,
        sign: impl FnOnce(Vec<u8>) -> Result<Vec<u8>, E>,
    ) -> Result<Self, SignError<E>> {
        use std::io::Write;

        if !headers.contains_key(http::header::DATE) {
            panic!("legacy signatures must contain Date header");
        }

        let mut body = Vec::new();

        write!(
            body,
            "(request-target): {} {}",
            request_method.as_str().to_lowercase(),
            request_path_and_query,
        )?;

        for name in headers.keys() {
            write!(body, "\n{}: ", name)?;

            let mut first = true;
            for value in headers.get_all(name) {
                if first {
                    first = false;
                } else {
                    write!(body, ", ")?;
                }

                body.extend(value.as_bytes());
            }
        }

        let header_names: Vec<_> = std::iter::once(SignatureHeaderName::RequestTarget)
            .chain(headers.keys().cloned().map(Into::into))
            .collect();

        let signature = sign(body).map_err(SignError::User)?;

        Ok(Self {
            algorithm: Some(http::header::HeaderName::from_static("hs2019")),
            created: None,
            expires: None,
            headers: Some(header_names),
            key_id: Some(key_id),
            signature,
        })
    }

    pub fn parse(value: &'a http::header::HeaderValue) -> Result<Self, ParseError> {
        let mut algorithm = None;
        let mut created = None;


@@ 239,7 292,7 @@ impl<'a> Signature<'a> {
        &self,
        request_method: &http::method::Method,
        request_path_and_query: &str,
        headers: &mut http::header::HeaderMap,
        headers: &http::header::HeaderMap,
        verify: impl FnOnce(&[u8], &[u8]) -> Result<bool, E>,
    ) -> Result<bool, VerifyError<E>> {
        use std::io::Write;


@@ 302,8 355,6 @@ impl<'a> Signature<'a> {
            }
        }

        if !verify(&body, &self.signature).map_err(VerifyError::User)? {
            false
        }
        verify(&body, &self.signature).map_err(VerifyError::User)
    }
}