diff options
author | Martin Fischer <martin@push-f.com> | 2022-07-30 03:14:37 +0200 |
---|---|---|
committer | Martin Fischer <martin@push-f.com> | 2022-07-30 03:14:37 +0200 |
commit | e3fb7739550ad71b6895a581fdbf16bf3629762e (patch) | |
tree | 1e25c2e773bcb67ff83d2894d8cc0e3b69d663db | |
parent | 6568d9f9119deb9bc4aa698909ef10d169c75ca8 (diff) |
-rw-r--r-- | src/security/signed.rs | 72 |
1 files changed, 0 insertions, 72 deletions
diff --git a/src/security/signed.rs b/src/security/signed.rs deleted file mode 100644 index 080bed2..0000000 --- a/src/security/signed.rs +++ /dev/null @@ -1,72 +0,0 @@ -use hmac::{Hmac, Mac}; -use sha2::Sha256; - -const SIGNED_KEY_LEN: usize = 32; -const BASE64_DIGEST_LEN: usize = 44; - -/// A convenience wrapper around HMAC. -/// -/// This code was adapted from the [`cookie`] crate which does not make the sign and verify functions public -/// forcing the use of [`CookieJar`](cookie::CookieJar)s, which are akward to work with without a high-level framework. -// Thanks to Sergio Benitez for writing the original code and releasing it under MIT! -pub struct Key(pub [u8; SIGNED_KEY_LEN]); - -impl Key { - const fn zero() -> Self { - Key([0; SIGNED_KEY_LEN]) - } - - /// Attempts to generate signing/encryption keys from a secure, random - /// source. Keys are generated nondeterministically. If randomness cannot be - /// retrieved from the underlying operating system, returns `None`. - pub fn try_generate() -> Option<Key> { - use rand::RngCore; - - let mut rng = rand::thread_rng(); - let mut both_keys = [0; SIGNED_KEY_LEN]; - rng.try_fill_bytes(&mut both_keys).ok()?; - Some(Key::from(&both_keys)) - } - - /// Creates a new Key from a 32 byte cryptographically random string. - pub fn from(key: &[u8]) -> Key { - if key.len() < SIGNED_KEY_LEN { - panic!("bad key length: expected >= 32 bytes, found {}", key.len()); - } - - let mut output = Key::zero(); - output.0.copy_from_slice(&key[..SIGNED_KEY_LEN]); - output - } - - /// Signs the value providing integrity and authenticity. - pub fn sign(&self, value: &str) -> String { - // Compute HMAC-SHA256 of the cookie's value. - let mut mac = Hmac::<Sha256>::new_from_slice(&self.0).expect("good key"); - mac.update(value.as_bytes()); - - // Cookie's new value is [MAC | original-value]. - let mut new_value = base64::encode(&mac.finalize().into_bytes()); - new_value.push_str(value); - new_value - } - - /// Extracts the value from a string signed with [`Key::sign`]. - /// Fails if the string is malformed or the signature doesn't match. - pub fn verify(&self, value: &str) -> Result<String, String> { - if value.len() < BASE64_DIGEST_LEN { - return Err("length of value is <= BASE64_DIGEST_LEN".to_string()); - } - - // Split [MAC | original-value] into its two parts. - let (digest_str, value) = value.split_at(BASE64_DIGEST_LEN); - let digest = base64::decode(digest_str).map_err(|_| "bad base64 digest")?; - - // Perform the verification. - let mut mac = Hmac::<Sha256>::new_from_slice(&self.0).expect("good key"); - mac.update(value.as_bytes()); - mac.verify_slice(&digest) - .map(|_| value.to_string()) - .map_err(|_| "value did not verify".to_string()) - } -} |