mirror of
https://git.asonix.dog/asonix/http-signature-normalization.git
synced 2024-11-21 08:51:00 +00:00
Add ring-backed digest types
This commit is contained in:
parent
1f23b72140
commit
ea964decc8
3 changed files with 203 additions and 6 deletions
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "http-signature-normalization-actix"
|
||||
description = "An HTTP Signatures library that leaves the signing to you"
|
||||
version = "0.10.0"
|
||||
version = "0.10.1"
|
||||
authors = ["asonix <asonix@asonix.dog>"]
|
||||
license = "AGPL-3.0"
|
||||
readme = "README.md"
|
||||
|
@ -12,11 +12,12 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[features]
|
||||
default = ["server", "sha-2", "sha-3"]
|
||||
client = ["awc"]
|
||||
digest = ["base64"]
|
||||
server = ["actix-web"]
|
||||
sha-2 = ["digest", "sha2"]
|
||||
sha-3 = ["digest", "sha3"]
|
||||
client = ["dep:awc"]
|
||||
digest = ["dep:base64"]
|
||||
server = ["dep:actix-web"]
|
||||
sha-2 = ["digest", "dep:sha2"]
|
||||
sha-3 = ["digest", "dep:sha3"]
|
||||
ring = ["digest", "dep:ring"]
|
||||
|
||||
[[example]]
|
||||
name = "server"
|
||||
|
@ -34,6 +35,7 @@ awc = { version = "3.0.0", default-features = false, optional = true }
|
|||
base64 = { version = "0.13", optional = true }
|
||||
futures-util = { version = "0.3", default-features = false }
|
||||
http-signature-normalization = { version = "0.7.0", path = ".." }
|
||||
ring = { version = "0.16.20", optional = true }
|
||||
sha2 = { version = "0.10", optional = true }
|
||||
sha3 = { version = "0.10", optional = true }
|
||||
thiserror = "1.0"
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#[cfg(feature = "server")]
|
||||
pub mod middleware;
|
||||
#[cfg(feature = "ring")]
|
||||
pub mod ring;
|
||||
#[cfg(feature = "sha-2")]
|
||||
mod sha2;
|
||||
#[cfg(feature = "sha-3")]
|
||||
|
|
193
actix/src/digest/ring.rs
Normal file
193
actix/src/digest/ring.rs
Normal file
|
@ -0,0 +1,193 @@
|
|||
//! 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)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue