Skip to content

Commit

Permalink
feature gate sha
Browse files Browse the repository at this point in the history
  • Loading branch information
abdulmth committed Dec 5, 2023
1 parent 1410c39 commit 92f966f
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 12 deletions.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ rand = { version = "0.8.5", default-features = false, features = ["std", "std_rn
thiserror = { version = "1.0", default-features = false }
strum = { version = "0.25", default-features = false, features = ["std", "derive"] }
itertools = { version = "0.12", default-features = false, features = ["use_std"] }
iota-crypto = { version = "0.23", default-features = false, features = ["std", "sha"] }
iota-crypto = { version = "0.23", default-features = false, features = ["sha"], optional = true }
serde = { version = "1.0", default-features = false, features = ["derive"] }

[dev-dependencies]
Expand All @@ -27,3 +27,6 @@ josekit = "0.8.4"
[[example]]
name = "sd_jwt"

[features]
default = ["sha"]
sha = ["iota-crypto"]
2 changes: 1 addition & 1 deletion examples/sd_jwt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ fn main() {
let (payload, _header) = jwt::decode_with_verifier(&sd_jwt.jwt, &verifier).unwrap();

// Decode the payload by providing the disclosures that were parsed from the SD-JWT.
let decoder = SdObjectDecoder::new();
let decoder = SdObjectDecoder::new_with_sha256();
let decoded = decoder.decode(payload.claims_set(), &sd_jwt.disclosures).unwrap();
println!("decoded object: {}", serde_json::to_string_pretty(&decoded).unwrap());
}
4 changes: 2 additions & 2 deletions src/api_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ fn test_complex_structure() {
let (payload, _header) = jwt::decode_with_verifier(&sd_jwt.jwt, &verifier).unwrap();

// Decode the payload by providing the disclosures that were parsed from the SD-JWT.
let decoder = SdObjectDecoder::new();
let decoder = SdObjectDecoder::new_with_sha256();
let decoded = decoder.decode(payload.claims_set(), &sd_jwt.disclosures).unwrap();
println!("decoded object: {}", serde_json::to_string_pretty(&decoded).unwrap());
assert_eq!(Value::Object(decoded), object);
Expand Down Expand Up @@ -156,7 +156,7 @@ fn concealed_object_in_array() {
.into_iter()
.map(|disclosure| disclosure.to_string())
.collect();
let decoder = SdObjectDecoder::new();
let decoder = SdObjectDecoder::new_with_sha256();
let decoded = decoder.decode(encoder.object(), &disclosures).unwrap();
assert_eq!(Value::Object(decoded), expected);
}
20 changes: 15 additions & 5 deletions src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
use crate::ARRAY_DIGEST_KEY;
use crate::DIGESTS_KEY;
use crate::SD_ALG;
use crate::SHA_ALG_NAME;

use super::Disclosure;
use super::Hasher;
#[cfg(feature = "sha")]
use super::Sha256Hasher;
use crate::Error;
use serde_json::Map;
Expand All @@ -20,13 +22,20 @@ pub struct SdObjectDecoder {

impl SdObjectDecoder {
/// Creates a new [`SdObjectDecoder`] with `sha-256` hasher.
pub fn new() -> Self {
#[cfg(feature = "sha")]
pub fn new_with_sha256() -> Self {
let hashers: BTreeMap<String, Box<dyn Hasher>> = BTreeMap::new();
let mut hasher = Self { hashers };
hasher.add_hasher(Box::new(Sha256Hasher::new()));
hasher
}

/// Creates a new [`SdObjectDecoder`] without any hashers.
pub fn new() -> Self {
let hashers: BTreeMap<String, Box<dyn Hasher>> = BTreeMap::new();
Self { hashers }
}

/// Adds a hasher.
///
/// If a hasher for the same algorithm [`Hasher::alg_name`] already exists, it will be replaced and
Expand Down Expand Up @@ -87,7 +96,7 @@ impl SdObjectDecoder {
"the value of `_sd_alg` is not a string".to_string(),
))?
} else {
Sha256Hasher::ALG_NAME
SHA_ALG_NAME
};
self
.hashers
Expand Down Expand Up @@ -227,9 +236,10 @@ impl SdObjectDecoder {
}
}

#[cfg(feature = "sha")]
impl Default for SdObjectDecoder {
fn default() -> Self {
Self::new()
Self::new_with_sha256()
}
}

Expand All @@ -251,7 +261,7 @@ mod test {
encoder
.object_mut()
.insert("id".to_string(), Value::String("id-value".to_string()));
let decoder = SdObjectDecoder::new();
let decoder = SdObjectDecoder::new_with_sha256();
let decoded = decoder.decode(encoder.object(), &vec![dis.to_string()]).unwrap_err();
assert!(matches!(decoded, Error::ClaimCollisionError(_)));
}
Expand All @@ -267,7 +277,7 @@ mod test {
let mut encoder = SdObjectEncoder::try_from(object).unwrap();
encoder.add_sd_alg_property();
assert_eq!(encoder.object().get("_sd_alg").unwrap(), "sha-256");
let decoder = SdObjectDecoder::new();
let decoder = SdObjectDecoder::new_with_sha256();
let decoded = decoder.decode(encoder.object(), &vec![]).unwrap();
assert!(decoded.get("_sd_alg").is_none());
}
Expand Down
17 changes: 17 additions & 0 deletions src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use super::Disclosure;
use super::Hasher;
#[cfg(feature = "sha")]
use super::Sha256Hasher;
use crate::Error;
use crate::Result;
Expand All @@ -18,6 +19,20 @@ pub(crate) const SD_ALG: &str = "_sd_alg";

/// Transforms a JSON object into an SD-JWT object by substituting selected values
/// with their corresponding disclosure digests.
#[cfg(not(feature = "sha"))]
pub struct SdObjectEncoder<H: Hasher> {
/// The object in JSON format.
object: Map<String, Value>,
/// Size of random data used to generate the salts for disclosures in bytes.
/// Constant length for readability considerations.
salt_size: usize,
/// The hash function used to create digests.
hasher: H,
}

/// Transforms a JSON object into an SD-JWT object by substituting selected values
/// with their corresponding disclosure digests.
#[cfg(feature = "sha")]
pub struct SdObjectEncoder<H: Hasher = Sha256Hasher> {
/// The object in JSON format.
object: Map<String, Value>,
Expand All @@ -28,6 +43,7 @@ pub struct SdObjectEncoder<H: Hasher = Sha256Hasher> {
hasher: H,
}

#[cfg(feature = "sha")]
impl SdObjectEncoder {
/// Creates a new [`SdObjectEncoder`] with `sha-256` hash function.
///
Expand All @@ -51,6 +67,7 @@ impl SdObjectEncoder {
}
}

#[cfg(feature = "sha")]
impl TryFrom<Value> for SdObjectEncoder {
type Error = crate::Error;

Expand Down
12 changes: 9 additions & 3 deletions src/hasher.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
// Copyright 2020-2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

#[cfg(feature = "sha")]
use crypto::hashes::sha::SHA256;

#[cfg(feature = "sha")]
use crypto::hashes::sha::SHA256_LEN;

pub const SHA_ALG_NAME: &'static str = "sha-256";

Check failure on line 10 in src/hasher.rs

View workflow job for this annotation

GitHub Actions / clippy

constants have by default a `'static` lifetime

error: constants have by default a `'static` lifetime --> src/hasher.rs:10:26 | 10 | pub const SHA_ALG_NAME: &'static str = "sha-256"; | -^^^^^^^---- help: consider removing `'static`: `&str` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes = note: `-D clippy::redundant-static-lifetimes` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::redundant_static_lifetimes)]`

/// Used to implement hash functions to be used for encoding/decoding.
///
/// ## Note
Expand Down Expand Up @@ -32,16 +37,17 @@ pub trait Hasher: Sync + Send {

/// An implementation of [`Hasher`] that uses the `sha-256` hash function.
#[derive(Default)]
#[cfg(feature = "sha")]
pub struct Sha256Hasher;

#[cfg(feature = "sha")]
impl Sha256Hasher {
pub const ALG_NAME: &'static str = "sha-256";
/// Creates a new [`ShaHasher`]
pub fn new() -> Self {
Sha256Hasher {}
}
}

#[cfg(feature = "sha")]
impl Hasher for Sha256Hasher {
fn digest(&self, input: &[u8]) -> Vec<u8> {
let mut digest: [u8; SHA256_LEN] = Default::default();
Expand All @@ -50,7 +56,7 @@ impl Hasher for Sha256Hasher {
}

fn alg_name(&self) -> &'static str {
Sha256Hasher::ALG_NAME
SHA_ALG_NAME
}
}

Expand Down

0 comments on commit 92f966f

Please sign in to comment.