/// <inheritdoc />
        public virtual async Task <ProofRequestMessage> CreateProofRequestAsync(Wallet wallet, string connectionId,
                                                                                string proofRequestJson)
        {
            Logger.LogInformation(LoggingEvents.CreateProofRequest, "ConnectionId {0}", connectionId);

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

            var proofJobj = JObject.Parse(proofRequestJson);

            var proofRecord = new ProofRecord
            {
                Id           = Guid.NewGuid().ToString(),
                ConnectionId = connection.ConnectionId,
                RequestJson  = proofRequestJson
            };

            proofRecord.Tags[TagConstants.Nonce]        = proofJobj["nonce"].ToObject <string>();
            proofRecord.Tags[TagConstants.ConnectionId] = connection.GetId();
            proofRecord.Tags[TagConstants.Role]         = TagConstants.Requestor;

            await RecordService.AddAsync(wallet, proofRecord);

            var proofRequest = await MessageSerializer.PackSealedAsync <ProofRequestMessage>(
                new ProofRequestDetails { ProofRequestJson = proofRequestJson },
                wallet,
                connection.MyVk,
                connection.TheirVk);

            proofRequest.Type = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.ProofRequest);

            return(proofRequest);
        }
예제 #2
0
        public async Task CanParseDidPattern()
        {
            var did = await Did.CreateAndStoreMyDidAsync(_wallet, "{}");

            var messageType = MessageUtils.FormatDidMessageType(did.Did, MessageTypes.ConnectionRequest);

            var(parsedDid, parsedType) = MessageUtils.ParseMessageType(messageType);

            Assert.Equal(did.Did, parsedDid);
            Assert.Equal(parsedType, MessageTypes.ConnectionRequest);
        }
예제 #3
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 <ProofMessage> CreateProofAsync(Wallet wallet, Pool pool, string proofRequestId,
                                                                  RequestedCredentials requestedCredentials)
        {
            var record = await RecordService.GetAsync <ProofRecord>(wallet, proofRequestId);

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

            var provisioningRecord = await ProvisioningService.GetProvisioningAsync(wallet);

            var credentialObjects = new List <CredentialInfo>();

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

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

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

            var revocationStates = await BuildRevocationStatesAsync(pool,
                                                                    credentialObjects,
                                                                    requestedCredentials);

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

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

            await RecordService.UpdateAsync(wallet, record);

            var proof = await MessageSerializer.PackSealedAsync <ProofMessage>(
                new ProofDetails
            {
                ProofJson    = proofJson,
                RequestNonce = JsonConvert.DeserializeObject <ProofRequest>(record.RequestJson).Nonce
            }, wallet, connection.MyVk, connection.TheirVk);

            proof.Type = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.DisclosedProof);

            return(proof);
        }
예제 #5
0
        public void CanConvertEnvelopeMessage()
        {
            var type = MessageUtils.FormatDidMessageType("3NnbYBdhyHfuFZnbaZhuU6", MessageTypes.Forward);

            var expected = new ForwardEnvelopeMessage {
                Type = type
            };
            var json = JsonConvert.SerializeObject(expected);

            var actual = JsonConvert.DeserializeObject <IEnvelopeMessage>(json);

            Assert.IsType <ForwardEnvelopeMessage>(actual);
            Assert.Equal(type, ((ForwardEnvelopeMessage)actual).Type);
        }
        /// <inheritdoc />
        public virtual async Task SendProofRequestAsync(Wallet wallet, string connectionId, string proofRequestJson)
        {
            Logger.LogInformation(LoggingEvents.SendProofRequest, "ConnectionId {0}", connectionId);

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

            var request = await CreateProofRequestAsync(wallet, connectionId, proofRequestJson);

            await RouterService.ForwardAsync(new ForwardEnvelopeMessage
            {
                Content = request.ToJson(),
                Type    = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.Forward)
            }, connection.Endpoint);
        }
        /// <inheritdoc />
        public virtual async Task AcceptProofRequestAsync(Wallet wallet, Pool pool, string proofRequestId,
                                                          RequestedCredentials requestedCredentials)
        {
            var request = await RecordService.GetAsync <ProofRecord>(wallet, proofRequestId);

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

            var proof = await CreateProofAsync(wallet, pool, proofRequestId, requestedCredentials);

            await RouterService.ForwardAsync(new ForwardEnvelopeMessage
            {
                Content = proof.ToJson(),
                Type    = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.Forward)
            }, connection.Endpoint);
        }
예제 #8
0
        /// <inheritdoc />
        public virtual async Task SendOfferAsync(Wallet wallet, DefaultCreateOfferConfiguration config)
        {
            Logger.LogInformation(LoggingEvents.SendCredentialOffer, "DefinitionId {0}, ConnectionId {1}, IssuerDid {2}",
                                  config.CredentialDefinitionId, config.ConnectionId, config.IssuerDid);

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

            var offer = await CreateOfferAsync(wallet, config);

            await RouterService.ForwardAsync(new ForwardEnvelopeMessage
            {
                Content = offer.ToJson(),
                Type    = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.Forward)
            }, connection.Endpoint);
        }
예제 #9
0
        /// <inheritdoc />
        public virtual async Task AcceptOfferAsync(Wallet wallet, Pool pool, string credentialId,
                                                   Dictionary <string, string> attributeValues = null)
        {
            var credential = await RecordService.GetAsync <CredentialRecord>(wallet, credentialId);

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

            var definition =
                await LedgerService.LookupDefinitionAsync(pool, connection.MyDid, credential.CredentialDefinitionId);

            var provisioning = await ProvisioningService.GetProvisioningAsync(wallet);

            var request = await AnonCreds.ProverCreateCredentialReqAsync(wallet, connection.MyDid, credential.OfferJson,
                                                                         definition.ObjectJson, provisioning.MasterSecretId);

            // Update local credential record with new info
            credential.CredentialRequestMetadataJson = request.CredentialRequestMetadataJson;

            var details = new CredentialRequestDetails
            {
                OfferJson             = credential.OfferJson,
                CredentialRequestJson = request.CredentialRequestJson,
                CredentialValuesJson  = CredentialUtils.FormatCredentialValues(attributeValues)
            };

            var requestMessage =
                await MessageSerializer.PackSealedAsync <CredentialRequestMessage>(details, wallet, connection.MyVk,
                                                                                   connection.TheirVk);

            requestMessage.Type =
                MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.CredentialRequest);

            await credential.TriggerAsync(CredentialTrigger.Request);

            await RecordService.UpdateAsync(wallet, credential);

            //TODO we need roll back, i.e if we fail to send the A2A message the credential record should revert to Offer phase
            //so the user can resend
            await RouterService.ForwardAsync(new ForwardEnvelopeMessage
            {
                Content = requestMessage.ToJson(),
                Type    = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.Forward)
            }, connection.Endpoint);
        }
예제 #10
0
        /// <inheritdoc />
        public virtual async Task AcceptRequestAsync(Wallet wallet, string connectionId)
        {
            Logger.LogInformation(LoggingEvents.AcceptConnectionRequest, "ConnectionId {0}", connectionId);

            var connection = await GetAsync(wallet, connectionId);

            await connection.TriggerAsync(ConnectionTrigger.Request);

            await Pairwise.CreateAsync(wallet, connection.TheirDid, connection.MyDid, connection.Endpoint.ToJson());

            await RecordService.UpdateAsync(wallet, connection);

            // Send back response message
            var provisioning = await ProvisioningService.GetProvisioningAsync(wallet);

            var response = new ConnectionDetails
            {
                Did      = connection.MyDid,
                Endpoint = provisioning.Endpoint,
                Verkey   = connection.MyVk
            };

            var responseMessage =
                await MessageSerializer.PackSealedAsync <ConnectionResponseMessage>(response, wallet, connection.MyVk,
                                                                                    connection.TheirVk);

            responseMessage.Type =
                MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.ConnectionResponse);
            responseMessage.To = connection.TheirDid;

            var forwardMessage = new ForwardEnvelopeMessage
            {
                Type    = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.Forward),
                Content = responseMessage.ToJson()
            };

            await RouterService.ForwardAsync(forwardMessage, connection.Endpoint);
        }
예제 #11
0
        /// <inheritdoc />
        public virtual async Task IssueCredentialAsync(Pool pool, Wallet wallet, string issuerDid, string credentialId,
                                                       Dictionary <string, string> values)
        {
            var credentialRecord = await RecordService.GetAsync <CredentialRecord>(wallet, credentialId);

            if (values != null && values.Count > 0)
            {
                credentialRecord.ValuesJson = CredentialUtils.FormatCredentialValues(values);
            }

            var definitionRecord =
                await SchemaService.GetCredentialDefinitionAsync(wallet, credentialRecord.CredentialDefinitionId);

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

            if (credentialRecord.State != CredentialState.Requested)
            {
                throw new Exception(
                          $"Credential sate was invalid. Expected '{CredentialState.Requested}', found '{credentialRecord.State}'");
            }

            string            revocationRegistryId = null;
            BlobStorageReader tailsReader          = null;

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

                var revocationRecord = revocationRecordSearch.First();

                revocationRegistryId = revocationRecord.RevocationRegistryId;
                tailsReader          = await TailsService.OpenTailsAsync(revocationRecord.TailsFile);
            }

            var issuedCredential = await AnonCreds.IssuerCreateCredentialAsync(wallet, credentialRecord.OfferJson,
                                                                               credentialRecord.RequestJson, credentialRecord.ValuesJson, revocationRegistryId, tailsReader);

            if (definitionRecord.SupportsRevocation)
            {
                await LedgerService.SendRevocationRegistryEntryAsync(wallet, pool, issuerDid,
                                                                     revocationRegistryId,
                                                                     "CL_ACCUM", issuedCredential.RevocRegDeltaJson);

                credentialRecord.CredentialRevocationId = issuedCredential.RevocId;
            }

            var credentialDetails = new CredentialDetails
            {
                CredentialJson       = issuedCredential.CredentialJson,
                RevocationRegistryId = revocationRegistryId
            };

            await credentialRecord.TriggerAsync(CredentialTrigger.Issue);

            await RecordService.UpdateAsync(wallet, credentialRecord);

            var credential = await MessageSerializer.PackSealedAsync <CredentialMessage>(credentialDetails, wallet,
                                                                                         connection.MyVk,
                                                                                         connection.TheirVk);

            credential.Type = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.Credential);

            await RouterService.ForwardAsync(new ForwardEnvelopeMessage
            {
                Content = credential.ToJson(),
                Type    = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.Forward)
            }, connection.Endpoint);
        }