Example #1
0
        private async Task VerifyProofToAssociatedAttributeKnowledge(UniversalProofs universalProofs, string schemeName)
        {
            AttributeProofs attr = universalProofs.IssuersAttributes?.FirstOrDefault(a => a.Issuer.Equals(universalProofs.Issuer))?.Attributes.FirstOrDefault(a => a.SchemeName == schemeName);

            if (attr == null)
            {
                throw new AssociatedAttrProofsAreMissingException(schemeName);
            }

            if (attr.CommitmentProof.SurjectionProof.AssetCommitments.Length != attr.BindingProof.AssetCommitments.Length)
            {
                throw new AssociatedAttrProofsMalformedException(schemeName);
            }

            if (!ConfidentialAssetsHelper.VerifySurjectionProof(attr.CommitmentProof.SurjectionProof, attr.Commitment.ArraySegment.Array))
            {
                throw new AssociatedAttrProofToValueKnowledgeIncorrectException(schemeName);
            }

            IKey commitmentKey = universalProofs.IssuersAttributes.FirstOrDefault(a => a.Issuer.Equals(universalProofs.Issuer))?.RootAttribute.Commitment;

            byte[] commitment = ConfidentialAssetsHelper.SumCommitments(commitmentKey.Value.Span, attr.Commitment.Value.Span);
            if (!ConfidentialAssetsHelper.VerifySurjectionProof(attr.BindingProof, commitment))
            {
                throw new AssociatedAttrProofToBindingIncorrectException(schemeName);
            }

            (Memory <byte> issuanceCommitment, Memory <byte> commitmentToRoot)[] attrs = new (Memory <byte>, Memory <byte>)[attr.BindingProof.AssetCommitments.Length];
Example #2
0
        public IActionResult SendOnboardingWithValidationsRequest([FromBody] UserAttributeTransferWithValidationsDto userAttributeTransferWithValidations)
        {
            ulong accountId = ulong.Parse(User.Identity.Name, CultureInfo.InvariantCulture);
            bool  res       = false;

            UtxoPersistency utxoPersistency = _executionContextManager.ResolveUtxoExecutionServices(accountId);

            var rootAttribute = _dataAccessService.GetUserAttributes(accountId).FirstOrDefault(u => !u.IsOverriden && u.AttributeType == _identityAttributesService.GetRootAttributeType().Item1);

            string blindingFactorSeedString = $"{rootAttribute.Content}{userAttributeTransferWithValidations.Password}";

            byte[] blindingFactorSeed        = ConfidentialAssetsHelper.FastHash256(Encoding.ASCII.GetBytes(blindingFactorSeedString));
            byte[] blindingFactor            = ConfidentialAssetsHelper.ReduceScalar32(blindingFactorSeed);
            byte[] blindingPoint             = ConfidentialAssetsHelper.GetPublicKey(blindingFactor);
            byte[] rootNonBlindedCommitment  = ConfidentialAssetsHelper.GetNonblindedAssetCommitment(rootAttribute.AssetId);
            byte[] rootOriginatingCommitment = ConfidentialAssetsHelper.SumCommitments(rootNonBlindedCommitment, blindingPoint);

            byte[] target = userAttributeTransferWithValidations.UserAttributeTransfer.Target.HexStringToByteArray();
            _dataAccessService.GetAccountId(target, out ulong spAccountId);

            AssociatedProofPreparation[] associatedProofPreparations = null;

            IEnumerable <SpIdenitityValidation> spIdenitityValidations = _dataAccessService.GetSpIdenitityValidations(spAccountId);

            if (spIdenitityValidations != null && spIdenitityValidations.Count() > 0)
            {
                associatedProofPreparations = new AssociatedProofPreparation[spIdenitityValidations.Count()];

                var associatedAttributes = _dataAccessService.GetUserAssociatedAttributes(accountId);

                int index = 0;
                foreach (var validation in spIdenitityValidations)
                {
                    string attrContent = associatedAttributes.FirstOrDefault(a => a.Item1 == validation.AttributeType)?.Item2 ?? string.Empty;
                    byte[] groupId     = _identityAttributesService.GetGroupId(validation.AttributeType);
                    byte[] assetId     = validation.AttributeType != AttributeType.DateOfBirth ? _assetsService.GenerateAssetId(validation.AttributeType, attrContent) : rootAttribute.AssetId;
                    byte[] associatedBlindingFactor        = validation.AttributeType != AttributeType.DateOfBirth ? ConfidentialAssetsHelper.GetRandomSeed() : null;
                    byte[] associatedCommitment            = validation.AttributeType != AttributeType.DateOfBirth ? ConfidentialAssetsHelper.GetAssetCommitment(assetId, associatedBlindingFactor) : null;
                    byte[] associatedNonBlindedCommitment  = ConfidentialAssetsHelper.GetNonblindedAssetCommitment(assetId);
                    byte[] associatedOriginatingCommitment = ConfidentialAssetsHelper.SumCommitments(associatedNonBlindedCommitment, blindingPoint);

                    AssociatedProofPreparation associatedProofPreparation = new AssociatedProofPreparation {
                        GroupId = groupId, Commitment = associatedCommitment, CommitmentBlindingFactor = associatedBlindingFactor, OriginatingAssociatedCommitment = associatedOriginatingCommitment, OriginatingBlindingFactor = blindingFactor, OriginatingRootCommitment = rootOriginatingCommitment
                    };

                    associatedProofPreparations[index++] = associatedProofPreparation;
                }
            }

            SendOnboardingRequest(userAttributeTransferWithValidations.UserAttributeTransfer, utxoPersistency.TransactionsService, associatedProofPreparations);

            return(Ok(res));
        }
Example #3
0
        public async Task <IActionResult> RegisterPerson([FromBody] BiometricPersonDataDto biometricPersonData)
        {
            byte[] imageContent = null;

            _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}, {biometricPersonData.Images?.Count ?? -1} {nameof(biometricPersonData.Images)}");
            Contract.Requires(biometricPersonData != null, nameof(biometricPersonData));
            Contract.Requires(biometricPersonData.Images != null, $"{nameof(biometricPersonData)}.{nameof(biometricPersonData.Images)}");
            Contract.Requires(biometricPersonData.Images.Count > 0, $"Count {nameof(biometricPersonData)}.{nameof(biometricPersonData.Images)} > 0");

            foreach (var image in biometricPersonData.Images)
            {
                _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}, {nameof(image.Key)}={image.Key}, image length: {image.Value?.Length ?? -1}");
            }

            TaskCompletionSource <InherenceData> taskCompletionSource = _inherenceService.GetIdentityProofsAwaiter(biometricPersonData.SessionKey);

            InherenceData inherenceData;

            if (taskCompletionSource.Task.IsCompleted)
            {
                inherenceData = taskCompletionSource.Task.Result;
            }
            else
            {
                try
                {
                    inherenceData = await taskCompletionSource.Task.TimeoutAfter(30000).ConfigureAwait(false);
                }
                catch (TimeoutException ex)
                {
                    _logger.Error($"[{_inherenceService.AccountId}]: Identity Proofs not received for the SessionKey {biometricPersonData.SessionKey}", ex);
                    return(BadRequest("Identity Proofs not received"));
                }
                catch (Exception ex)
                {
                    _logger.Error($"[{_inherenceService.AccountId}]: Identity Proofs failed", ex);
                    return(BadRequest($"Identity Proofs failed: {ex.Message}"));
                }
                finally
                {
                    _inherenceService.RemoveIdentityProofsAwaiter(biometricPersonData.SessionKey);
                }
            }

            _inherenceService.RemoveIdentityProofsAwaiter(biometricPersonData.SessionKey);

            if (inherenceData == null)
            {
                _logger.Error($"[{_inherenceService.AccountId}]: Identity Proofs failed for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}");
                return(BadRequest("Identity Proofs failed"));
            }

            _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, {nameof(InherenceData)} with {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey} obtained");

            string registrationKey = inherenceData.RootRegistrationProof.AssetCommitments[0].ToHexString();

            _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, root commitment is {inherenceData.AssetRootCommitment.ToHexString()} and registration key is {registrationKey} for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey} obtained");

            string personGroupId = _portalConfiguration.DemoMode ? _portalConfiguration.FacePersonGroupId.ToLower() : inherenceData.Issuer.ToHexString().ToLower();

            string commitmentToRoot = inherenceData.AssetRootCommitment.ToHexString();

            if (!ConfidentialAssetsHelper.VerifySurjectionProof(inherenceData.RootRegistrationProof, inherenceData.AssetRootCommitment))
            {
                _logger.Error($"[{_inherenceService.AccountId}]: Registration Proofs failed for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}");
                throw new InherenceRegistrationProofsIncorrectException();
            }

            if (inherenceData.AssociatedRootCommitment != null)
            {
                //=============================================================================
                // In the case when AssociatedRootCommitment is not null one of the following scenarios can occur:
                //   1. The user already has Root Inherence Protection attribute - in this case
                //      image provided for registration must be checked for compliance with the existing factor
                //   2. The user does not have yet Root Protection attribute - in this case user must provide two images,
                //      one for the Root Inherence protection attribute and the second for associated one.
                //      Both images must be checked for matching and then two attributes will be created.
                //=============================================================================

                _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, {nameof(InherenceData)} with {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey} contains {nameof(inherenceData.AssociatedRootCommitment)}");

                byte[] commitment = ConfidentialAssetsHelper.SumCommitments(inherenceData.AssetRootCommitment, inherenceData.AssociatedRootCommitment);

                if (!ConfidentialAssetsHelper.VerifySurjectionProof(inherenceData.AssociatedRegistrationProof, commitment))
                {
                    _logger.Error($"[{_inherenceService.AccountId}]: {nameof(inherenceData.AssociatedRegistrationProof)} failed for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}");
                    return(BadRequest(Resources.ERR_INHERENCE_REGISTRATION_PROOFS_INCORRECT));
                }

                string commitmentToAssociated    = inherenceData.AssociatedRootCommitment.ToHexString();
                string associatedRegistrationKey = inherenceData.AssociatedRegistrationProof.AssetCommitments[0].ToHexString();
                _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, associated commitment is {commitmentToAssociated} and registration key is {associatedRegistrationKey} for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey} obtained");

                if (!biometricPersonData.Images.ContainsKey(commitmentToAssociated))
                {
                    _logger.Error($"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, no image found for the associated commitment {commitmentToAssociated}");
                    return(BadRequest($"No image found for the associated commitment {commitmentToAssociated}"));
                }

                Guid rootRegistrationGuid = await GetPersonRegistrationGuid(personGroupId, registrationKey).ConfigureAwait(false);

                if (Guid.Empty.Equals(rootRegistrationGuid))
                {
                    _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, No root registration found for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}");

                    if (!biometricPersonData.Images.ContainsKey(commitmentToRoot))
                    {
                        _logger.Error($"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, no image found for the root commitment {commitmentToRoot}");
                        return(BadRequest($"No image found for the root commitment {commitmentToRoot}"));
                    }

                    imageContent = biometricPersonData.Images[commitmentToRoot];
                    byte[] faceAssociated = biometricPersonData.Images[commitmentToAssociated];

                    bool matches = await _facesService.VerifyFaces(imageContent, faceAssociated).ConfigureAwait(false);

                    if (!matches)
                    {
                        _logger.Error($"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, faces do not match for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}");
                        return(BadRequest("Provided face images do not match one to another"));
                    }

                    PersonFaceData rootFaceData = new PersonFaceData
                    {
                        PersonGroupId = personGroupId,
                        Name          = registrationKey,
                        UserData      = registrationKey,
                        ImageContent  = imageContent
                    };

                    _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, adding root registration {registrationKey} for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}");
                    await AddPerson(rootFaceData).ConfigureAwait(false);

                    registrationKey = inherenceData.AssociatedRegistrationProof.AssetCommitments[0].ToHexString();
                    imageContent    = faceAssociated;

                    _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, proceeding with associated registration {registrationKey} for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}");
                }
                else
                {
                    _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, Root registration with key {registrationKey} found for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}");

                    registrationKey = inherenceData.AssociatedRegistrationProof.AssetCommitments[0].ToHexString();
                    imageContent    = biometricPersonData.Images.ContainsKey(commitmentToAssociated) ? biometricPersonData.Images[commitmentToAssociated] : null;
                    bool isIdentical = await VerifyPersonFace(personGroupId, rootRegistrationGuid, imageContent).ConfigureAwait(false);

                    if (!isIdentical)
                    {
                        _logger.Error($"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, face do not match to registered one for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}");
                        throw new InherenceCrossMatchingFailedException(inherenceData.RootRegistrationProof.AssetCommitments[0].ToHexString());
                    }

                    _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, proceeding with associated registration {registrationKey} for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}");
                }
            }
            else
            {
                _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, {nameof(InherenceData)} with {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey} does not contain {nameof(inherenceData.AssociatedRootCommitment)}");
                if (!biometricPersonData.Images.ContainsKey(commitmentToRoot))
                {
                    _logger.Error($"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, no image found for the root commitment {commitmentToRoot}");
                    return(BadRequest($"No image found for the root commitment {commitmentToRoot}"));
                }

                imageContent = biometricPersonData.Images[commitmentToRoot];
            }

            Guid guid = _dataAccessService.FindPersonGuid(registrationKey);

            PersonFaceData personFaceData = new PersonFaceData
            {
                PersonGroupId = personGroupId,
                Name          = registrationKey,
                UserData      = registrationKey,
                ImageContent  = imageContent
            };

            try
            {
                if (guid == Guid.Empty)
                {
                    _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, adding registration {registrationKey} for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}");
                    await AddPerson(personFaceData).ConfigureAwait(false);
                }
                else
                {
                    _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, replacing registration {registrationKey} for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}");
                    await ReplacePerson(personFaceData).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                if (ex is AggregateException aex)
                {
                    _logger.Error($"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)} failed with aggregated exception", aex.InnerException);
                }
                else
                {
                    _logger.Error($"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)} failed with exception", ex);
                }

                throw;
            }

            _logger.LogIfDebug(() => $"[{_inherenceService.AccountId}]: {nameof(RegisterPerson)}, completed successfully for {nameof(biometricPersonData.SessionKey)}={biometricPersonData.SessionKey}");

            return(Ok());
        }