Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revocable checks #64

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions anoncreds/src/data_types/anoncreds/rev_reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ impl RevocationStatusList {
revoked: Option<BTreeSet<u32>>,
timestamp: Option<u64>,
) -> Result<(), error::Error> {
// only update if input is Some
if let Some(reg) = registry {
self.registry = Some(reg)
};
Expand Down Expand Up @@ -120,6 +121,7 @@ impl RevocationStatusList {
*bit = true;
}
}
// only update if input is Some
if let Some(t) = timestamp {
self.timestamp = Some(t);
}
Expand Down Expand Up @@ -195,6 +197,28 @@ pub mod serde_revocation_list {
}
}

// NonRevocationProof warnings:
// - timestamps_out_of_range: all timestamps used for rev_state that are o.o.r
// this can be for request / attribute / predicate level time intervals
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct NonRevProofWarnings {
pub timestamps_out_of_range: Option<Vec<String>>,
}

impl NonRevProofWarnings {
pub fn new(referents: Vec<String>) -> Self {
if referents.is_empty() {
Self {
timestamps_out_of_range: None,
}
} else {
Self {
timestamps_out_of_range: Some(referents),
}
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
3 changes: 0 additions & 3 deletions anoncreds/src/ffi/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ pub struct FfiCredRevInfo<'a> {
struct RevocationConfig {
reg_def: AnonCredsObject,
reg_def_private: AnonCredsObject,
registry: AnonCredsObject,
reg_idx: u32,
tails_path: String,
}
Expand All @@ -40,7 +39,6 @@ impl RevocationConfig {
Ok(CredentialRevocationConfig {
reg_def: self.reg_def.cast_ref()?,
reg_def_private: self.reg_def_private.cast_ref()?,
registry: self.registry.cast_ref()?,
registry_idx: self.reg_idx,
tails_reader: TailsFileReader::new_tails_reader(self.tails_path.as_str()),
})
Expand Down Expand Up @@ -112,7 +110,6 @@ pub extern "C" fn anoncreds_create_credential(
Some(RevocationConfig {
reg_def: revocation.reg_def.load()?,
reg_def_private: revocation.reg_def_private.load()?,
registry: revocation.registry.load()?,
reg_idx: revocation
.reg_idx
.try_into()
Expand Down
13 changes: 11 additions & 2 deletions anoncreds/src/ffi/presentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::error::{catch_error, ErrorCode};
use super::object::{AnonCredsObject, AnonCredsObjectList, ObjectHandle};
use super::util::{FfiList, FfiStrList};
use crate::data_types::anoncreds::cred_def::{CredentialDefinition, CredentialDefinitionId};
use crate::data_types::anoncreds::rev_reg::RevocationRegistryId;
use crate::data_types::anoncreds::rev_reg::{NonRevProofWarnings, RevocationRegistryId};
use crate::data_types::anoncreds::rev_reg_def::{
RevocationRegistryDefinition, RevocationRegistryDefinitionId,
};
Expand All @@ -21,6 +21,12 @@ use crate::services::{
impl_anoncreds_object!(Presentation, "Presentation");
impl_anoncreds_object_from_json!(Presentation, anoncreds_presentation_from_json);

impl_anoncreds_object!(NonRevProofWarnings, "NonRevProofWarnings");
impl_anoncreds_object_from_json!(
NonRevProofWarnings,
anoncreds_non_rev_proof_warnings_from_json
);

#[derive(Debug)]
#[repr(C)]
pub struct FfiCredentialEntry {
Expand Down Expand Up @@ -230,6 +236,7 @@ pub extern "C" fn anoncreds_verify_presentation(
rev_reg_def_ids: FfiStrList,
rev_reg_entries: FfiList<FfiRevocationEntry>,
result_p: *mut i8,
non_rev_proof_warning_p: *mut ObjectHandle,
) -> ErrorCode {
catch_error(|| {
if schemas.len() != schema_ids.len() {
Expand Down Expand Up @@ -301,7 +308,7 @@ pub extern "C" fn anoncreds_verify_presentation(
&rev_reg_def_identifiers,
)?;

let verify = verify_presentation(
let (verify, nrp) = verify_presentation(
presentation.load()?.cast_ref()?,
pres_req.load()?.cast_ref()?,
&schemas,
Expand All @@ -310,6 +317,8 @@ pub extern "C" fn anoncreds_verify_presentation(
Some(&rev_regs),
)?;
unsafe { *result_p = verify as i8 };
let nrp = ObjectHandle::create(nrp)?;
unsafe { *non_rev_proof_warning_p = nrp };
Ok(())
})
}
102 changes: 53 additions & 49 deletions anoncreds/src/services/issuer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use std::collections::{BTreeSet, HashSet};
use std::convert::{From, Into};
use std::iter::FromIterator;

use indy_utils::{Validatable, ValidationError};
Expand Down Expand Up @@ -219,61 +218,60 @@ pub fn create_revocation_status_list(
)
}

/// Update the timestamp only without changing any actual state
pub fn update_revocation_status_list_timestamp_only(
timestamp: u64,
current_list: &RevocationStatusList,
) -> RevocationStatusList {
let mut list = current_list.clone();
// this does not error as only timestamp is updated
list.update(None, None, None, Some(timestamp)).unwrap();
list
}
/// Update Revocation Status List
/// - if `rev_reg_def` is `Some`: updates will be made to the accumulator and status_list bitvec
/// according to the `BTreeSet`
/// - if `rev_reg_def` is `None`: only the timestamp will be updated
/// - if `timestamp` is `None`: the timestamp is not updated
pub fn update_revocation_status_list(
timestamp: Option<u64>,
issued: Option<BTreeSet<u32>>,
revoked: Option<BTreeSet<u32>>,
rev_reg_def: Option<&RevocationRegistryDefinition>,
rev_reg_def: &RevocationRegistryDefinition,
current_list: &RevocationStatusList,
) -> Result<RevocationStatusList> {
let mut new_list = current_list.clone();
if let Some(rev_reg_def) = rev_reg_def {
let issued = issued.map(|i_list| {
BTreeSet::from_iter(
i_list
.into_iter()
.filter(|&i| current_list.get(i as usize).unwrap_or(false)),
)
});

let revoked = revoked.map(|r_list| {
BTreeSet::from_iter(
r_list
.into_iter()
.filter(|&i| !current_list.get(i as usize).unwrap_or(true)),
)
});

let rev_reg_opt: Option<ursa::cl::RevocationRegistry> = current_list.into();
let mut rev_reg = rev_reg_opt.ok_or_else(|| {
Error::from_msg(
ErrorKind::Unexpected,
"Require Accumulator Value to update Rev Status List",
)
})?;
let tails_reader = TailsFileReader::new_tails_reader(&rev_reg_def.value.tails_location);
let max_cred_num = rev_reg_def.value.max_cred_num;
let issued = issued.map(|i_list| {
BTreeSet::from_iter(
i_list
.into_iter()
.filter(|&i| current_list.get(i as usize).unwrap_or(false)),
)
});

let revoked = revoked.map(|r_list| {
BTreeSet::from_iter(
r_list
.into_iter()
.filter(|&i| !current_list.get(i as usize).unwrap_or(true)),
)
});

let rev_reg_opt: Option<ursa::cl::RevocationRegistry> = current_list.into();
let mut rev_reg = rev_reg_opt.ok_or_else(|| {
Error::from_msg(
ErrorKind::Unexpected,
"Require Accumulator Value to update Rev Status List",
)
})?;
let tails_reader = TailsFileReader::new_tails_reader(&rev_reg_def.value.tails_location);
let max_cred_num = rev_reg_def.value.max_cred_num;

CryptoIssuer::update_revocation_registry(
&mut rev_reg,
max_cred_num,
issued.clone().unwrap_or_default(),
revoked.clone().unwrap_or_default(),
&tails_reader,
)?;
new_list.update(Some(rev_reg), issued, revoked, timestamp)?;
} else if timestamp.is_some() {
new_list.update(None, None, None, timestamp)?;
} else {
return Err(err_msg!(
Unexpected,
"Either timestamp or Revocation Registry Definition must be provided"
));
}
CryptoIssuer::update_revocation_registry(
&mut rev_reg,
max_cred_num,
issued.clone().unwrap_or_default(),
revoked.clone().unwrap_or_default(),
&tails_reader,
)?;
new_list.update(Some(rev_reg), issued, revoked, timestamp)?;

Ok(new_list)
}
Expand Down Expand Up @@ -332,7 +330,13 @@ pub fn create_credential(
match (revocation_config, rev_status_list) {
(Some(revocation_config), Some(rev_status_list)) => {
let rev_reg_def = &revocation_config.reg_def.value;
let mut rev_reg = revocation_config.registry.value.clone();
let rev_reg: Option<ursa::cl::RevocationRegistry> = rev_status_list.into();
let mut rev_reg = rev_reg.ok_or_else(|| {
err_msg!(
Unexpected,
"RevocationStatusList should have accumulator value"
)
})?;

let status = rev_status_list
.get(revocation_config.registry_idx as usize)
Expand Down Expand Up @@ -423,7 +427,7 @@ pub fn create_credential(
values: cred_values,
signature: credential_signature,
signature_correctness_proof,
rev_reg: rev_reg.clone(),
rev_reg,
witness,
};

Expand Down
28 changes: 22 additions & 6 deletions anoncreds/src/services/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ use crate::error::{Error, Result};
use crate::services::helpers::*;
use crate::ursa::cl::{
issuer::Issuer as CryptoIssuer, prover::Prover as CryptoProver,
verifier::Verifier as CryptoVerifier, CredentialPublicKey, RevocationRegistryDelta,
SubProofRequest, Witness,
verifier::Verifier as CryptoVerifier, CredentialPublicKey,
RevocationRegistry as CryptoRevocationRegistry, RevocationRegistryDelta, SubProofRequest,
Witness,
};
use indy_utils::Validatable;

Expand Down Expand Up @@ -246,6 +247,25 @@ pub fn create_presentation(
Ok(full_proof)
}

pub fn create_or_update_revocation_state_with_witness(
witness: Witness,
revocation_status_list: &RevocationStatusList,
timestamp: u64,
) -> Result<CredentialRevocationState> {
let rev_reg = <&RevocationStatusList as Into<Option<CryptoRevocationRegistry>>>::into(
revocation_status_list,
)
.ok_or_else(|| err_msg!(Unexpected, "Revocation Status List must have accum value"))?;

Ok(CredentialRevocationState {
witness,
rev_reg,
timestamp,
})
}

// This can be done by anyone, allowing prover to offload this task
// The tails_path here is used instead of tails_location in `revoc_reg_def` so prover can provide it
pub fn create_or_update_revocation_state(
tails_path: &str,
revoc_reg_def: &RevocationRegistryDefinition,
Expand Down Expand Up @@ -317,10 +337,6 @@ pub fn create_or_update_revocation_state(
&mut issued,
&mut revoked,
);
let rev_reg: Option<ursa::cl::RevocationRegistry> = rev_status_list.into();
let rev_reg = rev_reg.ok_or_else(|| {
err_msg!("revocation registry is not inside the revocation status list")
})?;
let rev_reg_delta = RevocationRegistryDelta::from_parts(None, &rev_reg, &issued, &revoked);
Witness::new(
rev_reg_idx,
Expand Down
5 changes: 1 addition & 4 deletions anoncreds/src/services/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,6 @@ impl Validatable for CredentialRevocationState {
pub struct CredentialRevocationConfig<'a> {
pub reg_def: &'a RevocationRegistryDefinition,
pub reg_def_private: &'a RevocationRegistryDefinitionPrivate,
// TODO remove this!
pub registry: &'a RevocationRegistry,
pub registry_idx: u32,
pub tails_reader: TailsReader,
}
Expand All @@ -227,10 +225,9 @@ impl<'a> std::fmt::Debug for CredentialRevocationConfig<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"CredentialRevocationConfig {{ reg_def: {:?}, private: {:?}, registry: {:?}, idx: {}, reader: {:?} }}",
"CredentialRevocationConfig {{ reg_def: {:?}, private: {:?}, idx: {}, reader: {:?} }}",
self.reg_def,
secret!(self.reg_def_private),
self.registry,
secret!(self.registry_idx),
self.tails_reader,
)
Expand Down
Loading