public async Task IssueCredentialThrowsExceptionUnableToSendA2AMessage()
        {
            //Establish a connection between the two parties
            var(issuerConnection, holderConnection) = await Scenarios.EstablishConnectionAsync(
                _connectionService, _messages, _issuerWallet, _holderWallet);

            // Create an issuer DID/VK. Can also be created during provisioning
            var issuer = await Did.CreateAndStoreMyDidAsync(_issuerWallet.Wallet,
                                                            new { seed = "000000000000000000000000Steward1" }.ToJson());

            // Creata a schema and credential definition for this issuer
            (var definitionId, _) = await Scenarios.CreateDummySchemaAndNonRevokableCredDef(_issuerWallet, _schemaService, issuer.Did,
                                                                                            new[] { "dummy_attr" });

            var offerConfig = new OfferConfiguration()
            {
                IssuerDid = issuer.Did,
                CredentialDefinitionId = definitionId
            };

            // Send an offer to the holder using the established connection channel
            await _credentialService.SendOfferAsync(_issuerWallet, issuerConnection.Id, offerConfig);

            // Holder retrives message from their cloud agent
            var credentialOffer = FindContentMessage <CredentialOfferMessage>(_messages);

            // Holder processes the credential offer by storing it
            var holderCredentialId =
                await _credentialService.ProcessOfferAsync(_holderWallet, credentialOffer, holderConnection);

            // Holder creates master secret. Will also be created during wallet agent provisioning
            await AnonCreds.ProverCreateMasterSecretAsync(_holderWallet.Wallet, MasterSecretId);

            // Holder accepts the credential offer and sends a credential request
            await _credentialService.AcceptOfferAsync(_holderWallet, holderCredentialId,
                                                      new Dictionary <string, string>
            {
                { "dummy_attr", "dummyVal" }
            });

            // Issuer retrieves credential request from cloud agent
            var credentialRequest = FindContentMessage <CredentialRequestMessage>(_messages);

            Assert.NotNull(credentialRequest);

            // Issuer processes the credential request by storing it
            var issuerCredentialId =
                await _credentialService.ProcessCredentialRequestAsync(_issuerWallet, credentialRequest, issuerConnection);

            //Try issue the credential with a credential service that has a bad routing service

            _routeMessage = false;
            var ex = await Assert.ThrowsAsync <AgentFrameworkException>(async() => await _credentialService.IssueCredentialAsync(_issuerWallet, issuer.Did, issuerCredentialId));

            Assert.True(ex.ErrorCode == ErrorCode.A2AMessageTransmissionError);
            _routeMessage = true;
        }
Exemple #2
0
        /// <inheritdoc />
        public virtual async Task ProvisionAgentAsync(Wallet wallet, ProvisioningConfiguration provisioningConfiguration)
        {
            if (provisioningConfiguration == null)
            {
                throw new ArgumentNullException(nameof(provisioningConfiguration));
            }
            if (provisioningConfiguration.EndpointUri == null)
            {
                throw new ArgumentNullException(nameof(provisioningConfiguration.EndpointUri));
            }

            var record = await GetProvisioningAsync(wallet);

            if (record != null)
            {
                throw new WalletAlreadyProvisionedException();
            }

            var agent = await Did.CreateAndStoreMyDidAsync(wallet,
                                                           provisioningConfiguration.AgentSeed != null
                                                           ?new { seed = provisioningConfiguration.AgentSeed }.ToJson()
                                                               : "{}");

            var masterSecretId = await AnonCreds.ProverCreateMasterSecretAsync(wallet, null);

            record = new ProvisioningRecord
            {
                IssuerSeed     = provisioningConfiguration.IssuerSeed,
                AgentSeed      = provisioningConfiguration.AgentSeed,
                MasterSecretId = masterSecretId,
                Endpoint       =
                {
                    Uri    = provisioningConfiguration.EndpointUri.ToString(),
                    Did    = agent.Did,
                    Verkey = agent.VerKey
                },
                Owner =
                {
                    Name     = provisioningConfiguration.OwnerName,
                    ImageUrl = provisioningConfiguration.OwnerImageUrl
                },
                TailsBaseUri = provisioningConfiguration.TailsBaseUri.ToString()
            };

            if (provisioningConfiguration.CreateIssuer)
            {
                var issuer = await Did.CreateAndStoreMyDidAsync(wallet,
                                                                provisioningConfiguration.IssuerSeed != null
                                                                ?new { seed = provisioningConfiguration.IssuerSeed }.ToJson()
                                                                    : "{}");

                record.IssuerDid    = issuer.Did;
                record.IssuerVerkey = issuer.VerKey;
            }

            await RecordService.AddAsync(wallet, record);
        }
        private async Task <string> BuildRevocationStatesAsync(IAgentContext agentContext,
                                                               IEnumerable <CredentialInfo> credentialObjects,
                                                               ProofRequest proofRequest,
                                                               RequestedCredentials requestedCredentials)
        {
            var allCredentials = new List <RequestedAttribute>();

            allCredentials.AddRange(requestedCredentials.RequestedAttributes.Values);
            allCredentials.AddRange(requestedCredentials.RequestedPredicates.Values);

            var result = new Dictionary <string, Dictionary <string, JObject> >();

            foreach (var requestedCredential in allCredentials)
            {
                // ReSharper disable once PossibleMultipleEnumeration
                var credential = credentialObjects.First(x => x.Referent == requestedCredential.CredentialId);
                if (credential.RevocationRegistryId == null ||
                    (proofRequest.NonRevoked == null))
                {
                    continue;
                }

                var registryDefinition = await LedgerService.LookupRevocationRegistryDefinitionAsync(
                    agentContext : agentContext,
                    registryId : credential.RevocationRegistryId);

                var delta = await LedgerService.LookupRevocationRegistryDeltaAsync(
                    agentContext : agentContext,
                    revocationRegistryId : credential.RevocationRegistryId,
                    from : proofRequest.NonRevoked.From,
                    to : proofRequest.NonRevoked.To);

                var tailsfile = await TailsService.EnsureTailsExistsAsync(agentContext, credential.RevocationRegistryId);

                var tailsReader = await TailsService.OpenTailsAsync(tailsfile);

                var state = await AnonCreds.CreateRevocationStateAsync(
                    blobStorageReader : tailsReader,
                    revRegDef : registryDefinition.ObjectJson,
                    revRegDelta : delta.ObjectJson,
                    timestamp : (long)delta.Timestamp,
                    credRevId : credential.CredentialRevocationId);

                if (!result.ContainsKey(credential.RevocationRegistryId))
                {
                    result.Add(credential.RevocationRegistryId, new Dictionary <string, JObject>());
                }

                requestedCredential.Timestamp = (long)delta.Timestamp;
                if (!result[credential.RevocationRegistryId].ContainsKey($"{delta.Timestamp}"))
                {
                    result[credential.RevocationRegistryId].Add($"{delta.Timestamp}", JObject.Parse(state));
                }
            }

            return(result.ToJson());
        }
        private async Task <string> BuildRevocationStatesAsync(Pool pool,
                                                               IEnumerable <CredentialInfo> credentialObjects,
                                                               RequestedCredentials requestedCredentials)
        {
            var allCredentials = new List <RequestedAttribute>();

            allCredentials.AddRange(requestedCredentials.RequestedAttributes.Values);
            allCredentials.AddRange(requestedCredentials.RequestedPredicates.Values);

            var result = new Dictionary <string, Dictionary <string, JObject> >();

            foreach (var requestedCredential in allCredentials)
            {
                // ReSharper disable once PossibleMultipleEnumeration
                var credential = credentialObjects.First(x => x.Referent == requestedCredential.CredentialId);
                if (credential.RevocationRegistryId == null)
                {
                    continue;
                }

                var timestamp = requestedCredential.Timestamp ??
                                throw new Exception(
                                          "Timestamp must be provided for credential that supports revocation");

                if (result.ContainsKey(credential.RevocationRegistryId) &&
                    result[credential.RevocationRegistryId].ContainsKey($"{timestamp}"))
                {
                    continue;
                }

                var registryDefinition =
                    await LedgerService.LookupRevocationRegistryDefinitionAsync(pool, null,
                                                                                credential.RevocationRegistryId);

                var delta = await LedgerService.LookupRevocationRegistryDeltaAsync(pool,
                                                                                   credential.RevocationRegistryId, -1, timestamp);

                var tailsfile = await TailsService.EnsureTailsExistsAsync(pool, credential.RevocationRegistryId);

                var tailsReader = await TailsService.OpenTailsAsync(tailsfile);

                var state = await AnonCreds.CreateRevocationStateAsync(tailsReader, registryDefinition.ObjectJson,
                                                                       delta.ObjectJson, (long)delta.Timestamp, credential.CredentialRevocationId);

                if (!result.ContainsKey(credential.RevocationRegistryId))
                {
                    result.Add(credential.RevocationRegistryId, new Dictionary <string, JObject>());
                }

                result[credential.RevocationRegistryId].Add($"{timestamp}", JObject.Parse(state));

                // TODO: Revocation state should provide the state between a certain period
                // that can be requested in the proof request in the 'non_revocation' field.
            }

            return(result.ToJson());
        }
Exemple #5
0
        public async Task RejectCredentialRequestThrowsExceptionCredentialInvalidState()
        {
            //Establish a connection between the two parties
            var(issuerConnection, holderConnection) = await Scenarios.EstablishConnectionAsync(
                _connectionService, _messages, _issuerWallet, _holderWallet);

            // Create an issuer DID/VK. Can also be created during provisioning
            var issuer = await Did.CreateAndStoreMyDidAsync(_issuerWallet.Wallet,
                                                            new { seed = TestConstants.StewartDid }.ToJson());

            // Create a schema and credential definition for this issuer
            var(definitionId, _) = await Scenarios.CreateDummySchemaAndNonRevokableCredDef(_issuerWallet, _schemaService, issuer.Did,
                                                                                           new[] { "dummy_attr" });

            var offerConfig = new OfferConfiguration
            {
                IssuerDid = issuer.Did,
                CredentialDefinitionId = definitionId
            };

            // Send an offer to the holder using the established connection channel
            var(offerMessage, _) = await _credentialService.CreateOfferAsync(_issuerWallet, offerConfig, issuerConnection.Id);

            _messages.Add(offerMessage);

            // Holder retrieves message from their cloud agent
            var credentialOffer = FindContentMessage <CredentialOfferMessage>(_messages);

            // Holder processes the credential offer by storing it
            var holderCredentialId =
                await _credentialService.ProcessOfferAsync(_holderWallet, credentialOffer, holderConnection);

            // Holder creates master secret. Will also be created during wallet agent provisioning
            await AnonCreds.ProverCreateMasterSecretAsync(_holderWallet.Wallet, TestConstants.DefaultMasterSecret);

            // Holder accepts the credential offer and sends a credential request
            (var request, var _) = await _credentialService.CreateRequestAsync(_holderWallet, holderCredentialId);

            _messages.Add(request);

            // Issuer retrieves credential request from cloud agent
            var credentialRequest = FindContentMessage <CredentialRequestMessage>(_messages);

            Assert.NotNull(credentialRequest);

            // Issuer processes the credential request by storing it
            var issuerCredentialId =
                await _credentialService.ProcessCredentialRequestAsync(_issuerWallet, credentialRequest, issuerConnection);

            await _credentialService.RejectCredentialRequestAsync(_issuerWallet, issuerCredentialId);

            //Try reject the credential request again
            var ex = await Assert.ThrowsAsync <AriesFrameworkException>(async() => await _credentialService.RejectCredentialRequestAsync(_issuerWallet, issuerCredentialId));

            Assert.True(ex.ErrorCode == ErrorCode.RecordInInvalidState);
        }
Exemple #6
0
        /// <inheritdoc />
        public virtual async Task <(ProofMessage, ProofRecord)> CreateProofAsync(IAgentContext agentContext,
                                                                                 string proofRequestId, RequestedCredentials requestedCredentials)
        {
            var record = await GetAsync(agentContext, proofRequestId);

            if (record.State != ProofState.Requested)
            {
                throw new AgentFrameworkException(ErrorCode.RecordInInvalidState,
                                                  $"Proof state was invalid. Expected '{ProofState.Requested}', found '{record.State}'");
            }

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

            var credentialObjects = new List <CredentialInfo>();

            foreach (var credId in requestedCredentials.GetCredentialIdentifiers())
            {
                credentialObjects.Add(
                    JsonConvert.DeserializeObject <CredentialInfo>(
                        await AnonCreds.ProverGetCredentialAsync(agentContext.Wallet, credId)));
            }

            var schemas = await BuildSchemasAsync(await agentContext.Pool,
                                                  credentialObjects
                                                  .Select(x => x.SchemaId)
                                                  .Distinct());

            var definitions = await BuildCredentialDefinitionsAsync(await agentContext.Pool,
                                                                    credentialObjects
                                                                    .Select(x => x.CredentialDefinitionId)
                                                                    .Distinct());

            var revocationStates = await BuildRevocationStatesAsync(await agentContext.Pool,
                                                                    credentialObjects,
                                                                    requestedCredentials);

            var proofJson = await AnonCreds.ProverCreateProofAsync(agentContext.Wallet, record.RequestJson,
                                                                   requestedCredentials.ToJson(), provisioningRecord.MasterSecretId, schemas, definitions,
                                                                   revocationStates);

            record.ProofJson = proofJson;
            await record.TriggerAsync(ProofTrigger.Accept);

            await RecordService.UpdateAsync(agentContext.Wallet, record);

            var threadId = record.GetTag(TagConstants.LastThreadId);

            var proofMsg = new ProofMessage
            {
                ProofJson = proofJson
            };

            proofMsg.ThreadFrom(threadId);

            return(proofMsg, record);
        }
Exemple #7
0
        public async Task RejectProofRequestCredentialInvalidState()
        {
            //Setup a connection and issue the credentials to the holder
            var(issuerConnection, holderConnection) = await Scenarios.EstablishConnectionAsync(
                _connectionService, _messages, _issuerWallet, _holderWallet);

            await Scenarios.IssueCredentialAsync(
                _schemaService, _credentialService, _messages, issuerConnection,
                holderConnection, _issuerWallet, _holderWallet, await _holderWallet.Pool, TestConstants.DefaultMasterSecret, true, new List <CredentialPreviewAttribute>
            {
                new CredentialPreviewAttribute("first_name", "Test"),
                new CredentialPreviewAttribute("last_name", "Holder")
            });

            _messages.Clear();

            //Requestor initialize a connection with the holder
            var(_, requestorConnection) = await Scenarios.EstablishConnectionAsync(
                _connectionService, _messages, _holderWallet, _requestorWallet);

            // Verifier sends a proof request to prover
            {
                var proofRequestObject = new ProofRequest
                {
                    Name                = "ProofReq",
                    Version             = "1.0",
                    Nonce               = await AnonCreds.GenerateNonceAsync(),
                    RequestedAttributes = new Dictionary <string, ProofAttributeInfo>
                    {
                        { "first-name-requirement", new ProofAttributeInfo {
                              Name = "first_name"
                          } }
                    }
                };

                //Requestor sends a proof request
                var(message, _) = await _proofService.CreateRequestAsync(_requestorWallet, proofRequestObject, requestorConnection.Id);

                _messages.Add(message);
            }

            //Holder retrieves proof request message from their cloud agent
            var proofRequest = FindContentMessage <RequestPresentationMessage>();

            Assert.NotNull(proofRequest);

            //Holder stores the proof request
            var holderProofRequestId = await _proofService.ProcessRequestAsync(_holderWallet, proofRequest, holderConnection);

            //Holder accepts the proof request and sends a proof
            await _proofService.RejectProofRequestAsync(_holderWallet, holderProofRequestId.Id);

            var ex = await Assert.ThrowsAsync <AriesFrameworkException>(async() => await _proofService.RejectProofRequestAsync(_holderWallet, holderProofRequestId.Id));

            Assert.True(ex.ErrorCode == ErrorCode.RecordInInvalidState);
        }
Exemple #8
0
        public async Task TestProverCreateMasterSecretWorksForDuplicate()
        {
            await AnonCreds.ProverCreateMasterSecretAsync(_wallet, "master_secret_name_duplicate");

            var ex = await Assert.ThrowsExceptionAsync <IndyException>(() =>
                                                                       AnonCreds.ProverCreateMasterSecretAsync(_wallet, "master_secret_name_duplicate")
                                                                       );

            Assert.AreEqual(ErrorCode.AnoncredsMasterSecretDuplicateNameError, ex.ErrorCode);
        }
        public async Task TestIssuerCreateAndStoreClaimDefWorksForInvalidSchemaJson()
        {
            var schema = "{\"seqNo\":1, \"name\":\"name\",\"version\":\"1.0\", \"keys\":[\"name\"]}";

            var ex = await Assert.ThrowsExceptionAsync <IndyException>(() =>
                                                                       AnonCreds.IssuerCreateAndStoreClaimDefAsync(_wallet, _issuerDid, schema, null, false)
                                                                       );

            Assert.AreEqual(ErrorCode.CommonInvalidStructure, ex.ErrorCode);
        }
        public async Task TestsProverGetClaimOffersWorksForEmptyFilter()
        {
            await InitCommonWallet();

            var claimOffers = await AnonCreds.ProverGetClaimOffersAsync(_commonWallet, "{}");

            var claimOffersArray = JArray.Parse(claimOffers);

            Assert.AreEqual(3, claimOffersArray.Count);
        }
        public async Task TestProverCreateAndStoreClaimReqWorksForInvalidClaimOffer()
        {
            await InitCommonWallet();

            var claimOffer = string.Format("{{\"issuer_did\":\"{0}\"}}", issuerDid);

            var ex = await Assert.ThrowsExceptionAsync <InvalidStructureException>(() =>
                                                                                   AnonCreds.ProverCreateCredentialReqAsync(commonWallet, proverDid, claimOffer, claimDef, masterSecretName)
                                                                                   );
        }
        public async Task TestProverCreateAndStoreClaimReqWorksForClaimDefDoesNotCorrespondToClaimOfferDifferentSchema()
        {
            await InitCommonWallet();

            var claimOffer = string.Format(claimOfferTemplate, issuerDid, 2);

            var ex = await Assert.ThrowsExceptionAsync <InvalidStructureException>(() =>
                                                                                   AnonCreds.ProverCreateCredentialReqAsync(commonWallet, proverDid, claimOffer, claimDef, masterSecretName)
                                                                                   );
        }
        public async Task TestProverGetCredentialsWorksForEmptyResult()
        {
            var filter = string.Format("{{\"issuer_id\":\"{0}a\"}}", issuerDid);

            var credentials = await AnonCreds.ProverGetCredentialsAsync(wallet, filter);

            var credentialsArray = JArray.Parse(credentials);

            Assert.AreEqual(0, credentialsArray.Count);
        }
        public async Task TestProverGetCredentialsWorksForFilterByCredDefId()
        {
            var filter = string.Format("{{\"cred_def_id\":\"{0}\"}}", issuer1gvtCredDefId);

            var credentials = await AnonCreds.ProverGetCredentialsAsync(wallet, filter);

            var credentialsArray = JArray.Parse(credentials);

            Assert.AreEqual(1, credentialsArray.Count);
        }
        public async Task TestProverGetCredentialsWorksForFilterBySchemaName()
        {
            var filter = "{\"schema_name\":\"gvt\"}";

            var credentials = await AnonCreds.ProverGetCredentialsAsync(wallet, filter);

            var credentialsArray = JArray.Parse(credentials);

            Assert.AreEqual(2, credentialsArray.Count);
        }
        public async Task TestProverGetCredentialsWorksForFilterBySchema()
        {
            var filter = string.Format("{{\"schema_id\":\"{0}\"}}", gvtSchemaId);

            var credentials = await AnonCreds.ProverGetCredentialsAsync(wallet, filter);

            var credentialsArray = JArray.Parse(credentials);

            Assert.AreEqual(2, credentialsArray.Count);
        }
Exemple #17
0
        public async Task TestProverCreateProofWorksForInvalidMasterSecret()
        {
            var schemasJson        = new JObject(new JProperty(gvtSchemaId, JObject.Parse(gvtSchema))).ToString();
            var credentialDefsJson = new JObject(new JProperty(issuer1gvtCredDefId, JObject.Parse(issuer1gvtCredDef))).ToString();
            var revocStatesJson    = "{}";

            var ex = await Assert.ThrowsExceptionAsync <WalletItemNotFoundException>(() =>
                                                                                     AnonCreds.ProverCreateProofAsync(wallet, proofRequest, requestedCredentialsJson, "wrong_master_secret", schemasJson, credentialDefsJson, revocStatesJson)
                                                                                     );
        }
Exemple #18
0
        public async Task CreateProofRequestConnectionNotFound()
        {
            var ex = await Assert.ThrowsAsync <AriesFrameworkException>(async() => await _proofService.CreateRequestAsync(_issuerWallet, new ProofRequest
            {
                Name  = "Test",
                Nonce = await AnonCreds.GenerateNonceAsync()
            }, "bad-connection-id"));

            Assert.True(ex.ErrorCode == ErrorCode.RecordNotFound);
        }
Exemple #19
0
        public async Task TestProverStoreClaimOfferWorksForInvalidIssuerDid()
        {
            var claimOffer = "{\"issuer_did\":\"invalid_base58_string\",\"schema_seq_no\":1}";

            var ex = await Assert.ThrowsExceptionAsync <IndyException>(() =>
                                                                       AnonCreds.ProverStoreClaimOfferAsync(_wallet, claimOffer)
                                                                       );

            Assert.AreEqual(ErrorCode.CommonInvalidStructure, ex.ErrorCode);
        }
        public async Task TestProverGetClaimsForProofRequestWorksForInvalidPredicateType()
        {
            await InitCommonWallet();

            var filter = string.Format("{{\"schema_seq_no\":\"{0}\"}}", 1);

            var ex = await Assert.ThrowsExceptionAsync <InvalidStructureException>(() =>
                                                                                   AnonCreds.ProverGetCredentialsAsync(commonWallet, filter)
                                                                                   );
        }
Exemple #21
0
        public async Task TestProverStoreClaimOfferWorksForInvalidJson()
        {
            var claimOffer = "{\"issuer_did\":\"NcYxiDXkpYi6ov5FcYDi1e\"}";

            var ex = await Assert.ThrowsExceptionAsync <IndyException>(() =>
                                                                       AnonCreds.ProverStoreClaimOfferAsync(_wallet, claimOffer)
                                                                       );

            Assert.AreEqual(ErrorCode.CommonInvalidStructure, ex.ErrorCode);
        }
        public async Task TestProverGetClaimsWorksForEmptyFilter()
        {
            await InitCommonWallet();

            var claims = await AnonCreds.ProverGetCredentialsAsync(commonWallet, "{}");

            var claimsArray = JArray.Parse(claims);

            Assert.AreEqual(1, claimsArray.Count);
        }
        public async Task TestIssuerCreateAndStoreCredentialReqWorksForInvalidCredentialValues()
        {
            var credentialValues = "{\"sex\":\"male\",\n" +
                                   "        \"age\":\"28\"" +
                                   "       }";

            var ex = await Assert.ThrowsExceptionAsync <InvalidStructureException>(() =>
                                                                                   AnonCreds.IssuerCreateCredentialAsync(wallet, issuer1GvtCredOffer, issuer1GvtCredReq, credentialValues, null, null)
                                                                                   );
        }
Exemple #24
0
        /// <inheritdoc />
        public virtual async Task <string> ProcessCredentialAsync(IAgentContext agentContext, CredentialIssueMessage credential,
                                                                  ConnectionRecord connection)
        {
            var credentialAttachment = credential.Credentials.FirstOrDefault(x => x.Id == "libindy-cred-0")
                                       ?? throw new ArgumentException("Credential attachment not found");

            var credentialJson = credentialAttachment.Data.Base64.GetBytesFromBase64().GetUTF8String();
            var credentialJobj = JObject.Parse(credentialJson);
            var definitionId   = credentialJobj["cred_def_id"].ToObject <string>();
            var revRegId       = credentialJobj["rev_reg_id"]?.ToObject <string>();

            var credentialRecord = await Policy.Handle <AriesFrameworkException>()
                                   .RetryAsync(3, async(ex, retry) => { await Task.Delay((int)Math.Pow(retry, 2) * 100); })
                                   .ExecuteAsync(() => this.GetByThreadIdAsync(agentContext, credential.GetThreadId()));

            if (credentialRecord.State != CredentialState.Requested)
            {
                throw new AriesFrameworkException(ErrorCode.RecordInInvalidState,
                                                  $"Credential state was invalid. Expected '{CredentialState.Requested}', found '{credentialRecord.State}'");
            }
            var credentialDefinition = await LedgerService.LookupDefinitionAsync(agentContext, definitionId);

            string revocationRegistryDefinitionJson = null;

            if (!string.IsNullOrEmpty(revRegId))
            {
                // If credential supports revocation, lookup registry definition
                var revocationRegistry =
                    await LedgerService.LookupRevocationRegistryDefinitionAsync(agentContext, revRegId);

                revocationRegistryDefinitionJson      = revocationRegistry.ObjectJson;
                credentialRecord.RevocationRegistryId = revRegId;
            }

            var credentialId = await AnonCreds.ProverStoreCredentialAsync(
                wallet : agentContext.Wallet,
                credId : credentialRecord.Id,
                credReqMetadataJson : credentialRecord.CredentialRequestMetadataJson,
                credJson : credentialJson,
                credDefJson : credentialDefinition.ObjectJson,
                revRegDefJson : revocationRegistryDefinitionJson);

            credentialRecord.CredentialId = credentialId;
            await credentialRecord.TriggerAsync(CredentialTrigger.Issue);

            await RecordService.UpdateAsync(agentContext.Wallet, credentialRecord);

            EventAggregator.Publish(new ServiceMessageProcessingEvent
            {
                RecordId    = credentialRecord.Id,
                MessageType = credential.Type,
                ThreadId    = credential.GetThreadId()
            });
            return(credentialRecord.Id);
        }
        /// <inheritdoc />
        public async Task <bool> IsRevokedAsync(IAgentContext context, CredentialRecord record)
        {
            if (record.RevocationRegistryId == null)
            {
                return(false);
            }
            if (record.State == CredentialState.Offered || record.State == CredentialState.Requested)
            {
                return(false);
            }
            if (record.State == CredentialState.Revoked || record.State == CredentialState.Rejected)
            {
                return(true);
            }

            var now          = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            var proofRequest = new ProofRequest
            {
                Name                = "revocation check",
                Version             = "1.0",
                Nonce               = await AnonCreds.GenerateNonceAsync(),
                RequestedAttributes = new Dictionary <string, ProofAttributeInfo>
                {
                    { "referent1", new ProofAttributeInfo {
                          Name = record.CredentialAttributesValues.First().Name
                      } }
                }, NonRevoked = new RevocationInterval
                {
                    From = (uint)now,
                    To   = (uint)now
                }
            };

            var proof = await CreateProofAsync(context, proofRequest, new RequestedCredentials
            {
                RequestedAttributes = new Dictionary <string, RequestedAttribute>
                {
                    { "referent1", new RequestedAttribute {
                          CredentialId = record.CredentialId, Timestamp = now, Revealed = true
                      } }
                }
            });

            var isValid = await VerifyProofAsync(context, proofRequest.ToJson(), proof);

            if (!isValid)
            {
                await record.TriggerAsync(CredentialTrigger.Revoke);

                record.SetTag("LastRevocationCheck", now.ToString());
                await RecordService.UpdateAsync(context.Wallet, record);
            }

            return(!isValid);
        }
Exemple #26
0
        /// <inheritdoc />
        public virtual async Task <CredentialOfferMessage> CreateOfferAsync(Wallet wallet, DefaultCreateOfferConfiguration config)
        {
            Logger.LogInformation(LoggingEvents.CreateCredentialOffer, "DefinitionId {0}, ConnectionId {1}, IssuerDid {2}",
                                  config.CredentialDefinitionId, config.ConnectionId, config.IssuerDid);

            var connection = await ConnectionService.GetAsync(wallet, config.ConnectionId);

            var offerJson = await AnonCreds.IssuerCreateCredentialOfferAsync(wallet, config.CredentialDefinitionId);

            var nonce = JObject.Parse(offerJson)["nonce"].ToObject <string>();

            // Write offer record to local wallet
            var credentialRecord = new CredentialRecord
            {
                Id = Guid.NewGuid().ToString(),
                CredentialDefinitionId = config.CredentialDefinitionId,
                OfferJson    = offerJson,
                ValuesJson   = CredentialUtils.FormatCredentialValues(config.CredentialAttributeValues),
                State        = CredentialState.Offered,
                ConnectionId = connection.GetId(),
            };

            credentialRecord.Tags.Add(TagConstants.Nonce, nonce);
            credentialRecord.Tags.Add(TagConstants.Role, TagConstants.Issuer);
            credentialRecord.Tags.Add(TagConstants.ConnectionId, connection.GetId());

            if (!string.IsNullOrEmpty(config.IssuerDid))
            {
                credentialRecord.Tags.Add(TagConstants.IssuerDid, config.IssuerDid);
            }

            if (config.Tags != null)
            {
                foreach (var tag in config.Tags)
                {
                    if (!credentialRecord.Tags.Keys.Contains(tag.Key))
                    {
                        credentialRecord.Tags.Add(tag.Key, tag.Value);
                    }
                }
            }

            await RecordService.AddAsync(wallet, credentialRecord);

            var credentialOffer = await MessageSerializer.PackSealedAsync <CredentialOfferMessage>(
                new CredentialOfferDetails { OfferJson = offerJson },
                wallet,
                connection.MyVk,
                connection.TheirVk);

            credentialOffer.Type = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.CredentialOffer);

            return(credentialOffer);
        }
        /// <inheritdoc />
        public virtual async Task <List <Credential> > ListCredentialsForProofRequestAsync(IAgentContext agentContext,
                                                                                           ProofRequest proofRequest, string attributeReferent)
        {
            using (var search =
                       await AnonCreds.ProverSearchCredentialsForProofRequestAsync(agentContext.Wallet, proofRequest.ToJson()))
            {
                var searchResult = await search.NextAsync(attributeReferent, 100);

                return(JsonConvert.DeserializeObject <List <Credential> >(searchResult));
            }
        }
Exemple #28
0
        public async Task TestProverGetClaimOffersWorksForInvalidFilterJson()
        {
            await InitCommonWallet();

            var filter = string.Format("{{\"schema_seq_no\":\"{0}\"}}", 1);

            var ex = await Assert.ThrowsExceptionAsync <InvalidStructureException>(() =>
                                                                                   AnonCreds.ProverGetClaimOffersAsync(commonWallet, filter)

                                                                                   );
        }
        public async Task <ClaimDefinition> CreateClaimDefinitionAsync(string userId, Guid credentialSchemaId)
        {
            var schema = await _dbContext.CredentialSchemas.Include(p => p.User).FirstOrDefaultAsync(p => p.Id == credentialSchemaId);

            var schemaCreatorWalletData = await GetDefaultWalletDataAsync(schema.UserId);

            var walletData = await GetDefaultWalletDataAsync(userId);

            var wallet = await Wallet.OpenWalletAsync(walletData.Name, null, null);

            try
            {
                using (var pool = await PoolUtils.CreateAndOpenPoolLedgerAsync())
                {
                    var schemaData = JsonConvert.SerializeObject(new
                    {
                        name    = schema.Name,
                        version = schema.Version
                    });

                    var getSchemaRequest = await Ledger.BuildGetSchemaRequestAsync(walletData.Did, schemaCreatorWalletData.Did, schemaData);

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

                    var schemaValue  = JObject.Parse(getSchemaResponse).GetValue("result");
                    var claimDefJson = await AnonCreds.IssuerCreateAndStoreClaimDefAsync(wallet, walletData.Did, schemaValue.ToString(), "CL", false);

                    var claimDef        = JObject.Parse(claimDefJson);
                    var claimDefRequest = await Ledger.BuildClaimDefTxnAsync(walletData.Did, claimDef.Value <int>("ref"), claimDef.Value <string>("signature_type"), claimDef.GetValue("data").ToString());

                    var result = await Ledger.SignAndSubmitRequestAsync(pool, wallet, walletData.Did, claimDefRequest);

                    var claimDefinition = new ClaimDefinition
                    {
                        Id = Guid.NewGuid(),
                        CredentialSchemaId = credentialSchemaId,
                        UserId             = userId
                    };

                    _dbContext.ClaimDefinitions.Add(claimDefinition);
                    await _dbContext.SaveChangesAsync();

                    return(claimDefinition);
                }
            }
            catch (Exception ex)
            {
                throw;
            }
            finally
            {
                await wallet.CloseAsync();
            }
        }
Exemple #30
0
        public async Task TestProverCreateProofWorksForInvalidSchemas()
        {
            var schemasJson        = "{}";
            var credentialDefsJson = new JObject(new JProperty(issuer1gvtCredDefId, issuer1gvtCredDef)).ToString();
            var revocStatesJson    = "{}";

            var ex = await Assert.ThrowsExceptionAsync <InvalidStructureException>(() =>
                                                                                   AnonCreds.ProverCreateProofAsync(wallet, proofRequest, requestedCredentialsJson, masterSecretId, schemasJson, credentialDefsJson, revocStatesJson)

                                                                                   );
        }