예제 #1
0
        async Task <IssuanceDetailsDto> IssueIdpAttributesAsRoot(
            string issuer,
            ConfidentialAccount confidentialAccount,
            Identity identity,
            IEnumerable <AttributeIssuanceDetails> attributeIssuanceDetails,
            AccountDescriptor account,
            StatePersistency statePersistency)
        {
            IssuanceDetailsDto issuanceDetails = new IssuanceDetailsDto();

            IEnumerable <IdentitiesScheme> identitiesSchemes = _dataAccessService.GetAttributesSchemeByIssuer(issuer, true);

            var rootAttributeDetails = attributeIssuanceDetails.First(a => a.Definition.IsRoot);

            byte[] rootAssetId = await _assetsService.GenerateAssetId(rootAttributeDetails.Definition.SchemeName, rootAttributeDetails.Value.Value, issuer).ConfigureAwait(false);

            IdentityAttribute rootAttribute = identity.Attributes.FirstOrDefault(a => a.AttributeName == rootAttributeDetails.Definition.AttributeName);

            statePersistency.TransactionsService.IssueBlindedAsset(rootAssetId, 0UL.ToByteArray(32), out byte[] originatingCommitment);
            _dataAccessService.UpdateIdentityAttributeCommitment(rootAttribute.AttributeId, originatingCommitment);
            issuanceDetails.AssociatedAttributes
                = await IssueAssociatedAttributes(
                      attributeIssuanceDetails.Where(a => !a.Definition.IsRoot)
                      .ToDictionary(d => identity.Attributes.First(a => a.AttributeName == d.Definition.AttributeName).AttributeId, d => d),
                      statePersistency.TransactionsService,
                      issuer, rootAssetId).ConfigureAwait(false);

            var packet = statePersistency.TransactionsService.TransferAssetToUtxo(rootAssetId, confidentialAccount);

            if (packet == null)
            {
                _logger.Error($"[{account.AccountId}]: failed to transfer Root Attribute");
                throw new RootAttributeTransferFailedException();
            }

            issuanceDetails.RootAttribute = new IssuanceDetailsDto.IssuanceDetailsRoot
            {
                AttributeName         = rootAttribute.AttributeName,
                OriginatingCommitment = packet.SurjectionProof.AssetCommitments[0].ToHexString(),
                AssetCommitment       = packet.TransferredAsset.AssetCommitment.ToHexString(),
                SurjectionProof       = $"{packet.SurjectionProof.Rs.E.ToHexString()}{packet.SurjectionProof.Rs.S[0].ToHexString()}"
            };

            return(issuanceDetails);
        }
예제 #2
0
        public async Task <ActionResult <IEnumerable <AttributeValue> > > IssueIdpAttributes(string issuer, [FromBody] IssueAttributesRequestDTO request)
        {
            if (request is null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            AccountDescriptor account          = _accountsService.GetByPublicKey(issuer.HexStringToByteArray());
            StatePersistency  statePersistency = _executionContextManager.ResolveStateExecutionServices(account.AccountId);

            IEnumerable <AttributeDefinition> attributeDefinitions = _dataAccessService.GetAttributesSchemeByIssuer(issuer, true)
                                                                     .Select(a => new AttributeDefinition
            {
                SchemeId      = a.IdentitiesSchemeId,
                AttributeName = a.AttributeName,
                SchemeName    = a.AttributeSchemeName,
                Alias         = a.Alias,
                Description   = a.Description,
                IsActive      = a.IsActive,
                IsRoot        = a.CanBeRoot
            });

            if (!attributeDefinitions.Any(a => a.IsRoot))
            {
                throw new NoRootAttributeSchemeDefinedException(issuer);
            }

            var issuanceInputDetails = GetValidatedIssuanceDetails(request, attributeDefinitions);

            Identity identity = CreateIdentityInDb(account, issuanceInputDetails);

            IssuanceDetailsDto issuanceDetails;

            if (!string.IsNullOrEmpty(request.PublicSpendKey) && !string.IsNullOrEmpty(request.PublicViewKey))
            {
                ConfidentialAccount targetAccount = new ConfidentialAccount
                {
                    PublicSpendKey = request.PublicSpendKey.HexStringToByteArray(),
                    PublicViewKey  = request.PublicViewKey.HexStringToByteArray()
                };

                issuanceDetails = await IssueIdpAttributesAsRoot(issuer, request.Protection, identity, issuanceInputDetails, account, targetAccount, statePersistency).ConfigureAwait(false);
            }
            else
            {
                issuanceDetails = await IssueIdpAttributesAsAssociated(issuer, identity, issuanceInputDetails, statePersistency).ConfigureAwait(false);
            }

            await _idenitiesHubContext.Clients.Group(account.AccountId.ToString()).SendAsync("RequestForIssuance", issuanceDetails);

            IIntegrationIdP integrationService = GetIntegrationService(account.AccountId);

            if (integrationService != null)
            {
                IssuanceDetails issuanceIntegration = new IssuanceDetails
                {
                    RootAttribute = new IssuanceDetails.IssuanceDetailsRoot
                    {
                        AttributeName         = issuanceDetails.RootAttribute.AttributeName,
                        AssetCommitment       = issuanceDetails.RootAttribute.AssetCommitment.HexStringToByteArray(),
                        OriginatingCommitment = issuanceDetails.RootAttribute.OriginatingCommitment.HexStringToByteArray(),
                        SurjectionProof       = issuanceDetails.RootAttribute.SurjectionProof.HexStringToByteArray()
                    },
                    AssociatedAttributes = issuanceDetails.AssociatedAttributes
                                           .Select(a =>
                                                   new IssuanceDetails.IssuanceDetailsAssociated
                    {
                        AttributeName           = a.AttributeName,
                        AssetCommitment         = a.AssetCommitment.HexStringToByteArray(),
                        BindingToRootCommitment = a.BindingToRootCommitment.HexStringToByteArray()
                    }).ToList()
                };

                integrationService.IssueAttributes(account.AccountId, issuanceIntegration);
            }

            var attributeValues = FillAttributeValues(request.Attributes, attributeDefinitions);

            return(Ok(attributeValues));

            #region Internal Functions

            IReadOnlyCollection <AttributeValue> FillAttributeValues(Dictionary <string, IssueAttributesRequestDTO.AttributeValue> attributes,
                                                                     IEnumerable <AttributeDefinition> attributeDefinitions)
            {
                List <AttributeValue> attributeValues = new List <AttributeValue>();
                var protectionAttrDefinition          = attributeDefinitions.FirstOrDefault(a => a.SchemeName == AttributesSchemes.ATTR_SCHEME_NAME_PASSWORD);

                foreach (var attributeName in attributes.Keys.Where(a => protectionAttrDefinition?.AttributeName != a))
                {
                    string content = attributes[attributeName].Value;

                    AttributeValue attributeValue = new AttributeValue
                    {
                        Value      = content,
                        Definition = attributeDefinitions.FirstOrDefault(d => d.AttributeName == attributeName)
                    };
                    attributeValues.Add(attributeValue);
                }

                return(new ReadOnlyCollection <AttributeValue>(attributeValues));
            }

            async Task <IssuanceDetailsDto> IssueIdpAttributesAsRoot(
                string issuer,
                IssuanceProtection protection,
                Identity identity,
                IEnumerable <AttributeIssuanceDetails> attributeIssuanceDetails,
                AccountDescriptor account,
                ConfidentialAccount targetAccount,
                StatePersistency statePersistency)
            {
                IssuanceDetailsDto issuanceDetails = new IssuanceDetailsDto();

                IEnumerable <IdentitiesScheme> identitiesSchemes = _dataAccessService.GetAttributesSchemeByIssuer(issuer, true);

                var rootAttributeDetails = attributeIssuanceDetails.First(a => a.Definition.IsRoot);

                byte[] rootAssetId = await _assetsService.GenerateAssetId(rootAttributeDetails.Definition.SchemeName, rootAttributeDetails.Value.Value, issuer).ConfigureAwait(false);

                IdentityAttribute rootAttribute = identity.Attributes.FirstOrDefault(a => a.AttributeName == rootAttributeDetails.Definition.AttributeName);

                if (!CreateRootAttributeIfNeeded(statePersistency, rootAttribute, rootAssetId))
                {
                    var  protectionAttribute = identity.Attributes.FirstOrDefault(a => a.AttributeName == AttributesSchemes.ATTR_SCHEME_NAME_PASSWORD);
                    bool res = VerifyProtectionAttribute(protectionAttribute,
                                                         protection.SignatureE.HexStringToByteArray(),
                                                         protection.SignatureS.HexStringToByteArray(),
                                                         protection.SessionCommitment.HexStringToByteArray());

                    if (!res)
                    {
                        _logger.Warning($"[{account.AccountId}]: Failed to verify Surjection Proofs of the Protection Attribute");
                        throw new ProtectionAttributeVerificationFailedException();
                    }
                }
                else
                {
                    issuanceDetails.AssociatedAttributes
                        = await IssueAssociatedAttributes(
                              attributeIssuanceDetails.Where(a => !a.Definition.IsRoot)
                              .ToDictionary(d => identity.Attributes.First(a => a.AttributeName == d.Definition.AttributeName).AttributeId, d => d),
                              statePersistency.TransactionsService,
                              issuer, rootAssetId).ConfigureAwait(false);
                }

                var packet = TransferAssetToUtxo(statePersistency.TransactionsService, targetAccount, rootAssetId);

                if (packet == null)
                {
                    _logger.Error($"[{account.AccountId}]: failed to transfer Root Attribute");
                    throw new RootAttributeTransferFailedException();
                }

                _dataAccessService.AddOrUpdateIdentityTarget(identity.IdentityId, targetAccount.PublicSpendKey.ToHexString(), targetAccount.PublicViewKey.ToHexString());

                issuanceDetails.RootAttribute = new IssuanceDetailsDto.IssuanceDetailsRoot
                {
                    AttributeName         = rootAttribute.AttributeName,
                    OriginatingCommitment = packet.SurjectionProof.AssetCommitments[0].ToHexString(),
                    AssetCommitment       = packet.TransferredAsset.AssetCommitment.ToHexString(),
                    SurjectionProof       = $"{packet.SurjectionProof.Rs.E.ToHexString()}{packet.SurjectionProof.Rs.S[0].ToHexString()}"
                };

                return(issuanceDetails);
            }

            async Task <IssuanceDetailsDto> IssueIdpAttributesAsAssociated(
                string issuer,
                Identity identity,
                IEnumerable <AttributeIssuanceDetails> attributeIssuanceDetails,
                StatePersistency statePersistency)
            {
                IssuanceDetailsDto issuanceDetails = new IssuanceDetailsDto();

                IdentitiesScheme rootScheme = _dataAccessService.GetRootIdentityScheme(issuer);

                IEnumerable <IdentitiesScheme> identitiesSchemes = _dataAccessService.GetAttributesSchemeByIssuer(issuer, true);
                var rootAttributeDetails = attributeIssuanceDetails.First(a => a.Definition.IsRoot);

                var packet = await IssueAssociatedAttribute(
                    rootScheme.AttributeSchemeName,
                    rootAttributeDetails.Value.Value,
                    rootAttributeDetails.Value.BlindingPointValue,
                    rootAttributeDetails.Value.BlindingPointRoot,
                    issuer,
                    statePersistency.TransactionsService).ConfigureAwait(false);

                _dataAccessService.UpdateIdentityAttributeCommitment(identity.Attributes.FirstOrDefault(a => a.AttributeName == rootScheme.AttributeName).AttributeId, packet.AssetCommitment);

                byte[] rootAssetId = _assetsService.GenerateAssetId(rootScheme.IdentitiesSchemeId, rootAttributeDetails.Value.Value);
                issuanceDetails.AssociatedAttributes = await IssueAssociatedAttributes(
                    attributeIssuanceDetails
                    .ToDictionary(d => identity.Attributes.First(a => a.AttributeName == d.Definition.AttributeName).AttributeId, d => d),
                    statePersistency.TransactionsService,
                    issuer, rootAssetId).ConfigureAwait(false);

                return(issuanceDetails);
            }