mirror of
https://git.asonix.dog/asonix/http-signature-normalization.git
synced 2024-06-13 02:39:34 +00:00
194 lines
4.5 KiB
Rust
194 lines
4.5 KiB
Rust
|
//! Types for creating digests with the `ring` cryptography library
|
||
|
|
||
|
use crate::digest::DigestName;
|
||
|
|
||
|
/// A Sha256 digest backed by ring
|
||
|
pub struct Sha256 {
|
||
|
ctx: ring::digest::Context,
|
||
|
}
|
||
|
|
||
|
/// A Sha384 digest backed by ring
|
||
|
pub struct Sha384 {
|
||
|
ctx: ring::digest::Context,
|
||
|
}
|
||
|
|
||
|
/// A Sha512 digest backed by ring
|
||
|
pub struct Sha512 {
|
||
|
ctx: ring::digest::Context,
|
||
|
}
|
||
|
|
||
|
impl Sha256 {
|
||
|
/// Create a new empty digest
|
||
|
pub fn new() -> Self {
|
||
|
Self::default()
|
||
|
}
|
||
|
|
||
|
/// Extract the context
|
||
|
pub fn into_inner(self) -> ring::digest::Context {
|
||
|
self.ctx
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Default for Sha256 {
|
||
|
fn default() -> Self {
|
||
|
Sha256 {
|
||
|
ctx: ring::digest::Context::new(&ring::digest::SHA256),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Sha384 {
|
||
|
/// Create a new empty digest
|
||
|
pub fn new() -> Self {
|
||
|
Self::default()
|
||
|
}
|
||
|
|
||
|
/// Extract the context
|
||
|
pub fn into_inner(self) -> ring::digest::Context {
|
||
|
self.ctx
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Default for Sha384 {
|
||
|
fn default() -> Self {
|
||
|
Sha384 {
|
||
|
ctx: ring::digest::Context::new(&ring::digest::SHA384),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Sha512 {
|
||
|
/// Create a new empty digest
|
||
|
pub fn new() -> Self {
|
||
|
Self::default()
|
||
|
}
|
||
|
|
||
|
/// Extract the context
|
||
|
pub fn into_inner(self) -> ring::digest::Context {
|
||
|
self.ctx
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Default for Sha512 {
|
||
|
fn default() -> Self {
|
||
|
Sha512 {
|
||
|
ctx: ring::digest::Context::new(&ring::digest::SHA512),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl DigestName for Sha256 {
|
||
|
const NAME: &'static str = "SHA-256";
|
||
|
}
|
||
|
|
||
|
impl DigestName for Sha384 {
|
||
|
const NAME: &'static str = "SHA-384";
|
||
|
}
|
||
|
|
||
|
impl DigestName for Sha512 {
|
||
|
const NAME: &'static str = "SHA-512";
|
||
|
}
|
||
|
|
||
|
#[cfg(feature = "client")]
|
||
|
mod client {
|
||
|
use super::*;
|
||
|
use crate::digest::DigestCreate;
|
||
|
|
||
|
fn create(mut context: ring::digest::Context, input: &[u8]) -> String {
|
||
|
context.update(input);
|
||
|
let digest = context.finish();
|
||
|
base64::encode(digest.as_ref())
|
||
|
}
|
||
|
|
||
|
impl DigestCreate for Sha256 {
|
||
|
fn compute(&mut self, input: &[u8]) -> String {
|
||
|
create(self.ctx.clone(), input)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl DigestCreate for Sha384 {
|
||
|
fn compute(&mut self, input: &[u8]) -> String {
|
||
|
create(self.ctx.clone(), input)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl DigestCreate for Sha512 {
|
||
|
fn compute(&mut self, input: &[u8]) -> String {
|
||
|
create(self.ctx.clone(), input)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[cfg(feature = "server")]
|
||
|
mod server {
|
||
|
use super::*;
|
||
|
use crate::digest::{DigestPart, DigestVerify};
|
||
|
use tracing::{debug, warn};
|
||
|
|
||
|
fn verify(context: ring::digest::Context, name: &str, parts: &[DigestPart]) -> bool {
|
||
|
if let Some(part) = parts
|
||
|
.iter()
|
||
|
.find(|p| p.algorithm.to_lowercase() == name.to_lowercase())
|
||
|
{
|
||
|
debug!("Verifying digest type, {}", name);
|
||
|
let digest = context.finish();
|
||
|
let encoded = base64::encode(digest.as_ref());
|
||
|
|
||
|
return part.digest == encoded;
|
||
|
}
|
||
|
warn!("No matching digest algorithm found for {}", name);
|
||
|
warn!(
|
||
|
"Provided: [{}]",
|
||
|
parts.iter().fold(String::new(), |mut acc, item| {
|
||
|
if acc.is_empty() {
|
||
|
} else {
|
||
|
acc.push_str(", ");
|
||
|
}
|
||
|
acc.push_str(&item.algorithm);
|
||
|
acc
|
||
|
})
|
||
|
);
|
||
|
|
||
|
false
|
||
|
}
|
||
|
|
||
|
impl DigestVerify for Sha256 {
|
||
|
fn update(&mut self, part: &[u8]) {
|
||
|
self.ctx.update(part);
|
||
|
}
|
||
|
|
||
|
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||
|
let alg = self.ctx.algorithm();
|
||
|
let ctx = std::mem::replace(&mut self.ctx, ring::digest::Context::new(alg));
|
||
|
|
||
|
verify(ctx, Self::NAME, parts)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl DigestVerify for Sha384 {
|
||
|
fn update(&mut self, part: &[u8]) {
|
||
|
self.ctx.update(part);
|
||
|
}
|
||
|
|
||
|
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||
|
let alg = self.ctx.algorithm();
|
||
|
let ctx = std::mem::replace(&mut self.ctx, ring::digest::Context::new(alg));
|
||
|
|
||
|
verify(ctx, Self::NAME, parts)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl DigestVerify for Sha512 {
|
||
|
fn update(&mut self, part: &[u8]) {
|
||
|
self.ctx.update(part);
|
||
|
}
|
||
|
|
||
|
fn verify(&mut self, parts: &[DigestPart]) -> bool {
|
||
|
let alg = self.ctx.algorithm();
|
||
|
let ctx = std::mem::replace(&mut self.ctx, ring::digest::Context::new(alg));
|
||
|
|
||
|
verify(ctx, Self::NAME, parts)
|
||
|
}
|
||
|
}
|
||
|
}
|