diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 101d4e76..1381d91d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,7 @@ name: "Anoncreds" env: - RUST_VERSION: "1.81.0" + RUST_VERSION: "1.85.0" CROSS_VERSION: "0.2.4" on: @@ -350,6 +350,9 @@ jobs: matrix: architecture: [aarch64-apple-ios, aarch64-apple-ios-sim, x86_64-apple-ios] + env: + IPHONEOS_DEPLOYMENT_TARGET: 10.0 + IPHONESIMULATOR_DEPLOYMENT_TARGET: 10.0 steps: - name: Checkout diff --git a/Cargo.toml b/Cargo.toml index e07f24f0..50ce39cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,13 +5,13 @@ authors = [ "Hyperledger AnonCreds Contributors ", ] description = "Verifiable credential issuance and presentation for Hyperledger AnonCreds (https://www.hyperledger.org/projects), which provides a foundation for self-sovereign identity." -edition = "2021" +edition = "2024" license = "Apache-2.0" readme = "../README.md" repository = "https://github.com/hyperledger/anoncreds-rs/" categories = ["authentication", "cryptography"] keywords = ["hyperledger", "ssi", "verifiable", "credentials"] -rust-version = "1.58" +rust-version = "1.85" [lib] name = "anoncreds" @@ -28,25 +28,25 @@ zeroize = ["dep:zeroize"] [dependencies] anoncreds-clsignatures = "0.3.2" -base64 = { version = "0.21.5", optional = true } +base64 = { version = "0.22", optional = true } bitvec = { version = "1.0.1", features = ["serde"] } bs58 = "0.5.0" chrono = { version = "0.4.31", optional = true, features = ["serde"] } -env_logger = { version = "0.9.3", optional = true } +env_logger = { version = "0.11", optional = true } ffi-support = { version = "0.4.0", optional = true } log = "0.4.17" -once_cell = "1.17.1" -rand = "0.8.5" +once_cell = "1" +rand = "0.9" regex = "1.7.1" rmp-serde = { version = "1.1.2", optional = true } serde = { version = "1.0.155", features = ["derive"] } serde_json = { version = "1.0.94", features = ["raw_value"] } sha2 = "0.10.6" -thiserror = "1.0.39" +thiserror = "2" zeroize = { version = "1.5.7", optional = true, features = ["zeroize_derive"] } [dev-dependencies] -rstest = "0.18.2" +rstest = "0.26" [profile.release] codegen-units = 1 diff --git a/Cross.toml b/Cross.toml new file mode 100644 index 00000000..f7483707 --- /dev/null +++ b/Cross.toml @@ -0,0 +1,8 @@ +[build.env] +passthrough = ["CFLAGS"] + +[target.aarch64-unknown-linux-gnu] +image = "ghcr.io/rust-cross/manylinux2014-cross:aarch64" + +[target.x86_64-unknown-linux-gnu] +image = "ghcr.io/rust-cross/manylinux2014-cross:x86_64" diff --git a/docs/design/w3c/w3c-representation.md b/docs/design/w3c/w3c-representation.md index a53e06e4..c1a42098 100644 --- a/docs/design/w3c/w3c-representation.md +++ b/docs/design/w3c/w3c-representation.md @@ -55,7 +55,7 @@ Methods purpose - have to forms of credentials (probably even duplicate in walle /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_credential_to_w3c( cred: ObjectHandle, issuer_id: FfiStr, @@ -71,7 +71,7 @@ pub extern "C" fn anoncreds_credential_to_w3c( /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_credential_from_w3c( cred: ObjectHandle, cred_p: *mut ObjectHandle, @@ -120,7 +120,7 @@ The reasons for adding duplication methods: /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_w3c_credential( cred_def: ObjectHandle, cred_def_private: ObjectHandle, @@ -145,7 +145,7 @@ pub extern "C" fn anoncreds_create_w3c_credential( /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_process_w3c_credential( cred: ObjectHandle, cred_req_metadata: ObjectHandle, @@ -166,7 +166,7 @@ pub extern "C" fn anoncreds_process_w3c_credential( /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_w3c_credential_get_integrity_proof_details( handle: ObjectHandle, cred_proof_info_p: *mut ObjectHandle, @@ -188,7 +188,7 @@ pub extern "C" fn anoncreds_w3c_credential_get_integrity_proof_details( /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_w3c_presentation( pres_req: ObjectHandle, credentials: FfiList, @@ -219,7 +219,7 @@ pub extern "C" fn anoncreds_create_w3c_presentation( /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_verify_w3c_presentation( presentation: ObjectHandle, pres_req: ObjectHandle, diff --git a/src/data_types/cred_def.rs b/src/data_types/cred_def.rs index caf6fd30..8789e62f 100644 --- a/src/data_types/cred_def.rs +++ b/src/data_types/cred_def.rs @@ -18,6 +18,14 @@ pub enum SignatureType { CL, } +impl SignatureType { + pub const fn as_str(&self) -> &'static str { + match self { + Self::CL => CL_SIGNATURE_TYPE, + } + } +} + impl FromStr for SignatureType { type Err = ConversionError; @@ -29,6 +37,12 @@ impl FromStr for SignatureType { } } +impl std::fmt::Display for SignatureType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(self.as_str()) + } +} + #[derive(Debug, Serialize, Deserialize)] pub struct CredentialDefinitionData { pub primary: CredentialPrimaryPublicKey, diff --git a/src/data_types/cred_request.rs b/src/data_types/cred_request.rs index e9fc917c..757b64ec 100644 --- a/src/data_types/cred_request.rs +++ b/src/data_types/cred_request.rs @@ -4,7 +4,7 @@ use crate::cl::{ }; use crate::error::{Result, ValidationError}; use crate::invalid; -use crate::utils::validation::{is_uri_identifier, Validatable, LEGACY_DID_IDENTIFIER}; +use crate::utils::validation::{LEGACY_DID_IDENTIFIER, Validatable, is_uri_identifier}; use super::{cred_def::CredentialDefinitionId, nonce::Nonce}; diff --git a/src/data_types/credential.rs b/src/data_types/credential.rs index 532e50df..9aead6c6 100644 --- a/src/data_types/credential.rs +++ b/src/data_types/credential.rs @@ -4,11 +4,11 @@ use std::collections::HashMap; #[cfg(feature = "zeroize")] use zeroize::Zeroize; +use crate::Error; use crate::cl::{CredentialSignature, RevocationRegistry, SignatureCorrectnessProof, Witness}; use crate::error::{ConversionError, ValidationError}; use crate::types::MakeCredentialValues; use crate::utils::validation::Validatable; -use crate::Error; use super::rev_reg_def::RevocationRegistryDefinitionId; use super::{cred_def::CredentialDefinitionId, schema::SchemaId}; diff --git a/src/data_types/link_secret.rs b/src/data_types/link_secret.rs index 68f6e704..5567b1de 100644 --- a/src/data_types/link_secret.rs +++ b/src/data_types/link_secret.rs @@ -1,6 +1,6 @@ use std::fmt; -use crate::cl::{bn::BigNumber, Prover as CryptoProver}; +use crate::cl::{Prover as CryptoProver, bn::BigNumber}; use crate::error::ConversionError; pub struct LinkSecret(pub(crate) BigNumber); diff --git a/src/data_types/macros.rs b/src/data_types/macros.rs index 654b38a8..e2f06641 100644 --- a/src/data_types/macros.rs +++ b/src/data_types/macros.rs @@ -3,8 +3,8 @@ macro_rules! impl_anoncreds_object_identifier { ($i:ident) => { use $crate::error::ValidationError; use $crate::utils::validation::{ - Validatable, LEGACY_CRED_DEF_IDENTIFIER, LEGACY_DID_IDENTIFIER, - LEGACY_REV_REG_DEF_IDENTIFIER, LEGACY_SCHEMA_IDENTIFIER, URI_IDENTIFIER, + LEGACY_CRED_DEF_IDENTIFIER, LEGACY_DID_IDENTIFIER, LEGACY_REV_REG_DEF_IDENTIFIER, + LEGACY_SCHEMA_IDENTIFIER, URI_IDENTIFIER, Validatable, }; #[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, Default)] @@ -53,7 +53,7 @@ macro_rules! impl_anoncreds_object_identifier { return Err($crate::invalid!( "type: {} does not have a validation regex", invalid_name, - )) + )); } }; diff --git a/src/data_types/nonce.rs b/src/data_types/nonce.rs index c0070d0f..3d03812a 100644 --- a/src/data_types/nonce.rs +++ b/src/data_types/nonce.rs @@ -2,10 +2,10 @@ use std::convert::TryFrom; use std::fmt; use std::hash::{Hash, Hasher}; -use crate::cl::{new_nonce, Nonce as CryptoNonce}; +use crate::cl::{Nonce as CryptoNonce, new_nonce}; use crate::error::ConversionError; use serde::de::{Error, SeqAccess}; -use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Visitor}; use serde_json::Value; pub struct Nonce { diff --git a/src/data_types/pres_request.rs b/src/data_types/pres_request.rs index 0838b2d6..8d1ce88a 100644 --- a/src/data_types/pres_request.rs +++ b/src/data_types/pres_request.rs @@ -2,7 +2,7 @@ use anoncreds_clsignatures::PredicateType; use std::collections::HashMap; use std::fmt; -use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer, de, ser}; use serde_json::Value; use super::credential::Credential; @@ -250,7 +250,9 @@ impl Validatable for PresentationRequest { let version = self.version(); if value.requested_attributes.is_empty() && value.requested_predicates.is_empty() { - return Err(invalid!("Presentation request validation failed: both `requested_attributes` and `requested_predicates` are empty")); + return Err(invalid!( + "Presentation request validation failed: both `requested_attributes` and `requested_predicates` are empty" + )); } for requested_attribute in value.requested_attributes.values() { @@ -270,10 +272,13 @@ impl Validatable for PresentationRequest { } if has_name && has_names { - return Err(invalid!("Presentation request validation failed: there is a requested attribute with both name and names: {:?}", requested_attribute)); + return Err(invalid!( + "Presentation request validation failed: there is a requested attribute with both name and names: {:?}", + requested_attribute + )); } - if let Some(ref restrictions) = requested_attribute.restrictions { + if let Some(restrictions) = &requested_attribute.restrictions { _process_operator(restrictions, &version)?; } } @@ -285,7 +290,7 @@ impl Validatable for PresentationRequest { requested_predicate )); } - if let Some(ref restrictions) = requested_predicate.restrictions { + if let Some(restrictions) = &requested_predicate.restrictions { _process_operator(restrictions, &version)?; } } @@ -299,37 +304,35 @@ fn _process_operator( version: &PresentationRequestVersion, ) -> Result<(), ValidationError> { match restriction_op { - Query::Eq(ref tag_name, ref tag_value) - | Query::Neq(ref tag_name, ref tag_value) - | Query::Gt(ref tag_name, ref tag_value) - | Query::Gte(ref tag_name, ref tag_value) - | Query::Lt(ref tag_name, ref tag_value) - | Query::Lte(ref tag_name, ref tag_value) - | Query::Like(ref tag_name, ref tag_value) => { - _check_restriction(tag_name, tag_value, version) - } - Query::In(ref tag_name, ref tag_values) => { + Query::Eq(tag_name, tag_value) + | Query::Neq(tag_name, tag_value) + | Query::Gt(tag_name, tag_value) + | Query::Gte(tag_name, tag_value) + | Query::Lt(tag_name, tag_value) + | Query::Lte(tag_name, tag_value) + | Query::Like(tag_name, tag_value) => _check_restriction(tag_name, tag_value, version), + Query::In(tag_name, tag_values) => { tag_values .iter() .map(|tag_value| _check_restriction(tag_name, tag_value, version)) .collect::, ValidationError>>()?; Ok(()) } - Query::Exist(ref tag_names) => { + Query::Exist(tag_names) => { tag_names .iter() .map(|tag_name| _check_restriction(tag_name, "", version)) .collect::, ValidationError>>()?; Ok(()) } - Query::And(ref operators) | Query::Or(ref operators) => { + Query::And(operators) | Query::Or(operators) => { operators .iter() .map(|operator| _process_operator(operator, version)) .collect::, ValidationError>>()?; Ok(()) } - Query::Not(ref operator) => _process_operator(operator, version), + Query::Not(operator) => _process_operator(operator, version), } } @@ -342,8 +345,10 @@ fn _check_restriction( && Credential::QUALIFIABLE_TAGS.contains(&tag_name) && validation::is_uri_identifier(tag_value) { - return Err(invalid!("Presentation request validation failed: fully qualified identifiers can not be used for presentation request of the first version. \ - Please, set \"ver\":\"2.0\" to use fully qualified identifiers.")); + return Err(invalid!( + "Presentation request validation failed: fully qualified identifiers can not be used for presentation request of the first version. \ + Please, set \"ver\":\"2.0\" to use fully qualified identifiers." + )); } Ok(()) } diff --git a/src/data_types/w3c/constants.rs b/src/data_types/w3c/constants.rs index af52bd39..cb4b14f3 100644 --- a/src/data_types/w3c/constants.rs +++ b/src/data_types/w3c/constants.rs @@ -1,5 +1,5 @@ use once_cell::sync::Lazy; -use serde_json::{json, Value}; +use serde_json::{Value, json}; use std::collections::HashSet; use crate::data_types::w3c::context::{Context, Contexts}; diff --git a/src/data_types/w3c/context.rs b/src/data_types/w3c/context.rs index cce67f96..fcefb6b4 100644 --- a/src/data_types/w3c/context.rs +++ b/src/data_types/w3c/context.rs @@ -1,9 +1,9 @@ +use crate::data_types::w3c::VerifiableCredentialSpecVersion; use crate::data_types::w3c::constants::{ ANONCREDS_VC_1_1_CONTEXTS, ANONCREDS_VC_2_0_CONTEXTS, ISSUER_DEPENDENT_VOCABULARY, W3C_DATA_INTEGRITY_CONTEXT, W3C_VC_1_1_BASE_CONTEXT, W3C_VC_2_0_BASE_CONTEXT, }; use crate::data_types::w3c::uri::URI; -use crate::data_types::w3c::VerifiableCredentialSpecVersion; #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] #[serde(untagged)] diff --git a/src/data_types/w3c/credential.rs b/src/data_types/w3c/credential.rs index ef8c848a..5b5f0847 100644 --- a/src/data_types/w3c/credential.rs +++ b/src/data_types/w3c/credential.rs @@ -3,18 +3,18 @@ use serde::{Deserialize, Serialize}; use std::collections::HashSet; use std::string::ToString; +use crate::Result; +use crate::data_types::w3c::VerifiableCredentialSpecVersion; use crate::data_types::w3c::constants::ANONCREDS_CREDENTIAL_TYPES; use crate::data_types::w3c::context::Contexts; use crate::data_types::w3c::credential_attributes::CredentialSubject; use crate::data_types::w3c::proof::{ CredentialPresentationProofValue, CredentialSignatureProofValue, DataIntegrityProof, }; -use crate::data_types::w3c::VerifiableCredentialSpecVersion; use crate::data_types::{ issuer_id::IssuerId, w3c::{constants::W3C_CREDENTIAL_TYPE, one_or_many::OneOrMany, uri::URI}, }; -use crate::Result; /// AnonCreds W3C Credential definition /// Note, that this definition is tied to AnonCreds W3C form diff --git a/src/data_types/w3c/format.rs b/src/data_types/w3c/format.rs index ab9625df..5c388169 100644 --- a/src/data_types/w3c/format.rs +++ b/src/data_types/w3c/format.rs @@ -1,5 +1,5 @@ pub mod base64_msgpack { - use serde::{de::Visitor, ser::Error, Deserialize, Serialize}; + use serde::{Deserialize, Serialize, de::Visitor, ser::Error}; use std::marker::PhantomData; use crate::utils::{base64, msg_pack}; diff --git a/src/data_types/w3c/presentation.rs b/src/data_types/w3c/presentation.rs index 52f1723e..134615bf 100644 --- a/src/data_types/w3c/presentation.rs +++ b/src/data_types/w3c/presentation.rs @@ -1,11 +1,11 @@ use serde::{Deserialize, Serialize}; +use crate::Result; +use crate::data_types::w3c::VerifiableCredentialSpecVersion; use crate::data_types::w3c::constants::{ANONCREDS_PRESENTATION_TYPES, W3C_PRESENTATION_TYPE}; use crate::data_types::w3c::context::Contexts; use crate::data_types::w3c::credential::{Types, W3CCredential}; use crate::data_types::w3c::proof::{DataIntegrityProof, PresentationProofValue}; -use crate::data_types::w3c::VerifiableCredentialSpecVersion; -use crate::Result; /// AnonCreds W3C Presentation definition /// Note, that this definition is tied to AnonCreds W3C form diff --git a/src/data_types/w3c/proof.rs b/src/data_types/w3c/proof.rs index bdcafc92..7101a096 100644 --- a/src/data_types/w3c/proof.rs +++ b/src/data_types/w3c/proof.rs @@ -3,16 +3,16 @@ use anoncreds_clsignatures::{ Witness, }; use serde::{ + Deserialize, Serialize, de::{Error, Visitor}, ser::SerializeSeq, - Deserialize, Serialize, }; use std::fmt::Debug; +use crate::Result; use crate::data_types::cred_def::CredentialDefinitionId; use crate::data_types::rev_reg_def::RevocationRegistryDefinitionId; use crate::data_types::schema::SchemaId; -use crate::Result; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum DataIntegrityProofType { diff --git a/src/data_types/w3c/uri.rs b/src/data_types/w3c/uri.rs index 1f770158..d8f0503a 100644 --- a/src/data_types/w3c/uri.rs +++ b/src/data_types/w3c/uri.rs @@ -1,4 +1,4 @@ -use serde::{de, Deserialize, Deserializer}; +use serde::{Deserialize, Deserializer, de}; use serde_json::Value; use crate::utils::validation::URI_IDENTIFIER; diff --git a/src/error.rs b/src/error.rs index 12141a3f..779754c9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,5 @@ use std::error::Error as StdError; use std::fmt::{self, Display, Formatter}; -use std::result::Result as StdResult; use crate::cl::{Error as CryptoError, ErrorKind as CryptoErrorKind}; @@ -188,52 +187,6 @@ macro_rules! err_map { }; } -pub trait ResultExt { - fn map_err_string(self) -> StdResult; - fn map_input_err(self, mapfn: F) -> Result - where - F: FnOnce() -> M, - M: fmt::Display + Send + Sync + 'static; - fn with_err_msg(self, kind: ErrorKind, msg: M) -> Result - where - M: fmt::Display + Send + Sync + 'static; - fn with_input_err(self, msg: M) -> Result - where - M: fmt::Display + Send + Sync + 'static; -} - -impl ResultExt for StdResult -where - E: std::error::Error + Send + Sync + 'static, -{ - fn map_err_string(self) -> StdResult { - self.map_err(|err| err.to_string()) - } - - fn map_input_err(self, mapfn: F) -> Result - where - F: FnOnce() -> M, - M: fmt::Display + Send + Sync + 'static, - { - self.map_err(|err| Error::from_msg(ErrorKind::Input, mapfn().to_string()).with_cause(err)) - } - - fn with_err_msg(self, kind: ErrorKind, msg: M) -> Result - where - M: fmt::Display + Send + Sync + 'static, - { - self.map_err(|err| Error::from_msg(kind, msg.to_string()).with_cause(err)) - } - - #[inline] - fn with_input_err(self, msg: M) -> Result - where - M: fmt::Display + Send + Sync + 'static, - { - self.map_err(|err| Error::from_msg(ErrorKind::Input, msg.to_string()).with_cause(err)) - } -} - type DynError = Box; macro_rules! define_error { diff --git a/src/ffi/cred_def.rs b/src/ffi/cred_def.rs index 8acf8185..9895199a 100644 --- a/src/ffi/cred_def.rs +++ b/src/ffi/cred_def.rs @@ -1,8 +1,9 @@ +use std::os::raw::c_char; use std::str::FromStr; -use ffi_support::{rust_string_to_c, FfiStr}; +use ffi_support::{FfiStr, rust_string_to_c}; -use super::error::{catch_error, ErrorCode}; +use super::error::{ErrorCode, catch_error}; use super::object::ObjectHandle; use crate::data_types::cred_def::CredentialDefinition; use crate::services::{ @@ -12,9 +13,8 @@ use crate::services::{ CredentialKeyCorrectnessProof as KeyCorrectnessProof, SignatureType, }, }; -use std::os::raw::c_char; -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_credential_definition_get_attribute( handle: ObjectHandle, name: FfiStr, @@ -25,12 +25,10 @@ pub extern "C" fn anoncreds_credential_definition_get_attribute( let cred_def = handle.load()?; let cred_def = cred_def.cast_ref::()?; let val = match name.as_opt_str().unwrap_or_default() { - "schema_id" => cred_def.schema_id.to_string().to_owned(), - "tag" => cred_def.tag.to_string().to_owned(), - "issuer_id" => cred_def.issuer_id.to_string().to_owned(), - "signature_type" => match cred_def.signature_type { - SignatureType::CL => "CL".to_string(), - }, + "schema_id" => cred_def.schema_id.to_string(), + "tag" => cred_def.tag.to_string(), + "issuer_id" => cred_def.issuer_id.to_string(), + "signature_type" => cred_def.signature_type.to_string(), s => return Err(err_msg!("Unsupported attribute: {}", s)), }; unsafe { *result_p = rust_string_to_c(val) }; @@ -38,7 +36,7 @@ pub extern "C" fn anoncreds_credential_definition_get_attribute( }) } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_credential_definition( schema_id: FfiStr, schema: ObjectHandle, diff --git a/src/ffi/cred_offer.rs b/src/ffi/cred_offer.rs index 7d3aed71..4d3ac7d6 100644 --- a/src/ffi/cred_offer.rs +++ b/src/ffi/cred_offer.rs @@ -1,10 +1,10 @@ use ffi_support::FfiStr; -use super::error::{catch_error, ErrorCode}; +use super::error::{ErrorCode, catch_error}; use super::object::ObjectHandle; use crate::services::{issuer::create_credential_offer, types::CredentialOffer}; -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_credential_offer( schema_id: FfiStr, cred_def_id: FfiStr, diff --git a/src/ffi/cred_req.rs b/src/ffi/cred_req.rs index 3e5625f5..d6c1af10 100644 --- a/src/ffi/cred_req.rs +++ b/src/ffi/cred_req.rs @@ -1,6 +1,6 @@ use ffi_support::FfiStr; -use super::error::{catch_error, ErrorCode}; +use super::error::{ErrorCode, catch_error}; use super::object::ObjectHandle; use crate::data_types::cred_def::CredentialDefinition; use crate::data_types::link_secret::LinkSecret; @@ -9,7 +9,7 @@ use crate::services::{ types::{CredentialRequest, CredentialRequestMetadata}, }; -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_credential_request( entropy: FfiStr, prover_did: FfiStr, diff --git a/src/ffi/credential.rs b/src/ffi/credential.rs index 05b4e11e..1dc3ca9a 100644 --- a/src/ffi/credential.rs +++ b/src/ffi/credential.rs @@ -1,11 +1,12 @@ use std::os::raw::c_char; use std::ptr; -use ffi_support::{rust_string_to_c, FfiStr}; +use ffi_support::{FfiStr, rust_string_to_c}; -use super::error::{catch_error, ErrorCode}; +use super::error::{ErrorCode, catch_error}; use super::object::{AnoncredsObject, ObjectHandle}; use super::util::FfiStrList; +use crate::Error; use crate::data_types::link_secret::LinkSecret; use crate::error::Result; use crate::services::{ @@ -15,7 +16,6 @@ use crate::services::{ types::{Credential, CredentialRevocationConfig, MakeCredentialValues}, }; use crate::types::CredentialValues; -use crate::Error; #[derive(Debug)] #[repr(C)] @@ -65,7 +65,7 @@ impl<'a> TryFrom<&'a RevocationConfig> for CredentialRevocationConfig<'a> { impl_anoncreds_object!(Credential, "Credential"); impl_anoncreds_object_from_json!(Credential, anoncreds_credential_from_json); -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_credential( cred_def: ObjectHandle, cred_def_private: ObjectHandle, @@ -102,7 +102,7 @@ pub extern "C" fn anoncreds_create_credential( }) } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_encode_credential_attributes( attr_raw_values: FfiStrList, result_p: *mut *const c_char, @@ -125,7 +125,7 @@ pub extern "C" fn anoncreds_encode_credential_attributes( }) } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_process_credential( cred: ObjectHandle, cred_req_metadata: ObjectHandle, @@ -161,7 +161,7 @@ pub extern "C" fn anoncreds_process_credential( }) } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_credential_get_attribute( handle: ObjectHandle, name: FfiStr, diff --git a/src/ffi/error.rs b/src/ffi/error.rs index cfd7b070..5c8d1101 100644 --- a/src/ffi/error.rs +++ b/src/ffi/error.rs @@ -1,7 +1,7 @@ use crate::error::{Error, ErrorKind, Result}; use std::os::raw::c_char; -use std::panic::{catch_unwind, UnwindSafe}; +use std::panic::{UnwindSafe, catch_unwind}; use std::sync::RwLock; use ffi_support::rust_string_to_c; @@ -48,7 +48,7 @@ impl From> for ErrorCode { } } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_get_current_error(error_json_p: *mut *const c_char) -> ErrorCode { trace!("anoncreds_get_current_error"); diff --git a/src/ffi/link_secret.rs b/src/ffi/link_secret.rs index d99cb310..716c3b89 100644 --- a/src/ffi/link_secret.rs +++ b/src/ffi/link_secret.rs @@ -1,9 +1,9 @@ -use super::error::{catch_error, ErrorCode}; +use super::error::{ErrorCode, catch_error}; use crate::services::prover::create_link_secret; use ffi_support::rust_string_to_c; use std::os::raw::c_char; -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_link_secret(link_secret_p: *mut *const c_char) -> ErrorCode { catch_error(|| { check_useful_c_ptr!(link_secret_p); diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs index 2f400375..8ff0580d 100644 --- a/src/ffi/mod.rs +++ b/src/ffi/mod.rs @@ -1,13 +1,13 @@ use std::os::raw::c_char; -use ffi_support::{rust_string_to_c, ByteBuffer}; +use ffi_support::{ByteBuffer, rust_string_to_c}; use zeroize::Zeroize; pub static LIB_VERSION: &str = env!("CARGO_PKG_VERSION"); ffi_support::define_string_destructor!(anoncreds_string_free); -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_buffer_free(buffer: ByteBuffer) { ffi_support::abort_on_panic::with_abort_on_panic(|| { buffer.destroy_into_vec().zeroize(); @@ -18,7 +18,7 @@ pub extern "C" fn anoncreds_buffer_free(buffer: ByteBuffer) { mod macros; mod error; -use self::error::{catch_error, ErrorCode}; +use self::error::{ErrorCode, catch_error}; #[macro_use] mod object; @@ -38,7 +38,7 @@ mod schema; #[cfg(feature = "w3c")] mod w3c; -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_set_default_logger() -> ErrorCode { catch_error(|| { env_logger::init(); @@ -47,7 +47,7 @@ pub extern "C" fn anoncreds_set_default_logger() -> ErrorCode { }) } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_version() -> *mut c_char { rust_string_to_c(LIB_VERSION.to_owned()) } diff --git a/src/ffi/object.rs b/src/ffi/object.rs index 484d1be7..1ecda8e6 100644 --- a/src/ffi/object.rs +++ b/src/ffi/object.rs @@ -7,11 +7,11 @@ use std::ops::{Deref, DerefMut}; use std::os::raw::c_char; use std::sync::{Arc, Mutex}; -use ffi_support::{rust_string_to_c, ByteBuffer}; +use ffi_support::{ByteBuffer, rust_string_to_c}; use once_cell::sync::Lazy; use serde::Serialize; -use super::error::{catch_error, ErrorCode}; +use super::error::{ErrorCode, catch_error}; use crate::error::Result; use crate::new_handle_type; @@ -141,7 +141,7 @@ macro_rules! impl_anoncreds_object { macro_rules! impl_anoncreds_object_from_json { ($ident:path, $method:ident) => { - #[no_mangle] + #[unsafe(no_mangle)] pub extern "C" fn $method( json: ffi_support::ByteBuffer, result_p: *mut $crate::ffi::object::ObjectHandle, @@ -157,7 +157,7 @@ macro_rules! impl_anoncreds_object_from_json { }; } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_object_get_json( handle: ObjectHandle, result_p: *mut ByteBuffer, @@ -171,7 +171,7 @@ pub extern "C" fn anoncreds_object_get_json( }) } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_object_get_type_name( handle: ObjectHandle, result_p: *mut *const c_char, @@ -185,7 +185,7 @@ pub extern "C" fn anoncreds_object_get_type_name( }) } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_object_free(handle: ObjectHandle) { handle.remove().ok(); } @@ -214,7 +214,7 @@ impl AnoncredsObjectList { Ok(refs) } - pub fn refs_map<'a, I, T>(&'a self, ids: &'a [I]) -> Result> + pub fn refs_map<'a, I, T>(&'a self, ids: &'a [I]) -> Result> where T: AnyAnoncredsObject + 'static, I: Eq + Hash, diff --git a/src/ffi/pres_req.rs b/src/ffi/pres_req.rs index f0ff3865..7c0f631d 100644 --- a/src/ffi/pres_req.rs +++ b/src/ffi/pres_req.rs @@ -2,7 +2,7 @@ use std::os::raw::c_char; use ffi_support::rust_string_to_c; -use super::error::{catch_error, ErrorCode}; +use super::error::{ErrorCode, catch_error}; use crate::services::{types::PresentationRequest, verifier::generate_nonce}; impl_anoncreds_object!(PresentationRequest, "PresentationRequest"); @@ -11,7 +11,7 @@ impl_anoncreds_object_from_json!( anoncreds_presentation_request_from_json ); -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_generate_nonce(nonce_p: *mut *const c_char) -> ErrorCode { catch_error(|| { check_useful_c_ptr!(nonce_p); diff --git a/src/ffi/presentation.rs b/src/ffi/presentation.rs index cef906d5..c915a496 100644 --- a/src/ffi/presentation.rs +++ b/src/ffi/presentation.rs @@ -1,4 +1,4 @@ -use super::error::{catch_error, ErrorCode}; +use super::error::{ErrorCode, catch_error}; use super::object::{AnoncredsObject, AnoncredsObjectList, ObjectHandle}; use super::util::{FfiList, FfiStrList}; use crate::data_types::cred_def::{CredentialDefinition, CredentialDefinitionId}; @@ -60,7 +60,7 @@ pub(crate) struct CredentialEntry { rev_state: Option, } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_presentation( pres_req: ObjectHandle, credentials: FfiList, @@ -143,7 +143,7 @@ impl<'a> FfiNonrevokedIntervalOverride<'a> { } } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_verify_presentation( presentation: ObjectHandle, pres_req: ObjectHandle, diff --git a/src/ffi/revocation.rs b/src/ffi/revocation.rs index b335292a..62f1b9ca 100644 --- a/src/ffi/revocation.rs +++ b/src/ffi/revocation.rs @@ -1,4 +1,4 @@ -use super::error::{catch_error, ErrorCode}; +use super::error::{ErrorCode, catch_error}; use super::object::{AnoncredsObject, ObjectHandle}; use super::util::FfiList; use crate::data_types::rev_status_list::RevocationStatusList; @@ -13,12 +13,12 @@ use crate::services::issuer::create_revocation_registry_def; use crate::services::prover::create_or_update_revocation_state; use crate::services::tails::TailsFileWriter; use crate::services::types::CredentialRevocationState; -use ffi_support::{rust_string_to_c, FfiStr}; +use ffi_support::{FfiStr, rust_string_to_c}; use std::collections::BTreeSet; use std::os::raw::c_char; use std::str::FromStr; -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_revocation_status_list( cred_def: ObjectHandle, rev_reg_def_id: FfiStr, @@ -59,7 +59,7 @@ pub extern "C" fn anoncreds_create_revocation_status_list( }) } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_update_revocation_status_list( cred_def: ObjectHandle, rev_reg_def: ObjectHandle, @@ -105,7 +105,7 @@ pub extern "C" fn anoncreds_update_revocation_status_list( }) } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_update_revocation_status_list_timestamp_only( timestamp: i64, rev_current_list: ObjectHandle, @@ -128,7 +128,7 @@ pub extern "C" fn anoncreds_update_revocation_status_list_timestamp_only( }) } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_revocation_registry_def( cred_def: ObjectHandle, cred_def_id: FfiStr, @@ -181,7 +181,7 @@ impl_anoncreds_object_from_json!( anoncreds_revocation_registry_definition_from_json ); -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_revocation_registry_definition_get_attribute( handle: ObjectHandle, name: FfiStr, @@ -220,7 +220,7 @@ impl_anoncreds_object_from_json!( anoncreds_revocation_status_list_from_json ); -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_or_update_revocation_state( rev_reg_def: ObjectHandle, rev_status_list: ObjectHandle, diff --git a/src/ffi/schema.rs b/src/ffi/schema.rs index 88cd36b2..27f622db 100644 --- a/src/ffi/schema.rs +++ b/src/ffi/schema.rs @@ -1,12 +1,12 @@ use ffi_support::FfiStr; -use super::error::{catch_error, ErrorCode}; +use super::error::{ErrorCode, catch_error}; use super::object::ObjectHandle; use super::util::FfiStrList; use crate::data_types::schema::Schema; use crate::services::issuer::create_schema; -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_schema( schema_name: FfiStr, schema_version: FfiStr, diff --git a/src/ffi/util.rs b/src/ffi/util.rs index 20662a95..93399303 100644 --- a/src/ffi/util.rs +++ b/src/ffi/util.rs @@ -40,11 +40,7 @@ impl<'a, T> FfiList<'a, T> { #[inline] pub fn len(&self) -> usize { - if self.data.is_null() { - 0 - } else { - self.count - } + if self.data.is_null() { 0 } else { self.count } } } diff --git a/src/ffi/w3c/credential.rs b/src/ffi/w3c/credential.rs index 27a71f47..fd71e6f8 100644 --- a/src/ffi/w3c/credential.rs +++ b/src/ffi/w3c/credential.rs @@ -1,5 +1,5 @@ use crate::data_types::w3c::VerifiableCredentialSpecVersion; -use ffi_support::{rust_string_to_c, FfiStr}; +use ffi_support::{FfiStr, rust_string_to_c}; use std::ffi::c_char; use std::ptr; @@ -7,8 +7,8 @@ use crate::data_types::w3c::credential::W3CCredential; use crate::data_types::w3c::credential_attributes::CredentialSubject; use crate::data_types::w3c::proof::CredentialProofDetails; use crate::error::Result; -use crate::ffi::credential::{FfiCredRevInfo, _link_secret, _revocation_config}; -use crate::ffi::error::{catch_error, ErrorCode}; +use crate::ffi::credential::{_link_secret, _revocation_config, FfiCredRevInfo}; +use crate::ffi::error::{ErrorCode, catch_error}; use crate::ffi::object::{AnoncredsObject, ObjectHandle}; use crate::ffi::util::FfiStrList; use crate::types::Credential; @@ -35,7 +35,7 @@ impl_anoncreds_object_from_json!(W3CCredential, anoncreds_w3c_credential_from_js /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_w3c_credential( cred_def: ObjectHandle, cred_def_private: ObjectHandle, @@ -89,7 +89,7 @@ pub extern "C" fn anoncreds_create_w3c_credential( /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_process_w3c_credential( cred: ObjectHandle, cred_req_metadata: ObjectHandle, @@ -131,7 +131,7 @@ pub extern "C" fn anoncreds_process_w3c_credential( /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_credential_to_w3c( cred: ObjectHandle, issuer_id: FfiStr, @@ -168,7 +168,7 @@ pub extern "C" fn anoncreds_credential_to_w3c( /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_credential_from_w3c( cred: ObjectHandle, cred_p: *mut ObjectHandle, @@ -198,7 +198,7 @@ pub extern "C" fn anoncreds_credential_from_w3c( /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_w3c_credential_get_integrity_proof_details( handle: ObjectHandle, cred_proof_info_p: *mut ObjectHandle, @@ -215,7 +215,7 @@ pub extern "C" fn anoncreds_w3c_credential_get_integrity_proof_details( }) } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_w3c_credential_proof_get_attribute( handle: ObjectHandle, name: FfiStr, diff --git a/src/ffi/w3c/presentation.rs b/src/ffi/w3c/presentation.rs index 01f6d64a..6ddcd1ad 100644 --- a/src/ffi/w3c/presentation.rs +++ b/src/ffi/w3c/presentation.rs @@ -1,12 +1,12 @@ -use crate::data_types::w3c::presentation::W3CPresentation; use crate::data_types::w3c::VerifiableCredentialSpecVersion; +use crate::data_types::w3c::presentation::W3CPresentation; use crate::ffi::credential::_link_secret; -use crate::ffi::error::{catch_error, ErrorCode}; +use crate::ffi::error::{ErrorCode, catch_error}; use crate::ffi::object::ObjectHandle; use crate::ffi::presentation::{ - FfiCredentialEntry, FfiCredentialProve, FfiNonrevokedIntervalOverride, _credentials, - _nonrevoke_interval_override, _prepare_cred_defs, _prepare_schemas, _present_credentials, - _rev_reg_defs, _rev_status_list, + _credentials, _nonrevoke_interval_override, _prepare_cred_defs, _prepare_schemas, + _present_credentials, _rev_reg_defs, _rev_status_list, FfiCredentialEntry, FfiCredentialProve, + FfiNonrevokedIntervalOverride, }; use crate::ffi::util::{FfiList, FfiStrList}; use crate::w3c::prover::create_presentation; @@ -32,7 +32,7 @@ impl_anoncreds_object_from_json!(W3CPresentation, anoncreds_w3c_presentation_fro /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_create_w3c_presentation( pres_req: ObjectHandle, credentials: FfiList, @@ -90,7 +90,7 @@ pub extern "C" fn anoncreds_create_w3c_presentation( /// /// # Returns /// Error code -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn anoncreds_verify_w3c_presentation( presentation: ObjectHandle, pres_req: ObjectHandle, diff --git a/src/macros.rs b/src/macros.rs index 4b460bb0..7cc2a0fc 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,13 +1,9 @@ #[cfg(debug_assertions)] macro_rules! secret { - ($val:expr) => {{ - $val - }}; + ($val:expr) => {{ $val }}; } #[cfg(not(debug_assertions))] macro_rules! secret { - ($val:expr) => {{ - "_" - }}; + ($val:expr) => {{ "_" }}; } diff --git a/src/services/helpers.rs b/src/services/helpers.rs index 117a358b..d24fff9a 100644 --- a/src/services/helpers.rs +++ b/src/services/helpers.rs @@ -1,6 +1,6 @@ use crate::cl::{ - bn::BigNumber, CredentialSchema, CredentialValues as CLCredentialValues, Issuer, - NonCredentialSchema, SubProofRequest, Verifier, + CredentialSchema, CredentialValues as CLCredentialValues, Issuer, NonCredentialSchema, + SubProofRequest, Verifier, bn::BigNumber, }; use crate::data_types::presentation::RequestedProof; use crate::data_types::rev_reg_def::RevocationRegistryDefinitionId; @@ -12,8 +12,8 @@ use crate::data_types::{ pres_request::{NonRevokedInterval, PresentationRequestPayload}, }; use crate::error::Result; -use crate::utils::hash::SHA256; use anoncreds_clsignatures::Predicate; +use sha2::{Digest, Sha256}; use std::collections::{HashMap, HashSet}; pub fn attr_common_view(attr: &str) -> String { @@ -76,7 +76,7 @@ pub fn encode_credential_attribute(raw_value: &str) -> Result { if let Ok(val) = raw_value.parse::() { Ok(val.to_string()) } else { - let digest = SHA256::digest(raw_value.as_bytes()); + let digest = Sha256::digest(raw_value.as_bytes()); #[cfg(target_endian = "big")] let digest = { let mut d = digest; @@ -93,8 +93,7 @@ pub fn build_sub_proof_request( ) -> Result { trace!( "build_sub_proof_request >>> attrs_for_credential: {:?}, predicates_for_credential: {:?}", - attrs_for_credential, - predicates_for_credential + attrs_for_credential, predicates_for_credential ); let mut sub_proof_request_builder = Verifier::new_sub_proof_request_builder()?; diff --git a/src/services/issuer.rs b/src/services/issuer.rs index 44e1cf61..0daf6529 100644 --- a/src/services/issuer.rs +++ b/src/services/issuer.rs @@ -56,9 +56,7 @@ pub fn create_schema( ) -> Result { trace!( "create_schema >>> schema_name: {}, schema_version: {}, attr_names: {:?}", - schema_name, - schema_version, - attr_names, + schema_name, schema_version, attr_names, ); let schema = Schema { @@ -128,8 +126,7 @@ pub fn create_credential_definition( )> { trace!( "create_credential_definition >>> schema: {:?}, config: {:?}", - schema, - config + schema, config ); let credential_schema = build_credential_schema(schema)?; @@ -237,8 +234,10 @@ pub fn create_revocation_registry_def( where TW: TailsWriter, { - trace!("create_revocation_registry >>> cred_def: {:?}, tag: {:?}, max_cred_num: {:?}, rev_reg_type: {:?}", - cred_def, tag, max_cred_num, rev_reg_type); + trace!( + "create_revocation_registry >>> cred_def: {:?}, tag: {:?}, max_cred_num: {:?}, rev_reg_type: {:?}", + cred_def, tag, max_cred_num, rev_reg_type + ); let credential_pub_key = cred_def.get_public_key().map_err(err_map!( Unexpected, @@ -708,10 +707,16 @@ pub fn create_credential( cred_values: CredentialValues, revocation_config: Option, ) -> Result { - trace!("create_credential >>> cred_def: {:?}, cred_def_private: {:?}, cred_offer.nonce: {:?}, cred_request: {:?},\ + trace!( + "create_credential >>> cred_def: {:?}, cred_def_private: {:?}, cred_offer.nonce: {:?}, cred_request: {:?},\ cred_values: {:?}, revocation_config: {:?}", - cred_def, secret!(&cred_def_private), &cred_offer.nonce, &cred_request, secret!(&cred_values), revocation_config, - ); + cred_def, + secret!(&cred_def_private), + &cred_offer.nonce, + &cred_request, + secret!(&cred_values), + revocation_config, + ); let (credential_signature, signature_correctness_proof, rev_reg_id, rev_reg, witness) = CLCredentialIssuer::new(cred_def, cred_def_private).create_credential( @@ -857,8 +862,8 @@ mod tests { use super::*; #[test] - fn test_issuer_id_equal_in_revocation_registry_definiton_and_credential_definition( - ) -> Result<()> { + fn test_issuer_id_equal_in_revocation_registry_definiton_and_credential_definition() + -> Result<()> { let issuer_id = "sample:uri".try_into()?; let schema_id = "schema:id".try_into()?; let cred_def_id = "sample:uri".try_into()?; diff --git a/src/services/prover.rs b/src/services/prover.rs index 2c7ea607..2762bcf8 100644 --- a/src/services/prover.rs +++ b/src/services/prover.rs @@ -162,8 +162,7 @@ pub fn create_credential_request( trace!( "create_credential_request <<< credential_request: {:?}, credential_request_metadata: {:?}", - credential_request, - credential_request_metadata + credential_request, credential_request_metadata ); Ok((credential_request, credential_request_metadata)) @@ -249,8 +248,14 @@ pub fn process_credential( cred_def: &CredentialDefinition, rev_reg_def: Option<&RevocationRegistryDefinition>, ) -> Result<()> { - trace!("process_credential >>> credential: {:?}, cred_request_metadata: {:?}, link_secret: {:?}, cred_def: {:?}, rev_reg_def: {:?}", - credential, cred_request_metadata, secret!(&link_secret), cred_def, rev_reg_def); + trace!( + "process_credential >>> credential: {:?}, cred_request_metadata: {:?}, link_secret: {:?}, cred_def: {:?}, rev_reg_def: {:?}", + credential, + cred_request_metadata, + secret!(&link_secret), + cred_def, + rev_reg_def + ); CLCredentialProver::new(link_secret).process_credential( &mut credential.signature, @@ -397,8 +402,16 @@ pub fn create_presentation( schemas: &HashMap, cred_defs: &HashMap, ) -> Result { - trace!("create_presentation >>> credentials: {:?}, pres_req: {:?}, credentials: {:?}, self_attested: {:?}, link_secret: {:?}, schemas: {:?}, cred_defs: {:?}", - credentials, pres_req, credentials, &self_attested, secret!(&link_secret), schemas, cred_defs); + trace!( + "create_presentation >>> credentials: {:?}, pres_req: {:?}, credentials: {:?}, self_attested: {:?}, link_secret: {:?}, schemas: {:?}, cred_defs: {:?}", + credentials, + pres_req, + credentials, + &self_attested, + secret!(&link_secret), + schemas, + cred_defs + ); if credentials.is_empty() && self_attested.as_ref().map_or(true, HashMap::is_empty) { return Err(err_msg!( @@ -419,41 +432,31 @@ pub fn create_presentation( let mut proof_builder = CLProofBuilder::new(pres_req_val, schemas, cred_defs)?; - for present in credentials.0 { + for present in &credentials.0 { if present.is_empty() { continue; } let credential = present.cred; - update_requested_proof( - &present.requested_attributes, - &present.requested_predicates, - pres_req_val, - credential, - sub_proof_index, - &mut requested_proof, - )?; + update_requested_proof(present, pres_req_val, sub_proof_index, &mut requested_proof)?; + let proof_link_secret = present.link_secret.unwrap_or(link_secret); proof_builder.add_sub_proof( &credential.values, &credential.signature, - link_secret, + proof_link_secret, &present, &credential.schema_id, &credential.cred_def_id, credential.rev_reg_id.as_ref(), )?; - let identifier = match pres_req { - PresentationRequest::PresentationRequestV2(_) - | PresentationRequest::PresentationRequestV1(_) => Identifier { - schema_id: credential.schema_id.clone(), - cred_def_id: credential.cred_def_id.clone(), - rev_reg_id: credential.rev_reg_id.clone(), - timestamp: present.timestamp, - }, + let identifier = Identifier { + schema_id: credential.schema_id.clone(), + cred_def_id: credential.cred_def_id.clone(), + rev_reg_id: credential.rev_reg_id.clone(), + timestamp: present.timestamp, }; - identifiers.push(identifier); sub_proof_index += 1; @@ -585,11 +588,7 @@ pub fn create_or_update_revocation_state( trace!( "create_or_update_revocation_state >>> revoc_reg_def: {:?}, \ rev_status_list: {:?}, rev_reg_idx: {}, rev_state: {:?}, old_rev_status_list {:?}", - rev_reg_def, - rev_status_list, - rev_reg_idx, - rev_state, - old_rev_status_list, + rev_reg_def, rev_status_list, rev_reg_idx, rev_state, old_rev_status_list, ); let rev_reg: Option = rev_status_list.into(); @@ -704,16 +703,21 @@ fn get_credential_values_for_attribute( } fn update_requested_proof( - req_attrs_for_credential: &HashSet<(String, bool)>, - req_predicates_for_credential: &HashSet, + present: &PresentCredential<'_, Credential>, proof_req: &PresentationRequestPayload, - credential: &Credential, sub_proof_index: u32, requested_proof: &mut RequestedProof, ) -> Result<()> { - trace!("_update_requested_proof >>> req_attrs_for_credential: {:?}, req_predicates_for_credential: {:?}, proof_req: {:?}, credential: {:?}, \ - sub_proof_index: {:?}, requested_proof: {:?}", - req_attrs_for_credential, req_predicates_for_credential, proof_req, secret!(&credential), sub_proof_index, secret!(&requested_proof)); + trace!( + "_update_requested_proof >>> presented: {:?}, sub_proof_index: {:?}, requested_proof: {:?}", + secret!(&present), + sub_proof_index, + secret!(&requested_proof) + ); + + let credential = present.cred; + let req_attrs_for_credential = &present.requested_attributes; + let req_predicates_for_credential = &present.requested_predicates; for (attr_referent, revealed) in req_attrs_for_credential { if *revealed { @@ -1011,8 +1015,8 @@ mod tests { } #[test] - fn get_credential_values_for_attribute_works_for_cred_values_and_requested_attr_contains_spaces( - ) { + fn get_credential_values_for_attribute_works_for_cred_values_and_requested_attr_contains_spaces() + { let cred_values = hashmap!(" name ".to_string() => _attr_values()); let res = @@ -1053,8 +1057,8 @@ mod tests { .unwrap() } - fn _cred_def_and_key_correctness_proof( - ) -> (CredentialDefinition, CredentialKeyCorrectnessProof) { + fn _cred_def_and_key_correctness_proof() + -> (CredentialDefinition, CredentialKeyCorrectnessProof) { let (cred_def, _, key_correctness_proof) = create_credential_definition( SCHEMA_ID.try_into().unwrap(), &_schema(), @@ -1088,8 +1092,8 @@ mod tests { .unwrap() } - fn _legacy_cred_def_and_key_correctness_proof( - ) -> (CredentialDefinition, CredentialKeyCorrectnessProof) { + fn _legacy_cred_def_and_key_correctness_proof() + -> (CredentialDefinition, CredentialKeyCorrectnessProof) { let (cred_def, _, key_correctness_proof) = create_credential_definition( LEGACY_SCHEMA_IDENTIFIER.try_into().unwrap(), &_legacy_schema(), diff --git a/src/services/tails.rs b/src/services/tails.rs index 572ae250..40570110 100644 --- a/src/services/tails.rs +++ b/src/services/tails.rs @@ -7,13 +7,13 @@ use std::path::{Path, PathBuf}; use rand::random; use sha2::{Digest, Sha256}; +use crate::ErrorKind; use crate::cl::{ Error as ClError, ErrorKind as ClErrorKind, RevocationTailsAccessor, RevocationTailsGenerator, Tail, }; use crate::error::Error; use crate::utils::base58; -use crate::ErrorKind; const TAILS_BLOB_TAG_SZ: u8 = 2; const TAIL_SIZE: usize = Tail::BYTES_REPR_SIZE; diff --git a/src/services/types.rs b/src/services/types.rs index e8cc9d06..2945af98 100644 --- a/src/services/types.rs +++ b/src/services/types.rs @@ -46,7 +46,7 @@ impl MakeCredentialValues { raw: impl Into, encoded: String, ) { - self.0 .0.insert( + self.0.0.insert( name.into(), AttributeValues { raw: raw.into(), @@ -63,7 +63,7 @@ impl MakeCredentialValues { let raw = raw.into(); let encoded = encode_credential_attribute(&raw)?; self.0 - .0 + .0 .insert(name.into(), AttributeValues { raw, encoded }); Ok(()) } @@ -98,6 +98,7 @@ impl<'p, T> PresentCredentials<'p, T> { rev_state, requested_attributes: HashSet::new(), requested_predicates: HashSet::new(), + link_secret: None, }); AddCredential { present: &mut self.0[idx], @@ -153,6 +154,7 @@ pub(crate) struct PresentCredential<'p, T> { pub rev_state: Option<&'p CredentialRevocationState>, pub requested_attributes: HashSet<(String, bool)>, pub requested_predicates: HashSet, + pub link_secret: Option<&'p LinkSecret>, // For testing only } impl PresentCredential<'_, T> { @@ -187,6 +189,13 @@ impl<'a, 'p, T> AddCredential<'a, 'p, T> { pub fn add_requested_predicate(&mut self, referent: impl Into) { self.present.requested_predicates.insert(referent.into()); } + + /// This method is intended for testing only, normally the link secret is + /// passed directly when creating a presentation. + #[doc(hidden)] + pub fn set_link_secret(&mut self, link_secret: &'p LinkSecret) { + self.present.link_secret.replace(link_secret); + } } #[allow(dead_code)] @@ -206,12 +215,6 @@ pub(crate) struct RequestedPredicate<'a> { pub rev_state: Option<&'a CredentialRevocationState>, } -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub(crate) struct ProvingCredentialKey { - pub cred_id: String, - pub timestamp: Option, -} - #[derive(Clone, Debug, Serialize, Deserialize)] pub struct CredentialRevocationState { pub witness: Witness, diff --git a/src/services/verifier.rs b/src/services/verifier.rs index 27505fdb..de7f9ebe 100644 --- a/src/services/verifier.rs +++ b/src/services/verifier.rs @@ -52,8 +52,10 @@ pub fn verify_presentation( &HashMap>, >, ) -> Result { - trace!("verify >>> presentation: {:?}, pres_req: {:?}, schemas: {:?}, cred_defs: {:?}, rev_reg_defs: {:?} rev_status_lists: {:?}", - presentation, pres_req, schemas, cred_defs, rev_reg_defs, rev_status_lists); + trace!( + "verify >>> presentation: {:?}, pres_req: {:?}, schemas: {:?}, cred_defs: {:?}, rev_reg_defs: {:?} rev_status_lists: {:?}", + presentation, pres_req, schemas, cred_defs, rev_reg_defs, rev_status_lists + ); // These values are from the prover and cannot be trusted let received_revealed_attrs: HashMap = @@ -310,7 +312,10 @@ fn verify_revealed_attribute_values( ) })?; if attr_infos.values.len() != attr_names.len() { - error!("Proof Revealed Attr Group does not match Proof Request Attribute Group, proof request attrs: {:?}, referent: {:?}, attr_infos: {:?}", pres_req.requested_attributes, attr_referent, attr_infos); + error!( + "Proof Revealed Attr Group does not match Proof Request Attribute Group, proof request attrs: {:?}, referent: {:?}, attr_infos: {:?}", + pres_req.requested_attributes, attr_referent, attr_infos + ); return Err(err_msg!( "Proof Revealed Attr Group does not match Proof Request Attribute Group", )); @@ -352,8 +357,13 @@ pub(crate) fn verify_revealed_attribute_value( })?; if reveal_attr_encoded != crypto_proof_encoded { - return Err(err_msg!(ProofRejected, - "Encoded Values for \"{}\" are different in RequestedProof \"{}\" and CryptoProof \"{}\"", attr_name, reveal_attr_encoded, crypto_proof_encoded)); + return Err(err_msg!( + ProofRejected, + "Encoded Values for \"{}\" are different in RequestedProof \"{}\" and CryptoProof \"{}\"", + attr_name, + reveal_attr_encoded, + crypto_proof_encoded + )); } Ok(()) @@ -409,7 +419,9 @@ pub(crate) fn verify_requested_restrictions( if filter_tags.contains(&"issuer_id".to_owned()) && filter_tags.contains(&"issuer_did".to_owned()) { - return Err(err_msg!("Presentation request contains restriction for `issuer_id` (new) and `issuer_did` (legacy)")); + return Err(err_msg!( + "Presentation request contains restriction for `issuer_id` (new) and `issuer_did` (legacy)" + )); } // We check whether both the `schema_issuer_id` and `schema_issuer_did` are included. Since @@ -418,7 +430,9 @@ pub(crate) fn verify_requested_restrictions( if filter_tags.contains(&"schema_issuer_id".to_owned()) && filter_tags.contains(&"schema_issuer_did".to_owned()) { - return Err(err_msg!("Presentation request contains both restrictions for `schema_issuer_id` (new) and `schema_issuer_did` (legacy)")); + return Err(err_msg!( + "Presentation request contains both restrictions for `schema_issuer_id` (new) and `schema_issuer_did` (legacy)" + )); } for (referent, info) in &requested_attrs { @@ -573,22 +587,26 @@ pub(crate) fn process_operator( filter: &Filter, ) -> Result<()> { match restriction_op { - Query::Eq(ref tag_name, ref tag_value) => { + Query::Eq(tag_name, tag_value) => { process_filter(attr_value_map, tag_name, tag_value, filter).map_err(err_map!( "$eq operator validation failed for tag: \"{}\", value: \"{}\"", tag_name, tag_value )) } - Query::Neq(ref tag_name, ref tag_value) => { + Query::Neq(tag_name, tag_value) => { if process_filter(attr_value_map, tag_name, tag_value, filter).is_err() { Ok(()) } else { - Err(err_msg!(ProofRejected, - "$neq operator validation failed for tag: \"{}\", value: \"{}\". Condition was passed.", tag_name, tag_value)) + Err(err_msg!( + ProofRejected, + "$neq operator validation failed for tag: \"{}\", value: \"{}\". Condition was passed.", + tag_name, + tag_value + )) } } - Query::In(ref tag_name, ref tag_values) => { + Query::In(tag_name, tag_values) => { let res = tag_values .iter() .any(|val| process_filter(attr_value_map, tag_name, val, filter).is_ok()); @@ -603,13 +621,13 @@ pub(crate) fn process_operator( )) } } - Query::And(ref operators) => operators + Query::And(operators) => operators .iter() .map(|op| process_operator(attr_value_map, op, filter)) .collect::>>() .map(|_| ()) .map_err(err_map!("$and operator validation failed.")), - Query::Or(ref operators) => { + Query::Or(operators) => { let res = operators .iter() .any(|op| process_operator(attr_value_map, op, filter).is_ok()); @@ -622,7 +640,7 @@ pub(crate) fn process_operator( )) } } - Query::Not(ref operator) => { + Query::Not(operator) => { if process_operator(attr_value_map, operator, filter).is_err() { Ok(()) } else { @@ -644,10 +662,7 @@ fn process_filter( ) -> Result<()> { trace!( "_process_filter: attr_value_map: {:?}, tag: {}, tag_value: {}, filter: {:?}", - attr_value_map, - tag, - tag_value, - filter + attr_value_map, tag, tag_value, filter ); match tag { tag_ @ "schema_id" => precess_filed(tag_, filter.schema_id.to_string(), tag_value), @@ -831,7 +846,9 @@ impl<'a> CLProofVerifier<'a> { >, rev_status_lists: Option<&'a Vec>, ) -> Result> { - let proof_verifier = Verifier::new_proof_verifier()?; + let mut proof_verifier = Verifier::new_proof_verifier()?; + // Require link secrets to be equal + proof_verifier.add_common_attribute("master_secret")?; let non_credential_schema = build_non_credential_schema()?; let revocation_map = build_revocation_registry_map(rev_status_lists)?; Ok(CLProofVerifier { diff --git a/src/services/w3c/credential_conversion.rs b/src/services/w3c/credential_conversion.rs index 9bdbdf21..8fa19d09 100644 --- a/src/services/w3c/credential_conversion.rs +++ b/src/services/w3c/credential_conversion.rs @@ -1,11 +1,11 @@ +use crate::Error; use crate::data_types::issuer_id::IssuerId; +use crate::data_types::w3c::VerifiableCredentialSpecVersion; use crate::data_types::w3c::credential::W3CCredential; use crate::data_types::w3c::credential_attributes::CredentialSubject; use crate::data_types::w3c::proof::{CredentialSignatureProofValue, DataIntegrityProof}; -use crate::data_types::w3c::VerifiableCredentialSpecVersion; use crate::types::Credential; use crate::utils::validation::Validatable; -use crate::Error; /// Convert credential in legacy form into W3C AnonCreds credential form /// @@ -92,8 +92,7 @@ pub fn credential_to_w3c( ) -> Result { trace!( "credential_to_w3c >>> credential: {:?}, issuer_id: {:?}", - credential, - issuer_id + credential, issuer_id ); credential.validate()?; @@ -243,7 +242,7 @@ pub(crate) mod tests { AttributeNames, CredentialDefinitionConfig, CredentialValues, MakeCredentialValues, SignatureType, }; - use crate::{issuer, ErrorKind}; + use crate::{ErrorKind, issuer}; use rstest::*; pub(crate) const ISSUER_ID: &str = "mock:uri"; diff --git a/src/services/w3c/issuer.rs b/src/services/w3c/issuer.rs index 488132d7..2d0393cf 100644 --- a/src/services/w3c/issuer.rs +++ b/src/services/w3c/issuer.rs @@ -1,8 +1,8 @@ use crate::data_types::cred_def::CredentialDefinition; +use crate::data_types::w3c::VerifiableCredentialSpecVersion; use crate::data_types::w3c::credential::W3CCredential; use crate::data_types::w3c::credential_attributes::CredentialSubject; use crate::data_types::w3c::proof::{CredentialSignatureProofValue, DataIntegrityProof}; -use crate::data_types::w3c::VerifiableCredentialSpecVersion; use crate::error::Result; use crate::issuer::CLCredentialIssuer; @@ -90,10 +90,16 @@ pub fn create_credential( revocation_config: Option, version: Option, ) -> Result { - trace!("create_w3c_credential >>> cred_def: {:?}, cred_def_private: {:?}, cred_offer.nonce: {:?}, cred_request: {:?},\ + trace!( + "create_w3c_credential >>> cred_def: {:?}, cred_def_private: {:?}, cred_offer.nonce: {:?}, cred_request: {:?},\ cred_values: {:?}, revocation_config: {:?}, version: {:?}", - cred_def, secret!(&cred_def_private), &cred_offer.nonce, &cred_request, secret!(&raw_credential_values), - revocation_config, version, + cred_def, + secret!(&cred_def_private), + &cred_offer.nonce, + &cred_request, + secret!(&raw_credential_values), + revocation_config, + version, ); let credential_values = raw_credential_values.encode()?; diff --git a/src/services/w3c/prover.rs b/src/services/w3c/prover.rs index 6693af9c..e03601b4 100644 --- a/src/services/w3c/prover.rs +++ b/src/services/w3c/prover.rs @@ -10,11 +10,11 @@ use crate::types::{ }; use crate::utils::validation::Validatable; +use crate::data_types::w3c::VerifiableCredentialSpecVersion; use crate::data_types::w3c::credential_attributes::CredentialSubject; use crate::data_types::w3c::proof::{ CredentialPresentationProofValue, DataIntegrityProof, PresentationProofValue, }; -use crate::data_types::w3c::VerifiableCredentialSpecVersion; use crate::prover::{CLCredentialProver, CLProofBuilder}; use std::collections::HashMap; @@ -99,8 +99,14 @@ pub fn process_credential( cred_def: &CredentialDefinition, rev_reg_def: Option<&RevocationRegistryDefinition>, ) -> Result<()> { - trace!("process_w3c_credential >>> credential: {:?}, cred_request_metadata: {:?}, link_secret: {:?}, cred_def: {:?}, rev_reg_def: {:?}", - w3c_credential, cred_request_metadata, secret!(&link_secret), cred_def, rev_reg_def); + trace!( + "process_w3c_credential >>> credential: {:?}, cred_request_metadata: {:?}, link_secret: {:?}, cred_def: {:?}, rev_reg_def: {:?}", + w3c_credential, + cred_request_metadata, + secret!(&link_secret), + cred_def, + rev_reg_def + ); let cred_values = w3c_credential.credential_subject.encode()?; @@ -164,10 +170,11 @@ pub fn create_presentation( let credential_values: CredentialValues = credential.credential_subject.encode()?; let proof = credential.get_credential_signature_proof()?; + let proof_link_secret = present.link_secret.unwrap_or(link_secret); proof_builder.add_sub_proof( &credential_values, &proof.signature, - link_secret, + proof_link_secret, present, &proof.schema_id, &proof.cred_def_id, diff --git a/src/services/w3c/types.rs b/src/services/w3c/types.rs index 10c3b5e7..eafc5615 100644 --- a/src/services/w3c/types.rs +++ b/src/services/w3c/types.rs @@ -13,7 +13,7 @@ impl MakeCredentialAttributes { CredentialAttributeValue::String(string_value) }; - self.0 .0.insert(name.into(), value); + self.0.0.insert(name.into(), value); } } diff --git a/src/services/w3c/verifier.rs b/src/services/w3c/verifier.rs index 8a6d871a..5dac9ad1 100644 --- a/src/services/w3c/verifier.rs +++ b/src/services/w3c/verifier.rs @@ -14,8 +14,8 @@ use crate::error::Result; use crate::services::helpers::{encode_credential_attribute, get_requested_non_revoked_interval}; use crate::types::{PresentationRequest, RevocationRegistryDefinition, RevocationStatusList}; use crate::utils::query::Query; +use crate::verifier::{CLProofVerifier, verify_revealed_attribute_value}; use crate::verifier::{gather_filter_info, process_operator}; -use crate::verifier::{verify_revealed_attribute_value, CLProofVerifier}; use anoncreds_clsignatures::{Proof, SubProof}; use std::collections::HashMap; @@ -31,8 +31,10 @@ pub fn verify_presentation( &HashMap>, >, ) -> Result { - trace!("verify >>> verify_w3c_presentation: {:?}, pres_req: {:?}, schemas: {:?}, cred_defs: {:?}, rev_reg_defs: {:?} rev_status_lists: {:?}", - presentation, pres_req, schemas, cred_defs, rev_reg_defs, rev_status_lists); + trace!( + "verify >>> verify_w3c_presentation: {:?}, pres_req: {:?}, schemas: {:?}, cred_defs: {:?}, rev_reg_defs: {:?} rev_status_lists: {:?}", + presentation, pres_req, schemas, cred_defs, rev_reg_defs, rev_status_lists + ); presentation.validate()?; @@ -395,17 +397,17 @@ fn check_request_data( #[cfg(test)] pub(crate) mod tests { use super::*; + use crate::ErrorKind; use crate::data_types::nonce::Nonce; use crate::data_types::pres_request::{AttributeInfo, PredicateTypes}; use crate::data_types::w3c::credential_attributes::CredentialSubject; + use crate::data_types::w3c::proof::DataIntegrityProof; use crate::data_types::w3c::proof::tests::{ credential_pres_proof_value, presentation_proof_value, }; - use crate::data_types::w3c::proof::DataIntegrityProof; use crate::w3c::credential_conversion::tests::{ cred_def_id, credential_definition, issuer_id, schema, schema_id, }; - use crate::ErrorKind; use rstest::*; const PROOF_TIMESTAMP_FROM: u64 = 40; @@ -572,8 +574,8 @@ pub(crate) mod tests { } #[fixture] - fn _presentation_request_with_case_insensitive_attribute_and_predicate( - ) -> PresentationRequestPayload { + fn _presentation_request_with_case_insensitive_attribute_and_predicate() + -> PresentationRequestPayload { PresentationRequestPayload { requested_attributes: HashMap::from([ ( diff --git a/src/utils/base64.rs b/src/utils/base64.rs index 457d3daf..1954228f 100644 --- a/src/utils/base64.rs +++ b/src/utils/base64.rs @@ -1,4 +1,4 @@ -use base64::{engine, Engine}; +use base64::{Engine, engine}; use crate::Error; diff --git a/src/utils/hash.rs b/src/utils/hash.rs deleted file mode 100644 index 525a0b12..00000000 --- a/src/utils/hash.rs +++ /dev/null @@ -1,122 +0,0 @@ -pub use sha2::Digest; - -use crate::error::ValidationError; - -/// Derive a new hash type -#[macro_export] -macro_rules! hash_type { - ($modname:ident, $digest:path, $doc:expr) => { - #[doc=$doc] - #[allow(non_snake_case)] - pub mod $modname { - #[cfg(test)] - use once_cell::sync::Lazy; - - use sha2::Digest; - - pub type DigestType = $digest; - - pub fn digest>(input: V) -> Vec { - DigestType::digest(input.as_ref()).to_vec() - } - - #[cfg(test)] - pub fn digest_empty() -> &'static [u8] { - static EMPTY_HASH_BYTES: Lazy> = Lazy::new(|| digest(&[])); - EMPTY_HASH_BYTES.as_slice() - } - - #[cfg(test)] - pub fn output_size() -> usize { - DigestType::output_size() - } - } - }; -} - -hash_type!(SHA256, sha2::Sha256, "Sha256 hash"); - -/// A trait for producing hashes of merkle tree leaves and nodes -pub trait TreeHash { - fn hash_leaf(leaf: &T) -> Result, ValidationError> - where - T: Hashable; - - fn hash_nodes(left: &T, right: &T) -> Result, ValidationError> - where - T: Hashable; -} - -impl TreeHash for H { - fn hash_leaf(leaf: &T) -> Result, ValidationError> - where - T: Hashable, - { - let mut ctx = Self::new(); - ctx.update([0x00]); - leaf.update_context(&mut ctx)?; - Ok(ctx.finalize().to_vec()) - } - - fn hash_nodes(left: &T, right: &T) -> Result, ValidationError> - where - T: Hashable, - { - let mut ctx = Self::new(); - ctx.update([0x01]); - left.update_context(&mut ctx)?; - right.update_context(&mut ctx)?; - Ok(ctx.finalize().to_vec()) - } -} - -/// The type of values stored in a `MerkleTree` must implement -/// this trait, in order for them to be able to be fed -/// to a Ring `Context` when computing the hash of a leaf. -/// -/// A default instance for types that already implements -/// `AsRef<[u8]>` is provided. -/// -/// ## Example -/// -/// Here is an example of how to implement `Hashable` for a type -/// that does not (or cannot) implement `AsRef<[u8]>`: -/// -/// ```ignore -/// impl Hashable for PublicKey { -/// fn update_context(&self, context: &mut Hasher) -> Result<(), CommonError> { -/// let bytes: Vec = self.to_bytes(); -/// Ok(context.update(&bytes)?) -/// } -/// } -/// ``` -pub trait Hashable { - /// Update the given `context` with `self`. - /// - /// See `openssl::hash::Hasher::update` for more information. - fn update_context(&self, context: &mut D) -> Result<(), ValidationError>; -} - -impl> Hashable for T { - fn update_context(&self, context: &mut D) -> Result<(), ValidationError> { - context.update(self.as_ref()); - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn hash_check_sha256() { - assert_eq!(SHA256::output_size(), 32); - assert_eq!( - SHA256::digest_empty(), - &[ - 227, 176, 196, 66, 152, 252, 28, 20, 154, 251, 244, 200, 153, 111, 185, 36, 39, - 174, 65, 228, 100, 155, 147, 76, 164, 149, 153, 27, 120, 82, 184, 85, - ] - ); - } -} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 9931f1d0..461c9689 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -6,8 +6,6 @@ pub mod base58; #[cfg(feature = "w3c")] pub mod base64; -pub mod hash; - pub mod query; pub mod msg_pack; diff --git a/src/utils/msg_pack.rs b/src/utils/msg_pack.rs index fd53dde5..ba5f7fa5 100644 --- a/src/utils/msg_pack.rs +++ b/src/utils/msg_pack.rs @@ -1,5 +1,5 @@ -use serde::de::DeserializeOwned; use serde::Serialize; +use serde::de::DeserializeOwned; use crate::Result; diff --git a/src/utils/query.rs b/src/utils/query.rs index e5cf5684..a6b9e2d8 100644 --- a/src/utils/query.rs +++ b/src/utils/query.rs @@ -1,6 +1,6 @@ use serde::ser::{Serialize, Serializer}; -use serde::{de, Deserialize, Deserializer}; -use serde_json::{self, json, Value as JsonValue}; +use serde::{Deserialize, Deserializer, de}; +use serde_json::{self, Value as JsonValue, json}; use std::string; /// An abstract query representation over a key and value type @@ -246,18 +246,18 @@ where { fn to_value(&self) -> JsonValue { match self { - Self::Eq(ref tag_name, ref tag_value) => json!({ tag_name: tag_value }), - Self::Neq(ref tag_name, ref tag_value) => json!({tag_name: {"$neq": tag_value}}), - Self::Gt(ref tag_name, ref tag_value) => json!({tag_name: {"$gt": tag_value}}), - Self::Gte(ref tag_name, ref tag_value) => json!({tag_name: {"$gte": tag_value}}), - Self::Lt(ref tag_name, ref tag_value) => json!({tag_name: {"$lt": tag_value}}), - Self::Lte(ref tag_name, ref tag_value) => json!({tag_name: {"$lte": tag_value}}), - Self::Like(ref tag_name, ref tag_value) => json!({tag_name: {"$like": tag_value}}), - Self::In(ref tag_name, ref tag_values) => json!({tag_name: {"$in":tag_values}}), - Self::Exist(ref tag_names) => { + Self::Eq(tag_name, tag_value) => json!({ tag_name: tag_value }), + Self::Neq(tag_name, tag_value) => json!({tag_name: {"$neq": tag_value}}), + Self::Gt(tag_name, tag_value) => json!({tag_name: {"$gt": tag_value}}), + Self::Gte(tag_name, tag_value) => json!({tag_name: {"$gte": tag_value}}), + Self::Lt(tag_name, tag_value) => json!({tag_name: {"$lt": tag_value}}), + Self::Lte(tag_name, tag_value) => json!({tag_name: {"$lte": tag_value}}), + Self::Like(tag_name, tag_value) => json!({tag_name: {"$like": tag_value}}), + Self::In(tag_name, tag_values) => json!({tag_name: {"$in":tag_values}}), + Self::Exist(tag_names) => { json!({ "$exist": tag_names.iter().map(Into::into).collect::>() }) } - Self::And(ref queries) => { + Self::And(queries) => { if queries.is_empty() { json!({}) } else { @@ -266,7 +266,7 @@ where }) } } - Self::Or(ref queries) => { + Self::Or(queries) => { if queries.is_empty() { json!({}) } else { @@ -275,7 +275,7 @@ where }) } } - Self::Not(ref query) => json!({"$not": query.to_value()}), + Self::Not(query) => json!({"$not": query.to_value()}), } } } @@ -413,12 +413,12 @@ fn parse_single_operator( #[cfg(test)] mod tests { use super::*; - use rand::distributions::Alphanumeric; - use rand::{thread_rng, Rng}; + use rand::distr::Alphanumeric; + use rand::{Rng, rng}; use serde_json::json; fn _random_string(len: usize) -> String { - String::from_utf8(thread_rng().sample_iter(&Alphanumeric).take(len).collect()).unwrap() + String::from_utf8(rng().sample_iter(&Alphanumeric).take(len).collect()).unwrap() } /// parse diff --git a/src/utils/validation.rs b/src/utils/validation.rs index 44bf97de..930ea0c8 100644 --- a/src/utils/validation.rs +++ b/src/utils/validation.rs @@ -62,18 +62,26 @@ mod test_identifiers { let valid_legacy_did_identifier = "DXoTtQJNtXtiwWaZAK3rB1"; assert!(URI_IDENTIFIER.captures(valid_uri_identifier).is_some()); - assert!(LEGACY_SCHEMA_IDENTIFIER - .captures(valid_legacy_schema_identifier) - .is_some()); - assert!(LEGACY_CRED_DEF_IDENTIFIER - .captures(valid_legacy_cred_def_identifier) - .is_some()); - assert!(LEGACY_REV_REG_DEF_IDENTIFIER - .captures(valid_legacy_rev_reg_def_identifier) - .is_some()); - assert!(LEGACY_DID_IDENTIFIER - .captures(valid_legacy_did_identifier) - .is_some()); + assert!( + LEGACY_SCHEMA_IDENTIFIER + .captures(valid_legacy_schema_identifier) + .is_some() + ); + assert!( + LEGACY_CRED_DEF_IDENTIFIER + .captures(valid_legacy_cred_def_identifier) + .is_some() + ); + assert!( + LEGACY_REV_REG_DEF_IDENTIFIER + .captures(valid_legacy_rev_reg_def_identifier) + .is_some() + ); + assert!( + LEGACY_DID_IDENTIFIER + .captures(valid_legacy_did_identifier) + .is_some() + ); } #[test] @@ -85,25 +93,37 @@ mod test_identifiers { let invalid_legacy_did_identifier = "invalid:id"; assert!(URI_IDENTIFIER.captures(invalid_uri_identifier).is_none()); - assert!(LEGACY_DID_IDENTIFIER - .captures(invalid_legacy_schema_identifier) - .is_none()); - assert!(LEGACY_CRED_DEF_IDENTIFIER - .captures(invalid_legacy_cred_def_identifier) - .is_none()); - assert!(LEGACY_REV_REG_DEF_IDENTIFIER - .captures(invalid_legacy_rev_reg_def_identifier) - .is_none()); - assert!(LEGACY_DID_IDENTIFIER - .captures(invalid_legacy_did_identifier) - .is_none()); + assert!( + LEGACY_DID_IDENTIFIER + .captures(invalid_legacy_schema_identifier) + .is_none() + ); + assert!( + LEGACY_CRED_DEF_IDENTIFIER + .captures(invalid_legacy_cred_def_identifier) + .is_none() + ); + assert!( + LEGACY_REV_REG_DEF_IDENTIFIER + .captures(invalid_legacy_rev_reg_def_identifier) + .is_none() + ); + assert!( + LEGACY_DID_IDENTIFIER + .captures(invalid_legacy_did_identifier) + .is_none() + ); - assert!(LEGACY_SCHEMA_IDENTIFIER - .captures("DXoTtQJNtXtiwWaZAK3rB1:3:example:1.0") - .is_none()); - assert!(LEGACY_CRED_DEF_IDENTIFIER - .captures("DXoTtQJNtXtiwWaZAK3rB1:4:CL:98153:default") - .is_none()); + assert!( + LEGACY_SCHEMA_IDENTIFIER + .captures("DXoTtQJNtXtiwWaZAK3rB1:3:example:1.0") + .is_none() + ); + assert!( + LEGACY_CRED_DEF_IDENTIFIER + .captures("DXoTtQJNtXtiwWaZAK3rB1:4:CL:98153:default") + .is_none() + ); assert!(LEGACY_REV_REG_DEF_IDENTIFIER .captures("DXoTtQJNtXtiwWaZAK3rB1:5:DXoTtQJNtXtiwWaZAK3rB1:3:CL:288602:example:CL_ACCUM:default") .is_none()); diff --git a/tests/anoncreds_demos.rs b/tests/anoncreds_demos.rs index f48e93fa..94b83442 100644 --- a/tests/anoncreds_demos.rs +++ b/tests/anoncreds_demos.rs @@ -1,6 +1,6 @@ -use anoncreds::data_types::w3c::credential_attributes::CredentialAttributeValue; use anoncreds::data_types::w3c::VerifiableCredentialSpecVersion; -use anoncreds::verifier; +use anoncreds::data_types::w3c::credential_attributes::CredentialAttributeValue; +use anoncreds::{verifier, w3c}; use rstest::rstest; use serde_json::json; use std::collections::{BTreeSet, HashMap}; @@ -727,6 +727,196 @@ fn anoncreds_demo_proof_does_not_verify_with_wrong_attr_and_predicates( assert!(valid.is_err()) } +#[rstest] +#[case(CredentialFormat::Legacy, PresentationFormat::Legacy)] +#[case(CredentialFormat::W3C, PresentationFormat::W3C)] +fn anoncreds_demo_proof_does_not_verify_with_multiple_link_secrets( + #[case] credential_format: CredentialFormat, + #[case] presentation_format: PresentationFormat, +) { + // Create pseudo ledger and wallets + + use anoncreds::{prover, types::PresentCredentials}; + let mut ledger = Ledger::default(); + let mut issuer_wallet = IssuerWallet::default(); + let mut prover_wallet_1 = ProverWallet::default(); + let mut prover_wallet_2 = ProverWallet::default(); + let verifier_wallet = VerifierWallet::default(); + + // Create schema + let (gvt_schema, gvt_schema_id) = issuer_wallet.create_schema(&mut ledger, GVT_CRED); + + // Create credential definition + let (gvt_cred_def, gvt_cred_def_id) = + issuer_wallet.create_cred_def(&mut ledger, &gvt_schema, false); + + // Issuer creates a Credential Offer + let cred_offer = issuer_wallet.create_credential_offer(&gvt_schema_id, &gvt_cred_def_id); + + // Prover creates a Credential Request + let (cred_request, cred_request_metadata) = + prover_wallet_1.create_credential_request(&gvt_cred_def, &cred_offer); + + // Issuer creates a credential + let cred_values = fixtures::credential_values(GVT_CRED); + let issue_cred = issuer_wallet.create_credential( + &credential_format, + &gvt_cred_def_id, + &cred_offer, + &cred_request, + cred_values.into(), + None, + None, + None, + None, + ); + + // Prover receives the credential and processes it + let mut recv_cred = issue_cred; + prover_wallet_1.store_credential( + GVT_CRED, + &mut recv_cred, + &cred_request_metadata, + &gvt_cred_def, + None, + ); + + // Prover creates a second Credential Request + let (cred_request, cred_request_metadata) = + prover_wallet_2.create_credential_request(&gvt_cred_def, &cred_offer); + + // Issuer creates a credential + let cred_values = fixtures::credential_values(GVT_CRED); + let issue_cred = issuer_wallet.create_credential( + &credential_format, + &gvt_cred_def_id, + &cred_offer, + &cred_request, + cred_values.into(), + None, + None, + None, + None, + ); + + // Prover receives the second credential and processes it, bound to a second link secret + let mut recv_cred = issue_cred; + prover_wallet_2.store_credential( + GVT_CRED, + &mut recv_cred, + &cred_request_metadata, + &gvt_cred_def, + None, + ); + + // Verifier creates a presentation request + let nonce = verifier_wallet.generate_nonce(); + let pres_request = serde_json::from_value(json!({ + "nonce": nonce, + "name":"pres_req_1", + "version":"0.1", + "requested_attributes":{ + "attr1_referent":{ + "name": "name" + }, + "attr2_referent":{ + "name": "height" + } + } + })) + .expect("Error creating proof request"); + + let schemas = ledger.resolve_schemas(vec![&gvt_schema_id]); + let cred_defs = ledger.resolve_cred_defs(vec![&gvt_cred_def_id]); + + // First referent from first prover wallet + let present_credentials_1 = vec![CredentialToPresent { + id: GVT_CRED.to_string(), + attributes: vec![PresentAttribute { + referent: "attr1_referent".to_string(), + form: PresentAttributeForm::RevealedAttribute, + }], + }]; + // Second referent from second prover wallet + let present_credentials_2 = vec![CredentialToPresent { + id: GVT_CRED.to_string(), + attributes: vec![PresentAttribute { + referent: "attr2_referent".to_string(), + form: PresentAttributeForm::RevealedAttribute, + }], + }]; + + // Prover creates presentation + let presentation = match presentation_format { + PresentationFormat::Legacy => { + // Prover creates presentation with two different link secrets + let mut presented = PresentCredentials::default(); + prover_wallet_1.prepare_credentials_to_present( + &mut presented, + &prover_wallet_1.credentials, + &present_credentials_1, + ); + prover_wallet_2.prepare_credentials_to_present( + &mut presented, + &prover_wallet_2.credentials, + &present_credentials_2, + ); + prover::create_presentation( + &pres_request, + presented, + None, + // This link secret value is superseded by the ones assigned to each credential in 'presented' + &prover_wallet_1.link_secret, + &schemas, + &cred_defs, + ) + .expect("Error creating presentation") + .into() + } + PresentationFormat::W3C => { + // Prover creates presentation with two different link secrets + let mut presented = PresentCredentials::default(); + prover_wallet_1.prepare_credentials_to_present( + &mut presented, + &prover_wallet_1.w3c_credentials, + &present_credentials_1, + ); + prover_wallet_2.prepare_credentials_to_present( + &mut presented, + &prover_wallet_2.w3c_credentials, + &present_credentials_2, + ); + + w3c::prover::create_presentation( + &pres_request, + presented, + // This link secret value is superseded by the ones assigned to each credential in 'presented' + &prover_wallet_1.link_secret, + &schemas, + &cred_defs, + None, + ) + .expect("Error creating presentation") + .into() + } + }; + + let valid = verifier_wallet.verify_presentation( + &presentation, + &pres_request, + &schemas, + &cred_defs, + None, + None, + None, + ); + + let err = valid.expect_err("Proof verification should fail"); + assert!(err.0.contains( + "Blinded value for common attribute 'master_secret' different across sub proofs" + )); +} + #[rstest] #[case(CredentialFormat::Legacy, PresentationFormat::Legacy)] #[case(CredentialFormat::W3C, PresentationFormat::W3C)] @@ -2996,8 +3186,8 @@ fn anoncreds_demo_works_for_issue_legacy_credential_convert_into_w3c_and_present } #[test] -fn anoncreds_demo_works_for_issue_w3c_credential_convert_into_legacy_and_present_legacy_presentation( -) { +fn anoncreds_demo_works_for_issue_w3c_credential_convert_into_legacy_and_present_legacy_presentation() + { // Create pseudo ledger and wallets let mut ledger = Ledger::default(); let mut issuer_wallet = IssuerWallet::default(); @@ -3131,8 +3321,8 @@ fn anoncreds_demo_works_for_issue_w3c_credential_convert_into_legacy_and_present } #[test] -fn anoncreds_demo_works_for_issue_two_credentials_in_different_forms_and_present_compound_w3c_presentation( -) { +fn anoncreds_demo_works_for_issue_two_credentials_in_different_forms_and_present_compound_w3c_presentation() + { // Create pseudo ledger and wallets let mut ledger = Ledger::default(); let mut issuer_1_wallet = IssuerWallet::default(); diff --git a/tests/utils/mock.rs b/tests/utils/mock.rs index f756c19c..fe8b10bd 100644 --- a/tests/utils/mock.rs +++ b/tests/utils/mock.rs @@ -6,14 +6,14 @@ use std::{ fs::create_dir, }; -use crate::utils::{fixtures, VerifierWallet}; +use crate::utils::{VerifierWallet, fixtures}; use anoncreds::data_types::nonce::Nonce; +use anoncreds::data_types::w3c::VerifiableCredentialSpecVersion; use anoncreds::data_types::w3c::credential::W3CCredential; use anoncreds::data_types::w3c::credential_attributes::{ CredentialAttributeValue, CredentialSubject, }; use anoncreds::data_types::w3c::presentation::W3CPresentation; -use anoncreds::data_types::w3c::VerifiableCredentialSpecVersion; use anoncreds::types::{ CredentialRequestMetadata, CredentialRevocationState, CredentialValues, RevocationRegistryDefinition, RevocationStatusList, @@ -39,7 +39,7 @@ use anoncreds::{ }; #[derive(Debug)] -pub struct TestError(String); +pub struct TestError(pub String); #[derive(Debug, Clone, PartialEq, Eq)] pub enum CredentialFormat { @@ -65,6 +65,18 @@ pub enum Presentations { W3C(W3CPresentation), } +impl From for Presentations { + fn from(value: Presentation) -> Self { + Presentations::Legacy(value) + } +} + +impl From for Presentations { + fn from(value: W3CPresentation) -> Self { + Presentations::W3C(value) + } +} + impl Credentials { pub fn legacy(&self) -> &Credential { match self { @@ -830,7 +842,7 @@ impl<'a> ProverWallet<'a> { rev_reg_def: Option<&RevocationRegistryDefinition>, ) { match credential { - Credentials::Legacy(ref mut credential) => { + Credentials::Legacy(credential) => { prover::process_credential( credential, cred_request_metadata, @@ -842,7 +854,7 @@ impl<'a> ProverWallet<'a> { self.credentials .insert(id.to_string(), credential.try_clone().unwrap()); } - Credentials::W3C(ref mut credential) => { + Credentials::W3C(credential) => { w3c::prover::process_credential( credential, cred_request_metadata, @@ -879,11 +891,10 @@ impl<'a> ProverWallet<'a> { pub fn prepare_credentials_to_present<'b, T: RevocableCredential>( &'b self, + present: &mut PresentCredentials<'b, T>, credentials: &'b HashMap, - present_credentials: &Vec, - ) -> PresentCredentials<'b, T> { - let mut present = PresentCredentials::default(); - + present_credentials: &[CredentialToPresent], + ) { for present_credential in present_credentials.iter() { let credential = credentials .get(&present_credential.id) @@ -896,6 +907,8 @@ impl<'a> ProverWallet<'a> { }; let mut cred = present.add_credential(credential, *timestamp, rev_state.as_ref()); + cred.set_link_secret(&self.link_secret); + for data in present_credential.attributes.iter() { match data.form { PresentAttributeForm::RevealedAttribute => { @@ -910,7 +923,6 @@ impl<'a> ProverWallet<'a> { } } } - present } pub fn create_presentation( @@ -925,8 +937,12 @@ impl<'a> ProverWallet<'a> { ) -> Presentations { match format { PresentationFormat::Legacy => { - let present = - self.prepare_credentials_to_present(&self.credentials, present_credentials); + let mut present = PresentCredentials::default(); + self.prepare_credentials_to_present( + &mut present, + &self.credentials, + present_credentials, + ); let presentation = prover::create_presentation( pres_request, present, @@ -936,11 +952,15 @@ impl<'a> ProverWallet<'a> { cred_defs, ) .expect("Error creating presentation"); - Presentations::Legacy(presentation) + presentation.into() } PresentationFormat::W3C => { - let present = - self.prepare_credentials_to_present(&self.w3c_credentials, present_credentials); + let mut present = PresentCredentials::default(); + self.prepare_credentials_to_present( + &mut present, + &self.w3c_credentials, + present_credentials, + ); let presentation = w3c::prover::create_presentation( pres_request, present, @@ -950,7 +970,7 @@ impl<'a> ProverWallet<'a> { version, ) .expect("Error creating presentation"); - Presentations::W3C(presentation) + presentation.into() } } }