Ejemplo n.º 1
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());
        }
Ejemplo n.º 2
0
        private async Task CheckAssociatedProof(Memory <byte> rootCommitment, IEnumerable <AttributesByIssuer> associatedAttributes, string schemeName)
        {
            AttributesByIssuer associatedAttributesForCheck = associatedAttributes.FirstOrDefault(c => c.RootAttribute.SchemeName == schemeName || c.Attributes.Any(a => a.SchemeName == schemeName));

            if (associatedAttributesForCheck == null)
            {
                throw new ValidationProofsWereNotCompleteException(schemeName);
            }

            //_logger.LogIfDebug(() => $"{nameof(CheckAssociatedProof)}: \r\n{nameof(rootCommitment)}={rootCommitment.ToHexString()}, \r\n{nameof(associatedRootAttribute)}={{0}}");
            bool proofToRoot = ConfidentialAssetsHelper.VerifySurjectionProof(associatedAttributesForCheck.RootAttribute.BindingProof, rootCommitment.Span);

            if (!proofToRoot)
            {
                _logger.Error("Proof of binding to Root failed");
                throw new ValidationProofFailedException(schemeName);
            }

            AttributeProofs attributeForCheck;

            if (schemeName == associatedAttributesForCheck.RootAttribute.SchemeName)
            {
                attributeForCheck = associatedAttributesForCheck.RootAttribute;

                if (attributeForCheck == null)
                {
                    throw new ValidationProofsWereNotCompleteException(schemeName);
                }
            }
            else
            {
                attributeForCheck = associatedAttributesForCheck.Attributes.FirstOrDefault(a => a.SchemeName == schemeName);

                if (attributeForCheck == null)
                {
                    throw new ValidationProofsWereNotCompleteException(schemeName);
                }

                // Check binding to the Root Attribute
                bool proofToAssociatedRoot = ConfidentialAssetsHelper.VerifySurjectionProof(attributeForCheck.BindingProof, associatedAttributesForCheck.RootAttribute.Commitment.Value.Span);
                if (!proofToAssociatedRoot)
                {
                    _logger.Error("Proof of binding to Associated Root failed");
                    throw new ValidationProofFailedException(schemeName);
                }
            }

            if (attributeForCheck.CommitmentProof.Values?.Any() ?? false)
            {
                long schemeId = await _assetsService.GetSchemeId(schemeName, associatedAttributesForCheck.Issuer.ToString()).ConfigureAwait(false);

                byte[][] assetIds = attributeForCheck.CommitmentProof.Values.Select(v => _assetsService.GenerateAssetId(schemeId, v)).ToArray();

                bool proofOfValue = ConfidentialAssetsHelper.VerifyIssuanceSurjectionProof(attributeForCheck.CommitmentProof.SurjectionProof, attributeForCheck.Commitment.Value.Span, assetIds);
                if (!proofOfValue)
                {
                    _logger.Error("Proof of value failed");
                    throw new ValidationProofFailedException(schemeName);
                }
            }
            else
            {
                bool proofOfValueKnowledge = ConfidentialAssetsHelper.VerifySurjectionProof(attributeForCheck.CommitmentProof.SurjectionProof, attributeForCheck.Commitment.Value.Span);
                if (!proofOfValueKnowledge)
                {
                    _logger.Error("Proof of value knowledge failed");
                    throw new ValidationProofFailedException(schemeName);
                }
            }
        }