This commit is contained in:
Rowan 2024-10-06 03:41:27 -05:00
parent 8e97870352
commit 3cbdf91cf1
3 changed files with 35 additions and 0 deletions

11
Cargo.lock generated
View file

@ -68,6 +68,16 @@ version = "0.2.159"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
[[package]]
name = "md-5"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
dependencies = [
"cfg-if",
"digest",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.86" version = "1.0.86"
@ -122,6 +132,7 @@ name = "subresource_integrity"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"base64", "base64",
"md-5",
"serde", "serde",
"sha2", "sha2",
] ]

View file

@ -6,8 +6,10 @@ edition = "2021"
[features] [features]
default = [] default = []
serde = ["dep:serde"] serde = ["dep:serde"]
md5 = ["dep:md-5"]
[dependencies] [dependencies]
base64 = "0.22.1" base64 = "0.22.1"
md-5 = { version = "0.10.6", optional = true }
serde = { version = "1.0.210", features = ["derive"], optional = true } serde = { version = "1.0.210", features = ["derive"], optional = true }
sha2 = "0.10.8" sha2 = "0.10.8"

View file

@ -16,6 +16,8 @@ pub enum Error {
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Algorithm { pub enum Algorithm {
#[cfg(feature = "md5")]
MD5,
SHA256, SHA256,
SHA384, SHA384,
SHA512, SHA512,
@ -24,6 +26,8 @@ pub enum Algorithm {
impl Algorithm { impl Algorithm {
pub fn digest(&self, data: impl AsRef<[u8]>) -> Vec<u8> { pub fn digest(&self, data: impl AsRef<[u8]>) -> Vec<u8> {
match self { match self {
#[cfg(feature = "md5")]
Self::MD5 => md5::Md5::digest(data).to_vec(),
Self::SHA256 => sha2::Sha256::digest(data).to_vec(), Self::SHA256 => sha2::Sha256::digest(data).to_vec(),
Self::SHA384 => sha2::Sha384::digest(data).to_vec(), Self::SHA384 => sha2::Sha384::digest(data).to_vec(),
Self::SHA512 => sha2::Sha512::digest(data).to_vec(), Self::SHA512 => sha2::Sha512::digest(data).to_vec(),
@ -34,6 +38,8 @@ impl Algorithm {
impl fmt::Display for Algorithm { impl fmt::Display for Algorithm {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let value = match self { let value = match self {
#[cfg(feature = "md5")]
Self::MD5 => "md5",
Self::SHA256 => "sha256", Self::SHA256 => "sha256",
Self::SHA384 => "sha384", Self::SHA384 => "sha384",
Self::SHA512 => "sha512", Self::SHA512 => "sha512",
@ -48,6 +54,8 @@ impl TryFrom<&str> for Algorithm {
fn try_from(value: &str) -> Result<Self, Self::Error> { fn try_from(value: &str) -> Result<Self, Self::Error> {
match value { match value {
#[cfg(feature = "md5")]
"md5" => Ok(Self::MD5),
"sha256" => Ok(Self::SHA256), "sha256" => Ok(Self::SHA256),
"sha384" => Ok(Self::SHA384), "sha384" => Ok(Self::SHA384),
"sha512" => Ok(Self::SHA512), "sha512" => Ok(Self::SHA512),
@ -126,6 +134,20 @@ mod test {
use crate::Integrity; use crate::Integrity;
use base64::Engine; use base64::Engine;
use sha2::Digest; use sha2::Digest;
#[cfg(feature = "md5")]
#[test]
fn try_from_md5() {
let value = "alert('Hello, world.');";
let digest = md5::Md5::digest(value);
let hash = base64::prelude::BASE64_STANDARD.encode(digest);
let integrity_value = format!("md5-{hash}");
let integrity = Integrity::try_from(integrity_value.as_str()).unwrap();
assert_eq!(integrity.algorithm, Algorithm::MD5);
assert_eq!(integrity.hash, digest.as_slice());
assert_eq!(integrity.to_string(), integrity_value)
}
#[test] #[test]
fn try_from_sha256() { fn try_from_sha256() {