Exemple #1
0
        public async Task TestAnoncredsWorksForClaimRevokedBeforeProofCreated()
        {
            //9. Issuer revoke claim
            var revocRegUpdateJson = await AnonCreds.IssuerRevokeCredentialAsync(
                _issuerWallet,
                issuerDid,
                1,
                1);

            //10. Prover gets Claims for Proof Request
            var claimsJson = await AnonCreds.ProverGetCredentialsForProofReqAsync(_issuerWallet, _proofReqJson);

            var claims         = JObject.Parse(claimsJson);
            var claimsForAttr1 = claims["attrs"]["attr1_referent"];
            var claim          = claimsForAttr1[0];
            var claimUuid      = claim.Value <string>("referent");

            //11. Prover create Proof
            var requestedClaimsJson = string.Format(_requestedClaimsJsonTemplate, claimUuid);

            var schemasJson    = string.Format("{{\"{0}\":{1}}}", claimUuid, schema);
            var claimDefsJson  = string.Format("{{\"{0}\":{1}}}", claimUuid, _claimDefJson);
            var revocRegsJsons = string.Format("{{\"{0}\":{1}}}", claimUuid, revocRegUpdateJson);

            var ex = await Assert.ThrowsExceptionAsync <ClaimRevokedException>(() =>
                                                                               AnonCreds.ProverCreateProofAsync(
                                                                                   _issuerWallet,
                                                                                   _proofReqJson,
                                                                                   requestedClaimsJson,
                                                                                   schemasJson,
                                                                                   masterSecretName,
                                                                                   claimDefsJson,
                                                                                   revocRegsJsons)
                                                                               );
        }
        /// <inheritdoc />
        public virtual async Task RevokeCredentialAsync(IAgentContext agentContext, string credentialId, string issuerDid)
        {
            var credential = await GetAsync(agentContext, credentialId);

            if (credential.State != CredentialState.Issued)
            {
                throw new AgentFrameworkException(ErrorCode.RecordInInvalidState,
                                                  $"Credential state was invalid. Expected '{CredentialState.Requested}', found '{credential.State}'");
            }

            var definition = await SchemaService.GetCredentialDefinitionAsync(agentContext.Wallet, credential.CredentialDefinitionId);

            // Check if the state machine is valid for revocation
            await credential.TriggerAsync(CredentialTrigger.Revoke);

            var revocationRecordSearch = await RecordService.SearchAsync <RevocationRegistryRecord>(
                agentContext.Wallet, SearchQuery.Equal(nameof(RevocationRegistryRecord.CredentialDefinitionId), definition.Id), null, 5);

            var revocationRecord = revocationRecordSearch.Single(); // TODO: Add support for multiple revocation registries

            // Revoke the credential
            var tailsReader = await TailsService.OpenTailsAsync(revocationRecord.TailsFile);

            var revocRegistryDeltaJson = await AnonCreds.IssuerRevokeCredentialAsync(agentContext.Wallet, tailsReader,
                                                                                     revocationRecord.Id, credential.CredentialRevocationId);

            // Write the delta state on the ledger for the corresponding revocation registry
            await LedgerService.SendRevocationRegistryEntryAsync(agentContext.Wallet, agentContext.Pool, issuerDid,
                                                                 revocationRecord.Id,
                                                                 "CL_ACCUM", revocRegistryDeltaJson);

            // Update local credential record
            await RecordService.UpdateAsync(agentContext.Wallet, credential);
        }
Exemple #3
0
        /// <inheritdoc />
        public virtual async Task RevokeCredentialAsync(Pool pool, Wallet wallet, string credentialId, string issuerDid)
        {
            var credential = await GetAsync(wallet, credentialId);

            var definition =
                await SchemaService.GetCredentialDefinitionAsync(wallet, credential.CredentialDefinitionId);

            // Check if the state machine is valid for revocation
            await credential.TriggerAsync(CredentialTrigger.Revoke);

            var revocationRecordSearch = await RecordService.SearchAsync <RevocationRegistryRecord>(
                wallet, new SearchRecordQuery { { TagConstants.CredentialDefinitionId, definition.DefinitionId } }, null, 1);

            var revocationRecord = revocationRecordSearch.First();

            // Revoke the credential
            var tailsReader = await TailsService.OpenTailsAsync(revocationRecord.TailsFile);

            var revocRegistryDeltaJson = await AnonCreds.IssuerRevokeCredentialAsync(wallet, tailsReader,
                                                                                     revocationRecord.RevocationRegistryId, credential.CredentialRevocationId);

            // Write the delta state on the ledger for the corresponding revocation registry
            await LedgerService.SendRevocationRegistryEntryAsync(wallet, pool, issuerDid,
                                                                 revocationRecord.RevocationRegistryId,
                                                                 "CL_ACCUM", revocRegistryDeltaJson);

            // Update local credential record
            await RecordService.UpdateAsync(wallet, credential);
        }
Exemple #4
0
        /// <inheritdoc />
        public virtual async Task RevokeCredentialAsync(IAgentContext agentContext, string credentialId)
        {
            var credentialRecord = await GetAsync(agentContext, credentialId);

            if (credentialRecord.State != CredentialState.Issued)
            {
                throw new AriesFrameworkException(ErrorCode.RecordInInvalidState,
                                                  $"Credential state was invalid. Expected '{CredentialState.Issued}', found '{credentialRecord.State}'");
            }

            var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet);

            // Check if the state machine is valid for revocation
            await credentialRecord.TriggerAsync(CredentialTrigger.Revoke);

            var revocationRecord =
                await RecordService.GetAsync <RevocationRegistryRecord>(agentContext.Wallet,
                                                                        credentialRecord.RevocationRegistryId);

            // Revoke the credential
            var tailsReader = await TailsService.OpenTailsAsync(revocationRecord.TailsFile);

            var revocRegistryDeltaJson = await AnonCreds.IssuerRevokeCredentialAsync(
                agentContext.Wallet,
                tailsReader,
                revocationRecord.Id,
                credentialRecord.CredentialRevocationId);

            var paymentInfo =
                await PaymentService.GetTransactionCostAsync(agentContext, TransactionTypes.REVOC_REG_ENTRY);

            // Write the delta state on the ledger for the corresponding revocation registry
            await LedgerService.SendRevocationRegistryEntryAsync(
                context : agentContext,
                issuerDid : provisioning.IssuerDid,
                revocationRegistryDefinitionId : revocationRecord.Id,
                revocationDefinitionType : "CL_ACCUM",
                value : revocRegistryDeltaJson,
                paymentInfo : paymentInfo);

            if (paymentInfo != null)
            {
                await RecordService.UpdateAsync(agentContext.Wallet, paymentInfo.PaymentAddress);
            }

            // Update local credential record
            await RecordService.UpdateAsync(agentContext.Wallet, credentialRecord);
        }
Exemple #5
0
        public async Task TestAnoncredsWorksForClaimRevokedAfterProofCreated()
        {
            //9. Prover gets Claims for Proof Request
            var claimsJson = await AnonCreds.ProverGetCredentialsForProofReqAsync(_issuerWallet, _proofReqJson);

            var claims         = JObject.Parse(claimsJson);
            var claimsForAttr1 = claims["attrs"]["attr1_referent"];
            var claim          = claimsForAttr1[0];
            var claimUuid      = claim.Value <string>("referent");

            //10. Prover create Proof
            var requestedClaimsJson = string.Format(_requestedClaimsJsonTemplate, claimUuid);

            var schemasJson    = string.Format("{{\"{0}\":{1}}}", claimUuid, schema);
            var claimDefsJson  = string.Format("{{\"{0}\":{1}}}", claimUuid, _claimDefJson);
            var revocRegsJsons = string.Format("{{\"{0}\":{1}}}", claimUuid, _claimResult.RevocRegDeltaJson);

            var proofJson = await AnonCreds.ProverCreateProofAsync(
                _issuerWallet,
                _proofReqJson,
                requestedClaimsJson,
                schemasJson,
                masterSecretName,
                claimDefsJson,
                revocRegsJsons);

            //11. Issuer revoke prover claim
            var revocRegUpdateJson = await AnonCreds.IssuerRevokeCredentialAsync(
                _issuerWallet,
                issuerDid,
                1,
                1);

            //12. Verifier verify proof
            var updatedRevocRegsJsons = string.Format("{{\"{0}\":{1}}}", claimUuid, revocRegUpdateJson);

            var valid = await AnonCreds.VerifierVerifyProofAsync(
                _proofReqJson,
                proofJson,
                schemasJson,
                claimDefsJson,
                updatedRevocRegsJsons);

            Assert.IsFalse(valid);
        }
        public async Task TestIssuerRevokeProofWorks()
        {
            // Create wallet, get wallet handle
            var walletConfig = JsonConvert.SerializeObject(new { id = "revocationWallet" });
            await Wallet.CreateWalletAsync(walletConfig, CREDENTIALS);

            var wallet = await Wallet.OpenWalletAsync(walletConfig, CREDENTIALS);

            // Issuer create Schema
            var createSchemaResult = await AnonCreds.IssuerCreateSchemaAsync(issuerDid, gvtSchemaName, schemaVersion, gvtSchemaAttributes);

            var schemaId   = createSchemaResult.SchemaId;
            var schemaJson = createSchemaResult.SchemaJson;

            // Issuer create issuer1GvtCredential definition
            var revocationCredentialDefConfig = "{\"support_revocation\":true}";
            var createCredentialDefResult     = await AnonCreds.IssuerCreateAndStoreCredentialDefAsync(wallet, issuerDid, schemaJson, tag, null, revocationCredentialDefConfig);

            var credDefId   = createCredentialDefResult.CredDefId;
            var credDefJson = createCredentialDefResult.CredDefJson;

            // Issuer create revocation registry
            var tailsWriter = await BlobStorage.OpenWriterAsync("default", tailsWriterConfig);

            var revRegConfig       = "{\"issuance_type\":null,\"max_cred_num\":5}";
            var createRevRegResult = await AnonCreds.IssuerCreateAndStoreRevocRegAsync(wallet, issuerDid, null, tag, credDefId, revRegConfig, tailsWriter);

            var revRegId  = createRevRegResult.RevRegId;
            var revRegDef = createRevRegResult.RevRegDefJson;

            // Prover create Master Secret
            await AnonCreds.ProverCreateMasterSecretAsync(wallet, masterSecretId);

            // Issuer create Credential Offer
            var credOfferJson = await AnonCreds.IssuerCreateCredentialOfferAsync(wallet, credDefId);

            // Prover create Credential Request
            var createCredReqResult =
                await AnonCreds.ProverCreateCredentialReqAsync(wallet, proverDid, credOfferJson, credDefJson, masterSecretId);

            var credentialReqJson         = createCredReqResult.CredentialRequestJson;
            var credentialReqMetadataJson = createCredReqResult.CredentialRequestMetadataJson;

            // Issuer open TailsReader
            var blobReader = await BlobStorage.OpenReaderAsync("default", tailsWriterConfig);

            //9. Issuer create Credential
            var createCredentialResult = await AnonCreds.IssuerCreateCredentialAsync(wallet, credOfferJson, credentialReqJson, gvtCredentialValuesJson, revRegId, blobReader);

            var credJson    = createCredentialResult.CredentialJson;
            var credRevocId = createCredentialResult.RevocId;
            var revRegDelta = createCredentialResult.RevocRegDeltaJson;

            // Prover create RevocationState
            var timestamp    = 100;
            var revStateJson = await AnonCreds.CreateRevocationStateAsync(blobReader, revRegDef, revRegDelta, timestamp, credRevocId);

            // Prover store received Credential
            await AnonCreds.ProverStoreCredentialAsync(wallet, credentialId1, credentialReqMetadataJson, credJson, credDefJson, revRegDef);

            // Prover gets Credentials for Proof Request
            var credentialsJson = await AnonCreds.ProverGetCredentialsForProofReqAsync(wallet, proofRequest);

            var credentials         = JObject.Parse(credentialsJson);
            var credentialsForAttr1 = credentials["attrs"]["attr1_referent"];

            var credentialUuid = credentialsForAttr1[0]["cred_info"]["referent"];

            // Prover create Proof
            var requestedCredentialsJson = string.Format("{{" +
                                                         "\"self_attested_attributes\":{{}}," +
                                                         "\"requested_attributes\":{{\"attr1_referent\":{{\"cred_id\":\"{0}\", \"revealed\":true, \"timestamp\":{1} }}}}," +
                                                         "\"requested_predicates\":{{\"predicate1_referent\":{{\"cred_id\":\"{2}\", \"timestamp\":{3}}}}}" +
                                                         "}}", credentialUuid, timestamp, credentialUuid, timestamp);

            var schemasJson        = JObject.Parse(string.Format("{{\"{0}\":{1}}}", schemaId, schemaJson)).ToString();
            var credentialDefsJson = JObject.Parse(string.Format("{{\"{0}\":{1}}}", credDefId, credDefJson)).ToString();
            var revStatesJson      = JObject.Parse(string.Format("{{\"{0}\":{{\"{1}\":{2}}}}}", revRegId, timestamp, revStateJson)).ToString();

            var proofJson = await AnonCreds.ProverCreateProofAsync(wallet, proofRequest, requestedCredentialsJson, masterSecretId, schemasJson, credentialDefsJson, revStatesJson);

            var proof = JObject.Parse(proofJson);

            // Issuer revoke Credential
            revRegDelta = await AnonCreds.IssuerRevokeCredentialAsync(wallet, blobReader, revRegId, credRevocId);

            // Verifier verify proof
            var revealedAttr1 = proof["requested_proof"]["revealed_attrs"]["attr1_referent"];

            Assert.AreEqual("Alex", revealedAttr1["raw"]);

            var revRegDefsJson = JObject.Parse(string.Format("{{\"{0}\":{1}}}", revRegId, revRegDef)).ToString();
            var revRegs        = JObject.Parse(string.Format("{{\"{0}\":{{\"{1}\":{2}}}}}", revRegId, timestamp, revRegDelta)).ToString();

            var valid = await AnonCreds.VerifierVerifyProofAsync(proofRequest, proofJson, schemasJson, credentialDefsJson, revRegDefsJson, revRegs);

            Assert.IsFalse(valid);

            //// Close and Delete Wallet
            await wallet.CloseAsync();

            await Wallet.DeleteWalletAsync(walletConfig, CREDENTIALS);
        }
Exemple #7
0
        public async Task testAnoncredsRevocationInteractionIssuanceByDefault()
        {
            // Issuer create DID
            var trusteeDidInfo = await Did.CreateAndStoreMyDidAsync(this.wallet, JsonConvert.SerializeObject(new { seed = TRUSTEE_SEED }));

            var issuerDidInfo = await Did.CreateAndStoreMyDidAsync(this.wallet, "{}");

            var nymRequest = await Ledger.BuildNymRequestAsync(trusteeDidInfo.Did, issuerDidInfo.Did,
                                                               issuerDidInfo.VerKey, null, "TRUSTEE");

            await Ledger.SignAndSubmitRequestAsync(pool, wallet, trusteeDidInfo.Did, nymRequest);

            var issuerDid = issuerDidInfo.Did;

            // Prover create DID
            var proverDidInfo = await Did.CreateAndStoreMyDidAsync(proverWallet, "{}");

            var proverDid    = proverDidInfo.Did;
            var proverVerkey = proverDidInfo.VerKey;

            // Issuer publish Prover DID
            nymRequest = await Ledger.BuildNymRequestAsync(issuerDid, proverDid, proverVerkey, null, null);

            await Ledger.SignAndSubmitRequestAsync(pool, wallet, issuerDid, nymRequest);

            // ISSUER post to Ledger Schema, CredentialDefinition, RevocationRegistry

            // Issuer creates Schema
            var schemaInfo =
                await AnonCreds.IssuerCreateSchemaAsync(issuerDidInfo.Did, GVT_SCHEMA_NAME,
                                                        SCHEMA_VERSION, GVT_SCHEMA_ATTRIBUTES);

            var schemaJson = schemaInfo.SchemaJson;

            // Issuer posts Schema to Ledger
            var schemaRequest = await Ledger.BuildSchemaRequestAsync(issuerDid, schemaJson);

            await Ledger.SignAndSubmitRequestAsync(pool, wallet, issuerDid, schemaRequest);

            // Issuer get Schema from Ledger
            var getSchemaRequest = await Ledger.BuildGetSchemaRequestAsync(issuerDid, schemaInfo.SchemaId);

            var getSchemaResponse = await PoolUtils.EnsurePreviousRequestAppliedAsync(pool, getSchemaRequest, response => {
                var getSchemaResponseObject = JObject.Parse(response);
                return(getSchemaResponseObject["result"]["seqNo"] != null);
            });

            // !!IMPORTANT!!
            // It is important to get Schema from Ledger and parse it to get the correct schema JSON and correspondent id in Ledger
            // After that we can create CredentialDefinition for received Schema(not for result of indy_issuer_create_schema)

            ParseResponseResult schemaInfo1 = await Ledger.ParseGetSchemaResponseAsync(getSchemaResponse);

            schemaJson = schemaInfo1.ObjectJson;

            // Issuer creates CredentialDefinition

            var credDefInfo =
                await AnonCreds.IssuerCreateAndStoreCredentialDefAsync(wallet, issuerDid, schemaJson,
                                                                       TAG, null, JsonConvert.SerializeObject(new { support_revocation = true }));

            var credDefId   = credDefInfo.CredDefId;
            var credDefJson = credDefInfo.CredDefJson;

            // Issuer post CredentialDefinition to Ledger
            var credDefRequest = await Ledger.BuildCredDefRequestAsync(issuerDid, credDefJson);

            await Ledger.SignAndSubmitRequestAsync(pool, wallet, issuerDid, credDefRequest);

            // Issuer creates RevocationRegistry
            /* FIXME: getIndyHomePath hard coded forward slash "/". It will not work for Windows. */
            var tailsWriterConfig = JsonConvert.SerializeObject(
                new
            {
                base_dir    = EnvironmentUtils.GetIndyHomePath("tails"),
                uri_pattern = string.Empty
            }
                );

            var tailsWriterHandle = await BlobStorage.OpenWriterAsync("default", tailsWriterConfig);

            var revRegInfo =
                await AnonCreds.IssuerCreateAndStoreRevocRegAsync(wallet, issuerDid, null, TAG,
                                                                  credDefId,
                                                                  JsonConvert.SerializeObject(new { max_cred_num = 5, issuance_type = "ISSUANCE_BY_DEFAULT" }),
                                                                  tailsWriterHandle);

            var revRegId        = revRegInfo.RevRegId;
            var revRegDefJson   = revRegInfo.RevRegDefJson;
            var revRegEntryJson = revRegInfo.RevRegEntryJson;

            // Issuer posts RevocationRegistryDefinition to Ledger
            var revRegDefRequest = await Ledger.BuildRevocRegDefRequestAsync(issuerDid, revRegDefJson);

            await Ledger.SignAndSubmitRequestAsync(pool, wallet, issuerDid, revRegDefRequest);

            // Issuer posts RevocationRegistryEntry to Ledger
            var revRegEntryRequest = await Ledger.BuildRevocRegEntryRequestAsync(issuerDid, revRegId, REVOC_REG_TYPE, revRegEntryJson);

            await Ledger.SignAndSubmitRequestAsync(pool, wallet, issuerDid, revRegEntryRequest);

            // Issuance Credential for Prover

            // Prover creates Master Secret
            await AnonCreds.ProverCreateMasterSecretAsync(proverWallet, COMMON_MASTER_SECRET);

            // Issuer creates Credential Offer
            var credOfferJson = await AnonCreds.IssuerCreateCredentialOfferAsync(wallet, credDefId);

            // Prover gets CredentialDefinition from Ledger
            var getCredDefRequest = await Ledger.BuildGetCredDefRequestAsync(proverDid, credDefInfo.CredDefId);

            var getCredDefResponse = await Ledger.SubmitRequestAsync(pool, getCredDefRequest);

            ParseResponseResult credDefIdInfo = await Ledger.ParseGetCredDefResponseAsync(getCredDefResponse);

            credDefId   = credDefIdInfo.Id;
            credDefJson = credDefIdInfo.ObjectJson;

            // Prover creates Credential Request
            var credReqInfo =
                await AnonCreds.ProverCreateCredentialReqAsync(proverWallet, proverDid, credOfferJson,
                                                               credDefJson, COMMON_MASTER_SECRET);

            var credReqJson         = credReqInfo.CredentialRequestJson;
            var credReqMetadataJson = credReqInfo.CredentialRequestMetadataJson;

            // Issuer creates TailsReader
            BlobStorageReader blobStorageReader = await BlobStorage.OpenReaderAsync(TYPE, tailsWriterConfig);

            // Issuer creates Credential
            // Issuer must not post rev_reg_delta to ledger for ISSUANCE_BY_DEFAULT strategy

            var credRegInfo =
                await AnonCreds.IssuerCreateCredentialAsync(wallet, credOfferJson, credReqJson,
                                                            GVT_CRED_VALUES, revRegId,
                                                            blobStorageReader);

            var credJson  = credRegInfo.CredentialJson;
            var credRevId = credRegInfo.RevocId;

            // Prover gets RevocationRegistryDefinition
            var getRevRegDefRequest = await Ledger.BuildGetRevocRegDefRequestAsync(proverDid, revRegId);

            var getRevRegDefResponse = await Ledger.SubmitRequestAsync(pool, getRevRegDefRequest);

            ParseResponseResult revRegInfo1 = await Ledger.ParseGetRevocRegDefResponseAsync(getRevRegDefResponse);

            revRegId = revRegInfo1.Id;
            var revocRegDefJson = revRegInfo1.ObjectJson;

            // Prover store received Credential

            await AnonCreds.ProverStoreCredentialAsync(proverWallet, "credential1_id",
                                                       credReqMetadataJson, credJson, credDefJson,
                                                       revocRegDefJson);

            // Verifying Prover Credential
            Thread.Sleep(3000);

            long to = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds / 1000;

            var proofRequest = JsonConvert.SerializeObject(
                new
            {
                nonce   = "123432421212",
                name    = "proof_req_1",
                version = "0.1",
                requested_attributes = new
                {
                    attr1_referent = new
                    {
                        name = "name"
                    }
                },
                requested_predicates = new
                {
                    predicate1_referent = new
                    {
                        name    = "age",
                        p_type  = ">=",
                        p_value = 18
                    }
                },
                non_revoked = new
                {
                    to = to
                }
            }
                );

            // Prover gets Claims for Proof Request

            var credentialsJson = await AnonCreds.ProverGetCredentialsForProofReqAsync(proverWallet, proofRequest);

            var credentials      = JObject.Parse(credentialsJson);
            var credsForReferent = (JArray)credentials["attrs"]["attr1_referent"];
            var credential       = credsForReferent[0]["cred_info"];

            // Prover gets RevocationRegistryDelta from Ledger

            /* FIXME */
            var getRevRegDeltaRequest = await Ledger.BuildGetRevocRegDeltaRequestAsync(proverDid, revRegId, -1, (int)to);

            var getRevRegDeltaResponse = await Ledger.SubmitRequestAsync(pool, getRevRegDeltaRequest);

            var revRegInfo2 = await Ledger.ParseGetRevocRegDeltaResponseAsync(getRevRegDeltaResponse);

            revRegId = revRegInfo2.Id;
            var revocRegDeltaJson = revRegInfo2.ObjectJson;

            // Prover creates RevocationState
            var timestamp = to;

            var revStateJson = await AnonCreds.CreateRevocationStateAsync(blobStorageReader,
                                                                          revocRegDefJson, revocRegDeltaJson, (int)timestamp, credRevId);

            // Prover gets Schema from Ledger
            getSchemaRequest = await Ledger.BuildGetSchemaRequestAsync(proverDid, schemaInfo1.Id);

            getSchemaResponse = await Ledger.SubmitRequestAsync(pool, getSchemaRequest);

            ParseResponseResult schemaInfo2 = await Ledger.ParseGetSchemaResponseAsync(getSchemaResponse);

            var schemaId = schemaInfo2.Id;

            schemaJson = schemaInfo2.ObjectJson;

            // Prover creates Proof
            var requestedCredentialsJson = JsonConvert.SerializeObject(
                new
            {
                self_attested_attributes = new { },
                requested_attributes     = new
                {
                    attr1_referent = new
                    {
                        cred_id   = credential["referent"],
                        timestamp = timestamp,
                        revealed  = true
                    }
                },
                requested_predicates = new
                {
                    predicate1_referent = new
                    {
                        cred_id   = credential["referent"],
                        timestamp = timestamp
                    }
                }
            }
                );


            var schemasJson   = new JObject(new JProperty(schemaId, JObject.Parse(schemaJson))).ToString();
            var credDefsJson  = new JObject(new JProperty(credDefId, JObject.Parse(credDefJson))).ToString();
            var revStatesJson = new JObject(new JProperty(revRegId, new JObject(new JProperty(timestamp.ToString(), JObject.Parse(revStateJson))))).ToString();

            var proofJson = await AnonCreds.ProverCreateProofAsync(proverWallet, proofRequest,
                                                                   requestedCredentialsJson, COMMON_MASTER_SECRET,
                                                                   schemasJson, credDefsJson, revStatesJson);


            var proof = JObject.Parse(proofJson);

            // Verifier gets RevocationRegistry from Ledger

            var getRevRegReq = await Ledger.BuildGetRevocRegRequestAsync(DID_MY1, revRegId, (int)timestamp);

            var getRevRegResp = await Ledger.SubmitRequestAsync(pool, getRevRegReq);

            var revRegInfo3 = await Ledger.ParseGetRevocRegResponseAsync(getRevRegResp);

            revRegId = revRegInfo3.Id;
            var revRegJson = revRegInfo3.ObjectJson;

            // Verifier verifies proof
            Assert.AreNotEqual("Alex", proof["requested_proof"]["revealed_attrs"]["attr1_referent"].ToString());

            var revRegDefsJson = new JObject(new JProperty(revRegId, JObject.Parse(revRegDefJson))).ToString();
            var revRegsJson    = new JObject(new JProperty(revRegId, new JObject(new JProperty(timestamp.ToString(), JObject.Parse(revRegJson))))).ToString();

            var valid = await AnonCreds.VerifierVerifyProofAsync(proofRequest,
                                                                 proofJson,
                                                                 schemasJson,
                                                                 credDefsJson,
                                                                 revRegDefsJson,
                                                                 revRegsJson);

            Assert.IsTrue(valid);

            // Issuer revokes credential
            var revRegDeltaJson = await AnonCreds.IssuerRevokeCredentialAsync(wallet,
                                                                              blobStorageReader,
                                                                              revRegId, credRevId);

            // Issuer post RevocationRegistryDelta to Ledger
            revRegEntryRequest = await Ledger.BuildRevocRegEntryRequestAsync(issuerDid, revRegId, REVOC_REG_TYPE, revRegDeltaJson);

            await Ledger.SignAndSubmitRequestAsync(pool, wallet, issuerDid, revRegEntryRequest);

            // Verifying Prover Credential after Revocation
            Thread.Sleep(3000);

            long from = to;

            to = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds / 1000;

            // Prover gets RevocationRegistryDelta from Ledger
            getRevRegDeltaRequest = await Ledger.BuildGetRevocRegDeltaRequestAsync(proverDid, revRegId, (int)from, (int)to);

            getRevRegDeltaResponse = await Ledger.SubmitRequestAsync(pool, getRevRegDeltaRequest);

            var revRegInfo4 = await Ledger.ParseGetRevocRegDeltaResponseAsync(getRevRegDeltaResponse);

            revRegId          = revRegInfo4.Id;
            revocRegDeltaJson = revRegInfo4.ObjectJson;
            timestamp         = (long)revRegInfo4.Timestamp;

            // Prover creates RevocationState
            revStateJson = await AnonCreds.CreateRevocationStateAsync(blobStorageReader,
                                                                      revocRegDefJson, revocRegDeltaJson, (int)timestamp, credRevId);

            requestedCredentialsJson = JsonConvert.SerializeObject(
                new
            {
                self_attested_attributes = new { },
                requested_attributes     = new
                {
                    attr1_referent = new
                    {
                        cred_id   = credential["referent"],
                        timestamp = timestamp,
                        revealed  = true
                    }
                },
                requested_predicates = new
                {
                    predicate1_referent = new
                    {
                        cred_id   = credential["referent"],
                        timestamp = timestamp
                    }
                }
            }
                );

            revStatesJson = new JObject(new JProperty(revRegId, new JObject(new JProperty(timestamp.ToString(), JObject.Parse(revStateJson))))).ToString();

            proofJson = await AnonCreds.ProverCreateProofAsync(proverWallet,
                                                               proofRequest,
                                                               requestedCredentialsJson,
                                                               COMMON_MASTER_SECRET,
                                                               schemasJson,
                                                               credDefsJson,
                                                               revStatesJson);

            // Verifier gets RevocationRegistry from Ledger
            getRevRegReq = await Ledger.BuildGetRevocRegRequestAsync(DID_MY1, revRegId, (int)timestamp);

            getRevRegResp = await Ledger.SubmitRequestAsync(pool, getRevRegReq);

            var revRegInfo5 = await Ledger.ParseGetRevocRegResponseAsync(getRevRegResp);

            revRegId   = revRegInfo5.Id;
            revRegJson = revRegInfo5.ObjectJson;
            timestamp  = (long)revRegInfo5.Timestamp;

            revRegsJson = new JObject(new JProperty(revRegId, new JObject(new JProperty(timestamp.ToString(), JObject.Parse(revRegJson))))).ToString();

            valid = await AnonCreds.VerifierVerifyProofAsync(proofRequest,
                                                             proofJson,
                                                             schemasJson,
                                                             credDefsJson,
                                                             revRegDefsJson,
                                                             revRegsJson);

            Assert.IsFalse(valid);
        }