/// <inheritdoc /> public virtual async Task <string> CreateProofAsync(IAgentContext agentContext, ProofRequest proofRequest, RequestedCredentials requestedCredentials) { 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, proofRequest.ToJson(), requestedCredentials.ToJson(), provisioningRecord.MasterSecretId, schemas, definitions, revocationStates); return(proofJson); }
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, // Ledger will not return correct revocation state if the 'from' field // is other than 0 from : 0, //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()); }
/// <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); }
/// <inheritdoc /> public Task <(RequestPresentationMessage, ProofRecord)> CreateRequestAsync( IAgentContext agentContext, ProofRequest proofRequest, string connectionId) =>
/// <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)); } }
/// <inheritdoc /> public async Task <(RequestPresentationMessage, ProofRecord)> CreateRequestFromProposalAsync(IAgentContext agentContext, ProofRequestParameters requestParams, string proofRecordId, string connectionId) { Logger.LogInformation(LoggingEvents.CreateProofRequest, "ConnectionId {0}", connectionId); if (proofRecordId == null) { throw new ArgumentNullException(nameof(proofRecordId), "You must provide proof record Id"); } if (connectionId != null) { var connection = await ConnectionService.GetAsync(agentContext, connectionId); if (connection.State != ConnectionState.Connected) { throw new AriesFrameworkException(ErrorCode.RecordInInvalidState, $"Connection state was invalid. Expected '{ConnectionState.Connected}', found '{connection.State}'"); } } var proofRecord = await RecordService.GetAsync <ProofRecord>(agentContext.Wallet, proofRecordId); var proofProposal = proofRecord.ProposalJson.ToObject <ProofProposal>(); // Build Proof Request from Proposal info var proofRequest = new ProofRequest { Name = requestParams.Name, Version = requestParams.Version, Nonce = await AnonCreds.GenerateNonceAsync(), RequestedAttributes = new Dictionary <string, ProofAttributeInfo>(), NonRevoked = requestParams.NonRevoked }; var attributesByReferent = new Dictionary <string, List <ProposedAttribute> >(); foreach (var proposedAttribute in proofProposal.ProposedAttributes) { if (proposedAttribute.Referent == null) { proposedAttribute.Referent = Guid.NewGuid().ToString(); } if (attributesByReferent.TryGetValue(proposedAttribute.Referent, out var referentAttributes)) { referentAttributes.Add(proposedAttribute); } else { attributesByReferent.Add(proposedAttribute.Referent, new List <ProposedAttribute> { proposedAttribute }); } } foreach (var referent in attributesByReferent.AsEnumerable()) { var proposedAttributes = referent.Value; var attributeName = proposedAttributes.Count() == 1 ? proposedAttributes.Single().Name : null; var attributeNames = proposedAttributes.Count() > 1 ? proposedAttributes.ConvertAll <string>(r => r.Name).ToArray() : null; var requestedAttribute = new ProofAttributeInfo() { Name = attributeName, Names = attributeNames, Restrictions = new List <AttributeFilter> { new AttributeFilter { CredentialDefinitionId = proposedAttributes.First().CredentialDefinitionId, SchemaId = proposedAttributes.First().SchemaId, IssuerDid = proposedAttributes.First().IssuerDid } } }; proofRequest.RequestedAttributes.Add(referent.Key, requestedAttribute); Console.WriteLine($"Added Attribute to Proof Request \n {proofRequest.ToString()}"); } foreach (var pred in proofProposal.ProposedPredicates) { if (pred.Referent == null) { pred.Referent = Guid.NewGuid().ToString(); } var predicate = new ProofPredicateInfo() { Name = pred.Name, PredicateType = pred.Predicate, PredicateValue = pred.Threshold, Restrictions = new List <AttributeFilter> { new AttributeFilter { CredentialDefinitionId = pred.CredentialDefinitionId, SchemaId = pred.SchemaId, IssuerDid = pred.IssuerDid } } }; proofRequest.RequestedPredicates.Add(pred.Referent, predicate); } proofRecord.RequestJson = proofRequest.ToJson(); await proofRecord.TriggerAsync(ProofTrigger.Request); await RecordService.UpdateAsync(agentContext.Wallet, proofRecord); var message = new RequestPresentationMessage { Id = proofRecord.Id, Requests = new[] { new Attachment { Id = "libindy-request-presentation-0", MimeType = CredentialMimeTypes.ApplicationJsonMimeType, Data = new AttachmentContent { Base64 = proofRequest .ToJson() .GetUTF8Bytes() .ToBase64String() } } } }; message.ThreadFrom(proofRecord.GetTag(TagConstants.LastThreadId)); return(message, proofRecord); }
/// <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); var result = JsonConvert.DeserializeObject <List <Credential> >(searchResult); if (proofRequest.NonRevoked != null) { return(result.Where(x => x.CredentialInfo.RevocationRegistryId != null).ToList()); } return(result); } }