optimize: use ring hash and hmac implementations as an opt-in feature (#141)

Defaults to sha2 and hmac.
This commit is contained in:
Alfred Mathew 2025-03-22 14:30:37 +04:00 committed by GitHub
parent ddec540b22
commit b26ed09e42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 72 additions and 17 deletions

View File

@ -16,10 +16,11 @@ default-features = false
features = ["stream"] features = ["stream"]
[features] [features]
default = ["default-tls"] default = ["default-tls", "dep:hmac", "dep:sha2"]
default-tls = ["reqwest/default-tls"] default-tls = ["reqwest/default-tls"]
native-tls = ["reqwest/native-tls"] native-tls = ["reqwest/native-tls"]
rustls-tls = ["reqwest/rustls-tls"] rustls-tls = ["reqwest/rustls-tls"]
ring = ["dep:ring"]
[dependencies] [dependencies]
async-recursion = "1.1.1" async-recursion = "1.1.1"
@ -34,7 +35,7 @@ derivative = "2.2.0"
env_logger = "0.11.7" env_logger = "0.11.7"
futures-util = "0.3.31" futures-util = "0.3.31"
hex = "0.4.3" hex = "0.4.3"
hmac = "0.12.1" hmac = { version = "0.12.1", optional = true }
#home = "0.5.9" #home = "0.5.9"
http = "1.2.0" http = "1.2.0"
hyper = { version = "1.6.0", features = ["full"] } hyper = { version = "1.6.0", features = ["full"] }
@ -45,9 +46,10 @@ multimap = "0.10.0"
percent-encoding = "2.3.1" percent-encoding = "2.3.1"
rand = { version = "0.8.5", features = ["small_rng"] } rand = { version = "0.8.5", features = ["small_rng"] }
regex = "1.11.1" regex = "1.11.1"
ring = { version = "0.17.14", optional = true, default-features = false, features = ["alloc"] }
serde = { version = "1.0.219", features = ["derive"] } serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140" serde_json = "1.0.140"
sha2 = "0.10.8" sha2 = { version = "0.10.8", optional = true }
tokio = { version = "1.44.0", features = ["full"] } tokio = { version = "1.44.0", features = ["full"] }
tokio-stream = "0.1.17" tokio-stream = "0.1.17"
tokio-util = { version = "0.7.13", features = ["io"] } tokio-util = { version = "0.7.13", features = ["io"] }

View File

@ -20,16 +20,29 @@ use crate::s3::utils::{
to_signer_date, to_signer_date,
}; };
use hex::encode as hexencode; use hex::encode as hexencode;
#[cfg(not(feature = "ring"))]
use hmac::{Hmac, Mac}; use hmac::{Hmac, Mac};
use hyper::http::Method; use hyper::http::Method;
#[cfg(feature = "ring")]
use ring::hmac;
#[cfg(not(feature = "ring"))]
use sha2::Sha256; use sha2::Sha256;
/// Returns HMAC hash for given key and data /// Returns HMAC hash for given key and data
pub fn hmac_hash(key: &[u8], data: &[u8]) -> Vec<u8> { pub fn hmac_hash(key: &[u8], data: &[u8]) -> Vec<u8> {
let mut hasher = Hmac::<Sha256>::new_from_slice(key).expect("HMAC can take key of any size"); #[cfg(feature = "ring")]
{
let key = hmac::Key::new(hmac::HMAC_SHA256, key);
hmac::sign(&key, data).as_ref().to_vec()
}
#[cfg(not(feature = "ring"))]
{
let mut hasher =
Hmac::<Sha256>::new_from_slice(key).expect("HMAC can take key of any size");
hasher.update(data); hasher.update(data);
hasher.finalize().into_bytes().to_vec() hasher.finalize().into_bytes().to_vec()
} }
}
/// Returns hex encoded HMAC hash for given key and data /// Returns hex encoded HMAC hash for given key and data
pub fn hmac_hash_hex(key: &[u8], data: &[u8]) -> String { pub fn hmac_hash_hex(key: &[u8], data: &[u8]) -> String {

View File

@ -22,11 +22,15 @@ use base64::engine::general_purpose::STANDARD as BASE64;
use byteorder::{BigEndian, ReadBytesExt}; use byteorder::{BigEndian, ReadBytesExt};
use chrono::{DateTime, Datelike, NaiveDateTime, ParseError, Utc}; use chrono::{DateTime, Datelike, NaiveDateTime, ParseError, Utc};
use crc::{CRC_32_ISO_HDLC, Crc}; use crc::{CRC_32_ISO_HDLC, Crc};
use hex::ToHex;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use md5::compute as md5compute; use md5::compute as md5compute;
use multimap::MultiMap; use multimap::MultiMap;
use percent_encoding::{AsciiSet, NON_ALPHANUMERIC, percent_decode_str, utf8_percent_encode}; use percent_encoding::{AsciiSet, NON_ALPHANUMERIC, percent_decode_str, utf8_percent_encode};
use regex::Regex; use regex::Regex;
#[cfg(feature = "ring")]
use ring::digest::{Context, SHA256};
#[cfg(not(feature = "ring"))]
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
pub use urlencoding::decode as urldecode; pub use urlencoding::decode as urldecode;
pub use urlencoding::encode as urlencode; pub use urlencoding::encode as urlencode;
@ -68,17 +72,35 @@ pub fn uint32(mut data: &[u8]) -> Result<u32, std::io::Error> {
/// Gets hex encoded SHA256 hash of given data /// Gets hex encoded SHA256 hash of given data
pub fn sha256_hash(data: &[u8]) -> String { pub fn sha256_hash(data: &[u8]) -> String {
#[cfg(feature = "ring")]
{
ring::digest::digest(&SHA256, data).encode_hex()
}
#[cfg(not(feature = "ring"))]
{
let mut hasher = Sha256::new(); let mut hasher = Sha256::new();
hasher.update(data); hasher.update(data);
format!("{:x}", hasher.finalize()) hasher.finalize().encode_hex()
}
} }
pub fn sha256_hash_sb(sb: &SegmentedBytes) -> String { pub fn sha256_hash_sb(sb: &SegmentedBytes) -> String {
#[cfg(feature = "ring")]
{
let mut context = Context::new(&SHA256);
for data in sb.iter() {
context.update(data.as_ref());
}
context.finish().encode_hex()
}
#[cfg(not(feature = "ring"))]
{
let mut hasher = Sha256::new(); let mut hasher = Sha256::new();
for data in sb.iter() { for data in sb.iter() {
hasher.update(data); hasher.update(data);
} }
format!("{:x}", hasher.finalize()) hasher.finalize().encode_hex()
}
} }
/// Gets bas64 encoded MD5 hash of given data /// Gets bas64 encoded MD5 hash of given data

View File

@ -16,17 +16,35 @@
mod common; mod common;
use crate::common::{RandReader, TestContext, create_bucket_helper, rand_object_name}; use crate::common::{RandReader, TestContext, create_bucket_helper, rand_object_name};
use hex::ToHex;
use minio::s3::response::PutObjectContentResponse; use minio::s3::response::PutObjectContentResponse;
use minio::s3::types::S3Api; use minio::s3::types::S3Api;
#[cfg(feature = "ring")]
use ring::digest::{Context, SHA256};
#[cfg(not(feature = "ring"))]
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
#[cfg(feature = "ring")]
use std::io::Read;
use std::path::PathBuf; use std::path::PathBuf;
use std::{fs, io}; use std::{fs, io};
fn get_hash(filename: &String) -> String { fn get_hash(filename: &String) -> String {
#[cfg(feature = "ring")]
{
let mut context = Context::new(&SHA256);
let mut file = fs::File::open(filename).unwrap();
let mut buf = Vec::new();
file.read_to_end(&mut buf).unwrap();
context.update(&buf);
context.finish().encode_hex()
}
#[cfg(not(feature = "ring"))]
{
let mut hasher = Sha256::new(); let mut hasher = Sha256::new();
let mut file = fs::File::open(filename).unwrap(); let mut file = fs::File::open(filename).unwrap();
io::copy(&mut file, &mut hasher).unwrap(); io::copy(&mut file, &mut hasher).unwrap();
format!("{:x}", hasher.finalize()) hasher.finalize().encode_hex()
}
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 10)] #[tokio::test(flavor = "multi_thread", worker_threads = 10)]