diff --git a/Cargo.toml b/Cargo.toml index 9dc0983411..e958044495 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,8 +23,8 @@ serde = { version = "1.0", default-features = false, features = ["alloc", "deriv thiserror = { version = "1.0", default-features = false } strum = { version = "0.25", default-features = false, features = ["std", "derive"] } serde_json = { version = "1.0", default-features = false } -json-proof-token = { version = "0.3.3" } -zkryptium = { version = "0.1.9", default-features = false, features = ["bbsplus"] } +json-proof-token = { version = "0.3.4" } +zkryptium = { version = "0.2.0", default-features = false, features = ["bbsplus"] } [workspace.package] authors = ["IOTA Stiftung"] diff --git a/identity_jose/src/jwk/curve/bls.rs b/identity_jose/src/jwk/curve/bls.rs new file mode 100644 index 0000000000..a93e48b3e3 --- /dev/null +++ b/identity_jose/src/jwk/curve/bls.rs @@ -0,0 +1,36 @@ +use core::fmt::Display; +use core::fmt::Formatter; +use core::fmt::Result; + +/// Supported BLS Curves. +/// +/// [More Info](https://datatracker.ietf.org/doc/html/draft-ietf-cose-bls-key-representations-05#name-curve-parameter-registratio) +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub enum BlsCurve { + /// A cryptographic key on the Barreto-Lynn-Scott (BLS) curve featuring an embedding degree 12 with 381-bit p in the subgroup of G1. + BLS12381G1, + /// A cryptographic key on the Barreto-Lynn-Scott (BLS) curve featuring an embedding degree 12 with 381-bit p in the subgroup of G2. + BLS12381G2, + /// A cryptographic key on the Barreto-Lynn-Scott (BLS) curve featuring an embedding degree 48 with 581-bit p in the subgroup of G1. + BLS48581G1, + /// A cryptographic key on the Barreto-Lynn-Scott (BLS) curve featuring an embedding degree 48 with 581-bit p in the subgroup of G2. + BLS48581G2, +} + +impl BlsCurve { + /// Returns the name of the curve as a string slice. + pub const fn name(self) -> &'static str { + match self { + Self::BLS12381G1 => "BLS12381G1", + Self::BLS12381G2 => "BLS12381G2", + Self::BLS48581G1 => "BLS48581G1", + Self::BLS48581G2 => "BLS48581G2", + } + } +} + +impl Display for BlsCurve { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.write_str(self.name()) + } +} \ No newline at end of file diff --git a/identity_jose/src/jwk/curve/mod.rs b/identity_jose/src/jwk/curve/mod.rs index 38a1e3bba7..d333ad879c 100644 --- a/identity_jose/src/jwk/curve/mod.rs +++ b/identity_jose/src/jwk/curve/mod.rs @@ -4,7 +4,9 @@ mod ec; mod ecx; mod ed; +mod bls; pub use self::ec::*; pub use self::ecx::*; pub use self::ed::*; +pub use self::bls::*; \ No newline at end of file diff --git a/identity_jose/src/jwk/jwk_ext.rs b/identity_jose/src/jwk/jwk_ext.rs index 7c6621a5d0..a5b1d47256 100644 --- a/identity_jose/src/jwk/jwk_ext.rs +++ b/identity_jose/src/jwk/jwk_ext.rs @@ -1,14 +1,14 @@ use super::Jwk; use super::JwkOperation; use super::JwkParams; -use super::JwkParamsOkp; +use super::JwkParamsEc; use super::JwkType; use super::JwkUse; use identity_core::common::Url; use jsonprooftoken::jpa::algs::ProofAlgorithm; use jsonprooftoken::jwk::alg_parameters::Algorithm; use jsonprooftoken::jwk::alg_parameters::JwkAlgorithmParameters; -use jsonprooftoken::jwk::alg_parameters::JwkOctetKeyPairParameters; +use jsonprooftoken::jwk::alg_parameters::JwkEllipticCurveKeyParameters; use jsonprooftoken::jwk::curves::EllipticCurveTypes; use jsonprooftoken::jwk::key::Jwk as JwkExt; use jsonprooftoken::jwk::key::KeyOps; @@ -50,23 +50,6 @@ impl From for KeyOps { } } -// impl Into for JwkOperation { -// fn into(self) -> KeyOps { -// match self { -// Self::Sign => KeyOps::Sign, -// Self::Verify => KeyOps::Verify, -// Self::Encrypt => KeyOps::Encrypt, -// Self::Decrypt => KeyOps::Decrypt, -// Self::WrapKey => KeyOps::WrapKey, -// Self::UnwrapKey => KeyOps::UnwrapKey, -// Self::DeriveKey => KeyOps::DeriveKey, -// Self::DeriveBits => KeyOps::DeriveBits, -// Self::ProofGeneration => KeyOps::ProofGeneration, -// Self::ProofVerification => KeyOps::ProofVerification, -// } -// } -// } - impl From for JwkUse { fn from(value: PKUse) -> Self { match value { @@ -87,24 +70,26 @@ impl From for PKUse { } } -impl From for JwkParamsOkp { - fn from(value: JwkOctetKeyPairParameters) -> Self { +impl From for JwkParamsEc { + fn from(value: JwkEllipticCurveKeyParameters) -> Self { Self { crv: value.crv.to_string(), x: value.x, + y: value.y, d: value.d, } } } -impl TryInto for &JwkParamsOkp { +impl TryInto for &JwkParamsEc { type Error = crate::error::Error; - fn try_into(self) -> Result { - Ok(JwkOctetKeyPairParameters { - kty: KeyType::OctetKeyPair, - crv: EllipticCurveTypes::from_str(&self.crv).map_err(|_| Self::Error::KeyError("Invalid crv!"))?, + fn try_into(self) -> Result { + Ok(JwkEllipticCurveKeyParameters { + kty: KeyType::EllipticCurve, + crv: EllipticCurveTypes::from_str(&self.crv).map_err(|_| Self::Error::KeyError("crv not supported!"))?, x: self.x.clone(), + y: self.y.clone(), d: self.d.clone(), }) } @@ -120,7 +105,8 @@ impl TryFrom for Jwk { }; let (kty, params) = match value.key_params { - JwkAlgorithmParameters::OctetKeyPair(p) => (JwkType::Okp, JwkParams::Okp(JwkParamsOkp::from(p))), + JwkAlgorithmParameters::EllipticCurve(p) => (JwkType::Ec, JwkParams::Ec(JwkParamsEc::from(p))), + _ => return Err(Self::Error::KeyError("invalid kty")) }; Ok(Self { @@ -145,7 +131,7 @@ impl TryInto for &Jwk { fn try_into(self) -> Result { let params = match &self.params { - JwkParams::Okp(p) => JwkAlgorithmParameters::OctetKeyPair(p.try_into()?), + JwkParams::Ec(p) => JwkAlgorithmParameters::EllipticCurve(p.try_into()?), _ => return Err(Self::Error::InvalidParam("Parameters not supported!")), }; @@ -170,4 +156,4 @@ impl TryInto for &Jwk { key_params: params, }) } -} +} \ No newline at end of file diff --git a/identity_storage/src/key_storage/jwk_storage.rs b/identity_storage/src/key_storage/jwk_storage.rs index e0e488be03..d74f51b077 100644 --- a/identity_storage/src/key_storage/jwk_storage.rs +++ b/identity_storage/src/key_storage/jwk_storage.rs @@ -11,6 +11,7 @@ use identity_verification::jose::jws::JwsAlgorithm; use jsonprooftoken::jpa::algs::ProofAlgorithm; use jsonprooftoken::jpt::claims::JptClaims; use jsonprooftoken::jwp::header::IssuerProtectedHeader; +use zkryptium::bbsplus::signature::BBSplusSignature; use super::jwk_gen_output::JwkGenOutput; @@ -88,7 +89,7 @@ pub trait JwkStorageExt: JwkStorage { &self, key_id: &KeyId, public_key: &Jwk, - proof: &[u8; 112], + proof: &[u8; BBSplusSignature::BYTES], ctx: ProofUpdateCtx, - ) -> KeyStorageResult<[u8; 112]>; + ) -> KeyStorageResult<[u8; BBSplusSignature::BYTES]>; } diff --git a/identity_storage/src/key_storage/memstore.rs b/identity_storage/src/key_storage/memstore.rs index 4758840da1..b0a8061666 100644 --- a/identity_storage/src/key_storage/memstore.rs +++ b/identity_storage/src/key_storage/memstore.rs @@ -12,11 +12,11 @@ use identity_verification::jose::jwk::EdCurve; use identity_verification::jose::jwk::Jwk; use identity_verification::jose::jwk::JwkType; use identity_verification::jose::jws::JwsAlgorithm; +use identity_verification::jwk::BlsCurve; use identity_verification::jwu; use jsonprooftoken::encoding::SerializationType; use jsonprooftoken::jpa::algs::ProofAlgorithm; use jsonprooftoken::jpt::claims::JptClaims; -use jsonprooftoken::jwk::curves::EllipticCurveTypes; use jsonprooftoken::jwk::key::Jwk as JwkExt; use jsonprooftoken::jwk::types::KeyPairSubtype; use jsonprooftoken::jwp::header::IssuerProtectedHeader; @@ -25,12 +25,11 @@ use rand::distributions::DistString; use shared::Shared; use tokio::sync::RwLockReadGuard; use tokio::sync::RwLockWriteGuard; -use zkryptium::bbsplus::keys::BBSplusPublicKey; use zkryptium::bbsplus::keys::BBSplusSecretKey; -use zkryptium::schemes::algorithms::BBS_BLS12381_SHA256; -use zkryptium::schemes::algorithms::BBS_BLS12381_SHAKE256; +use zkryptium::bbsplus::signature::BBSplusSignature; +use zkryptium::schemes::algorithms::BbsBls12381Sha256; +use zkryptium::schemes::algorithms::BbsBls12381Shake256; use zkryptium::schemes::generics::Signature; -use zkryptium::utils::message::BBSplusMessage; use super::ed25519::encode_jwk; use super::ed25519::expand_secret_jwk; @@ -339,16 +338,16 @@ impl JwkStorageExt for JwkMemStore { match alg { ProofAlgorithm::BLS12381_SHA256 | ProofAlgorithm::BLS12381_SHAKE256 => { - let okp_params = public_key.try_okp_params().map_err(|err| { + let ec_params = public_key.try_ec_params().map_err(|err| { KeyStorageError::new(KeyStorageErrorKind::Unspecified) - .with_custom_message(format!("expected a Jwk with Okp params in order to sign with {alg}")) + .with_custom_message(format!("expected a Jwk with EC params in order to sign with {alg}")) .with_source(err) })?; - if okp_params.crv != EllipticCurveTypes::Bls12381G2.to_string() { + if ec_params.crv != BlsCurve::BLS12381G2.to_string() { return Err( KeyStorageError::new(KeyStorageErrorKind::Unspecified).with_custom_message(format!( - "expected Jwk with Okp {} crv in order to generate the proof with {alg}", - EllipticCurveTypes::Bls12381G2 + "expected Jwk with EC {} crv in order to generate the proof with {alg}", + BlsCurve::BLS12381G2 )), ); } @@ -384,9 +383,9 @@ impl JwkStorageExt for JwkMemStore { &self, key_id: &KeyId, public_key: &Jwk, - proof: &[u8; 112], + proof: &[u8; BBSplusSignature::BYTES], ctx: ProofUpdateCtx, - ) -> KeyStorageResult<[u8; 112]> { + ) -> KeyStorageResult<[u8; BBSplusSignature::BYTES]> { let jwk_store: RwLockReadGuard<'_, JwkKeyStore> = self.jwk_store.read().await; let ProofUpdateCtx { @@ -409,16 +408,16 @@ impl JwkStorageExt for JwkMemStore { match alg { ProofAlgorithm::BLS12381_SHA256 | ProofAlgorithm::BLS12381_SHAKE256 => { - let okp_params = public_key.try_okp_params().map_err(|err| { + let ec_params = public_key.try_ec_params().map_err(|err| { KeyStorageError::new(KeyStorageErrorKind::Unspecified) - .with_custom_message(format!("expected a Jwk with Okp params in order to sign with {alg}")) + .with_custom_message(format!("expected a Jwk with EC params in order to sign with {alg}")) .with_source(err) })?; - if okp_params.crv != EllipticCurveTypes::Bls12381G2.to_string() { + if ec_params.crv != BlsCurve::BLS12381G2.to_string() { return Err( KeyStorageError::new(KeyStorageErrorKind::Unspecified).with_custom_message(format!( - "expected Jwk with Okp {} crv in order to generate the proof with {alg}", - EllipticCurveTypes::Bls12381G2 + "expected Jwk with EC {} crv in order to generate the proof with {alg}", + BlsCurve::BLS12381G2 )), ); } @@ -436,13 +435,7 @@ impl JwkStorageExt for JwkMemStore { .get(key_id) .ok_or_else(|| KeyStorageError::new(KeyStorageErrorKind::KeyNotFound))?; - let params = jwk.try_okp_params().map_err(|_| KeyStorageErrorKind::Unspecified)?; - - let pk = BBSplusPublicKey::from_bytes(&jwu::decode_b64(¶ms.x).map_err(|err| { - KeyStorageError::new(KeyStorageErrorKind::Unspecified) - .with_custom_message("unable to decode `d` param") - .with_source(err) - })?); + let params = jwk.try_ec_params().map_err(|_| KeyStorageErrorKind::Unspecified)?; let sk = BBSplusSecretKey::from_bytes( ¶ms @@ -458,94 +451,65 @@ impl JwkStorageExt for JwkMemStore { .with_custom_message("unable to decode `d` param") .with_source(err) })?, - ); + ).map_err(|_| { + KeyStorageError::new(KeyStorageErrorKind::Unspecified) + .with_custom_message("key not valid") + })?; let new_proof = match alg { ProofAlgorithm::BLS12381_SHA256 => { - let vec_old_start_validity_timeframe = serde_json::to_vec(&old_start_validity_timeframe) - .map_err(|_| KeyStorageError::new(KeyStorageErrorKind::Unspecified))?; - let old_start_validity_timeframe = - BBSplusMessage::map_message_to_scalar_as_hash::(&vec_old_start_validity_timeframe, None); - - let vec_new_start_validity_timeframe = serde_json::to_vec(&new_start_validity_timeframe) - .map_err(|_| KeyStorageError::new(KeyStorageErrorKind::Unspecified))?; - let new_start_validity_timeframe = - BBSplusMessage::map_message_to_scalar_as_hash::(&vec_new_start_validity_timeframe, None); - - let vec_old_end_validity_timeframe = serde_json::to_vec(&old_end_validity_timeframe) - .map_err(|_| KeyStorageError::new(KeyStorageErrorKind::Unspecified))?; - let old_end_validity_timeframe = - BBSplusMessage::map_message_to_scalar_as_hash::(&vec_old_end_validity_timeframe, None); - - let vec_new_end_validity_timeframe = serde_json::to_vec(&new_end_validity_timeframe) - .map_err(|_| KeyStorageError::new(KeyStorageErrorKind::Unspecified))?; - let new_end_validity_timeframe = - BBSplusMessage::map_message_to_scalar_as_hash::(&vec_new_end_validity_timeframe, None); - - let proof = Signature::::from_bytes(proof).update_signature( + let proof = Signature::::from_bytes(proof) + .map_err(|_| KeyStorageError::new(KeyStorageErrorKind::Unspecified).with_custom_message("Signature not valid"))? + .update_signature( &sk, - &pk, - number_of_signed_messages, &old_start_validity_timeframe, &new_start_validity_timeframe, index_start_validity_timeframe, - ); + number_of_signed_messages, + ).map_err(|_| { + KeyStorageError::new(KeyStorageErrorKind::Unspecified) + .with_custom_message("Signature update failed") + })?; proof - .update_signature( - &sk, - &pk, - number_of_signed_messages, - &old_end_validity_timeframe, - &new_end_validity_timeframe, - index_end_validity_timeframe, - ) - .to_bytes() + .update_signature( + &sk, + &old_end_validity_timeframe, + &new_end_validity_timeframe, + index_end_validity_timeframe, + number_of_signed_messages, + ).map_err(|_| { + KeyStorageError::new(KeyStorageErrorKind::Unspecified) + .with_custom_message("Signature update failed") + })? + .to_bytes() } ProofAlgorithm::BLS12381_SHAKE256 => { - let vec_old_start_validity_timeframe = serde_json::to_vec(&old_start_validity_timeframe) - .map_err(|_| KeyStorageError::new(KeyStorageErrorKind::Unspecified))?; - let old_start_validity_timeframe = BBSplusMessage::map_message_to_scalar_as_hash::( - &vec_old_start_validity_timeframe, - None, - ); - - let vec_new_start_validity_timeframe = serde_json::to_vec(&new_start_validity_timeframe) - .map_err(|_| KeyStorageError::new(KeyStorageErrorKind::Unspecified))?; - let new_start_validity_timeframe = BBSplusMessage::map_message_to_scalar_as_hash::( - &vec_new_start_validity_timeframe, - None, - ); - - let vec_old_end_validity_timeframe = serde_json::to_vec(&old_end_validity_timeframe) - .map_err(|_| KeyStorageError::new(KeyStorageErrorKind::Unspecified))?; - let old_end_validity_timeframe = - BBSplusMessage::map_message_to_scalar_as_hash::(&vec_old_end_validity_timeframe, None); - - let vec_new_end_validity_timeframe = serde_json::to_vec(&new_end_validity_timeframe) - .map_err(|_| KeyStorageError::new(KeyStorageErrorKind::Unspecified))?; - let new_end_validity_timeframe = - BBSplusMessage::map_message_to_scalar_as_hash::(&vec_new_end_validity_timeframe, None); - - let proof = Signature::::from_bytes(proof).update_signature( + let proof = Signature::::from_bytes(proof) + .map_err(|_| KeyStorageError::new(KeyStorageErrorKind::Unspecified).with_custom_message("Signature not valid"))? + .update_signature( &sk, - &pk, - number_of_signed_messages, &old_start_validity_timeframe, &new_start_validity_timeframe, index_start_validity_timeframe, - ); + number_of_signed_messages, + ).map_err(|_| { + KeyStorageError::new(KeyStorageErrorKind::Unspecified) + .with_custom_message("Signature update failed") + })?; proof - .update_signature( - &sk, - &pk, - number_of_signed_messages, - &old_end_validity_timeframe, - &new_end_validity_timeframe, - index_end_validity_timeframe, - ) - .to_bytes() + .update_signature( + &sk, + &old_end_validity_timeframe, + &new_end_validity_timeframe, + index_end_validity_timeframe, + number_of_signed_messages, + ).map_err(|_| { + KeyStorageError::new(KeyStorageErrorKind::Unspecified) + .with_custom_message("Signature update failed") + })? + .to_bytes() } other => { return Err( diff --git a/identity_storage/src/storage/timeframe_revocation_ext.rs b/identity_storage/src/storage/timeframe_revocation_ext.rs index 0d3ed740b7..d03b7d5d8d 100644 --- a/identity_storage/src/storage/timeframe_revocation_ext.rs +++ b/identity_storage/src/storage/timeframe_revocation_ext.rs @@ -16,17 +16,18 @@ use jsonprooftoken::encoding::SerializationType; use jsonprooftoken::jpt::payloads::Payloads; use jsonprooftoken::jwp::issued::JwpIssued; use serde_json::Value; +use zkryptium::bbsplus::signature::BBSplusSignature; /// Contains information needed to update the signature in the RevocationTimeframe2024 revocation mechanism. pub struct ProofUpdateCtx { /// Old `startValidityTimeframe` value - pub old_start_validity_timeframe: String, + pub old_start_validity_timeframe: Vec, /// New `startValidityTimeframe` value to be signed - pub new_start_validity_timeframe: String, + pub new_start_validity_timeframe: Vec, /// Old `endValidityTimeframe` value - pub old_end_validity_timeframe: String, + pub old_end_validity_timeframe: Vec, /// New `endValidityTimeframe` value to be signed - pub new_end_validity_timeframe: String, + pub new_end_validity_timeframe: Vec, /// Index of `startValidityTimeframe` claim inside the array of Claims pub index_start_validity_timeframe: usize, /// Index of `endValidityTimeframe` claim inside the array of Claims @@ -132,15 +133,15 @@ impl TimeframeRevocationExtension for CoreDocument { .map_err(|_| Error::ProofUpdateError("'endValidityTimeframe' value NOT found".to_owned()))? .map_err(|_| Error::ProofUpdateError("'endValidityTimeframe' value NOT a JSON String".to_owned()))?; - let proof: [u8; 112] = proof + let proof: [u8; BBSplusSignature::BYTES] = proof .try_into() .map_err(|_| Error::ProofUpdateError("Invalid bytes length of JWP proof".to_owned()))?; let proof_update_ctx = ProofUpdateCtx { - old_start_validity_timeframe, - new_start_validity_timeframe, - old_end_validity_timeframe, - new_end_validity_timeframe, + old_start_validity_timeframe: serde_json::to_vec(&old_start_validity_timeframe).unwrap(), + new_start_validity_timeframe: serde_json::to_vec(&new_start_validity_timeframe).unwrap(), + old_end_validity_timeframe: serde_json::to_vec(&old_end_validity_timeframe).unwrap(), + new_end_validity_timeframe: serde_json::to_vec(&new_end_validity_timeframe).unwrap(), index_start_validity_timeframe, index_end_validity_timeframe, number_of_signed_messages: payloads.0.len(),