Пример #1
0
        protected static void ReadSurjectionProof(ref Memory <byte> spanBody, ref int readBytes, out SurjectionProof surjectionProof)
        {
            ushort assetCommitmentsCount = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span);

            readBytes += sizeof(ushort);

            byte[][] assetCommitments = new byte[assetCommitmentsCount][];
            for (int i = 0; i < assetCommitmentsCount; i++)
            {
                assetCommitments[i] = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                readBytes          += Globals.NODE_PUBLIC_KEY_SIZE;
            }

            byte[] e = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
            readBytes += Globals.NODE_PUBLIC_KEY_SIZE;

            byte[][] s = new byte[assetCommitmentsCount][];
            for (int i = 0; i < assetCommitmentsCount; i++)
            {
                s[i]       = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                readBytes += Globals.NODE_PUBLIC_KEY_SIZE;
            }

            surjectionProof = new SurjectionProof
            {
                AssetCommitments = assetCommitments,
                Rs = new BorromeanRingSignature
                {
                    E = e,
                    S = s
                }
            };
        }
Пример #2
0
        private static SurjectionProof GetSurhectionProof(ref Memory <byte> spanBody, ref int readBytes)
        {
            SurjectionProof surjectionProof;
            ushort          assetCommitmentsCount = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span);

            readBytes += 2;

            byte[][] assetCommitments = new byte[assetCommitmentsCount][];
            for (int i = 0; i < assetCommitmentsCount; i++)
            {
                assetCommitments[i] = spanBody.Slice(readBytes, 32).ToArray();
                readBytes          += 32;
            }

            byte[] e = spanBody.Slice(readBytes, 32).ToArray();
            readBytes += 32;

            byte[][] s = new byte[assetCommitmentsCount][];
            for (int i = 0; i < assetCommitmentsCount; i++)
            {
                s[i]       = spanBody.Slice(readBytes, 32).ToArray();
                readBytes += 32;
            }

            surjectionProof = new SurjectionProof
            {
                AssetCommitments = assetCommitments,
                Rs = new BorromeanRingSignature
                {
                    E = e,
                    S = s
                }
            };
            return(surjectionProof);
        }
Пример #3
0
        private void WriteCommitmentAndProof(BinaryWriter bw, byte[] commitment, SurjectionProof surjectionProof)
        {
            if (commitment != null)
            {
                bw.Write(commitment);
            }

            WriteSurjectionProof(bw, surjectionProof);
        }
Пример #4
0
        private async Task ProcessUniversalTransport(UniversalTransport universalTransport)
        {
            _logger.LogIfDebug(() => $"[{AccountId}]: {nameof(ProcessUniversalTransport)} with {nameof(universalTransport.KeyImage)}={universalTransport.KeyImage}");

            TaskCompletionSource <UniversalProofs> universalProofsTask = _universalProofsPool.Extract(universalTransport.KeyImage);

            try
            {
                UniversalProofs universalProofs = await universalProofsTask.Task.ConfigureAwait(false);

                _logger.LogIfDebug(() => $"[{AccountId}]: {nameof(ProcessUniversalTransport)}, {nameof(UniversalProofs)} obtained with {nameof(universalProofs.KeyImage)}={universalProofs.KeyImage} and {nameof(universalProofs.SessionKey)}={universalProofs.SessionKey}");

                var             mainIssuer       = universalProofs.RootIssuers.Find(i => i.Issuer.Equals(universalProofs.MainIssuer));
                IKey            commitmentKey    = mainIssuer.IssuersAttributes.FirstOrDefault(a => a.Issuer.Equals(mainIssuer.Issuer))?.RootAttribute.Commitment;
                SurjectionProof eligibilityProof = mainIssuer.IssuersAttributes.FirstOrDefault(a => a.Issuer.Equals(mainIssuer.Issuer))?.RootAttribute.BindingProof;

                bool isEligibilityCorrect = await CheckEligibilityProofs(commitmentKey.Value, eligibilityProof, mainIssuer.Issuer.Value).ConfigureAwait(false);

                if (!isEligibilityCorrect && !string.IsNullOrEmpty(universalProofs.SessionKey))
                {
                    SetException(universalProofs.SessionKey, new ArgumentException("Eligibility proofs were wrong"));
                    return;
                }

                SurjectionProof registrationProof = mainIssuer.IssuersAttributes.FirstOrDefault(a => a.Issuer.Equals(mainIssuer.Issuer))?.RootAttribute.CommitmentProof.SurjectionProof;
                _spValidationsService.HandleAccount(AccountId, commitmentKey.Value, registrationProof);

                SetCompletion(
                    new InherenceData
                {
                    Issuer = mainIssuer.Issuer.ArraySegment.Array,
                    AssetRootCommitment         = commitmentKey.ArraySegment.Array,
                    RootRegistrationProof       = registrationProof,
                    AssociatedRootCommitment    = mainIssuer.IssuersAttributes?.FirstOrDefault(a => !a.Issuer.Equals(mainIssuer.Issuer))?.RootAttribute.Commitment.ArraySegment.Array,
                    AssociatedRegistrationProof = mainIssuer.IssuersAttributes?.FirstOrDefault(a => !a.Issuer.Equals(mainIssuer.Issuer))?.RootAttribute.CommitmentProof.SurjectionProof
                }, universalProofs.SessionKey);
            }
            catch (TimeoutException)
            {
                _logger.Error($"[{AccountId}]: Timeout during obtaining {nameof(UniversalProofs)} for key image {universalTransport.KeyImage}");
            }
            catch (Exception ex)
            {
                if (ex is AggregateException aex)
                {
                    _logger.Error($"[{AccountId}]: {nameof(ProcessUniversalTransport)}, unexpected aggregated exception", aex.InnerException);
                }
                else
                {
                    _logger.Error($"[{AccountId}]: {nameof(ProcessUniversalTransport)}, unexpected exception", ex);
                }

                throw;
            }
        }
Пример #5
0
        protected static void WriteSurjectionProof(BinaryWriter bw, SurjectionProof surjectionProof)
        {
            bw.Write((ushort)surjectionProof.AssetCommitments.Length);
            for (int j = 0; j < surjectionProof.AssetCommitments.Length; j++)
            {
                bw.Write(surjectionProof.AssetCommitments[j]);
            }

            bw.Write(surjectionProof.Rs.E);
            for (int j = 0; j < surjectionProof.Rs.S.Length; j++)
            {
                bw.Write(surjectionProof.Rs.S[j]);
            }
        }
Пример #6
0
        public async Task <IActionResult> SignPersonFaceVerification([FromBody] BiometricPersonDataForSignatureDto biometricPersonData)
        {
            byte[] imageSource = Convert.FromBase64String(biometricPersonData.ImageSource);
            byte[] imageTarget = Convert.FromBase64String(biometricPersonData.ImageTarget);

            byte[] assetId = await _assetsService.GenerateAssetId(AttributesSchemes.ATTR_SCHEME_NAME_PASSPORTPHOTO, biometricPersonData.ImageSource, null).ConfigureAwait(false);

            byte[] sourceImageCommitment = biometricPersonData.SourceImageCommitment.HexStringToByteArray();

            SurjectionProof surjectionProof = new SurjectionProof
            {
                AssetCommitments = new byte[][] { biometricPersonData.SourceImageProofCommitment.HexStringToByteArray() },
                Rs = new BorromeanRingSignature
                {
                    E = biometricPersonData.SourceImageProofSignatureE.HexStringToByteArray(),
                    S = new byte[][] { biometricPersonData.SourceImageProofSignatureS.HexStringToByteArray() }
                }
            };

            if (!ConfidentialAssetsHelper.VerifyIssuanceSurjectionProof(surjectionProof, sourceImageCommitment, new byte[][] { assetId }))
            {
                return(BadRequest("Surjection proofs validation failed"));
            }

            //byte[] auxBytes = null; // Convert.FromBase64String(biometricPersonData.AuxMessage);

            //byte[] msg = new byte[sourceImageCommitment.Length + auxBytes?.Length ?? 0];

            //Array.Copy(sourceImageCommitment, 0, msg, 0, sourceImageCommitment.Length);

            //if ((auxBytes?.Length ?? 0) > 0)
            //{
            //	Array.Copy(auxBytes, 0, msg, sourceImageCommitment.Length, auxBytes.Length);
            //}

            bool res = await _facesService.VerifyFaces(imageSource, imageTarget).ConfigureAwait(false);

            if (res)
            {
                Tuple <byte[], byte[]> signRes = _facesService.Sign(sourceImageCommitment);

                return(Ok(new BiometricSignedVerificationDto {
                    PublicKey = signRes.Item1.ToHexString(), Signature = signRes.Item2.ToHexString()
                }));
            }

            return(BadRequest());
        }
Пример #7
0
        public async Task CheckEligibilityProofs(Memory <byte> assetCommitment, SurjectionProof eligibilityProofs, Memory <byte> issuer)
        {
            Contract.Requires(eligibilityProofs != null);

            bool isCommitmentCorrect = ConfidentialAssetsHelper.VerifySurjectionProof(eligibilityProofs, assetCommitment.Span);

            if (!isCommitmentCorrect)
            {
                throw new CommitmentNotEligibleException();
            }

            bool res = await _gatewayService.AreRootAttributesValid(issuer, eligibilityProofs.AssetCommitments.Select(a => new Memory <byte>(a))).ConfigureAwait(false);

            if (!res)
            {
                throw new CommitmentNotEligibleException();
            }
        }
Пример #8
0
        private void WriteCommitmentAndProof(BinaryWriter bw, byte[] commitment, SurjectionProof surjectionProof)
        {
            if (commitment != null)
            {
                bw.Write(commitment);
            }

            bw.Write((ushort)surjectionProof.AssetCommitments.Length);
            for (int i = 0; i < surjectionProof.AssetCommitments.Length; i++)
            {
                bw.Write(surjectionProof.AssetCommitments[i]);
            }

            bw.Write(surjectionProof.Rs.E);

            for (int i = 0; i < surjectionProof.AssetCommitments.Length; i++)
            {
                bw.Write(surjectionProof.Rs.S[i]);
            }
        }
Пример #9
0
        private bool CheckEligibilityProofs(byte[] assetCommitment, SurjectionProof eligibilityProofs, byte[] issuer)
        {
            bool isCommitmentCorrect = ConfidentialAssetsHelper.VerifySurjectionProof(eligibilityProofs, assetCommitment);

            if (!isCommitmentCorrect)
            {
                return(false);
            }

            foreach (byte[] commitment in eligibilityProofs.AssetCommitments)
            {
                //TODO: make bulk check!
                if (!_gatewayService.IsRootAttributeValid(issuer, commitment))
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #10
0
        protected static SurjectionProof ReadSurjectionProof(Span <byte> span, out int readBytes)
        {
            ushort assetCommitmentsLength = BinaryPrimitives.ReadUInt16LittleEndian(span);

            readBytes = sizeof(ushort);

            byte[][] assetCommitments = new byte[assetCommitmentsLength][];

            for (int i = 0; i < assetCommitmentsLength; i++)
            {
                assetCommitments[i] = span.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                readBytes          += Globals.NODE_PUBLIC_KEY_SIZE;
            }

            byte[] e = span.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
            readBytes += Globals.NODE_PUBLIC_KEY_SIZE;

            byte[][] s = new byte[assetCommitmentsLength][];

            for (int i = 0; i < assetCommitmentsLength; i++)
            {
                s[i]       = span.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                readBytes += Globals.NODE_PUBLIC_KEY_SIZE;
            }

            BorromeanRingSignature rs = new BorromeanRingSignature
            {
                E = e,
                S = s
            };

            SurjectionProof surjectionProof = new SurjectionProof
            {
                AssetCommitments = assetCommitments,
                Rs = rs
            };

            return(surjectionProof);
        }
Пример #11
0
        protected override Memory <byte> ParseUtxoConfidential(ushort version, Memory <byte> spanBody, out UtxoConfidentialBase utxoConfidentialBase)
        {
            UtxoConfidentialBase block = null;

            if (version == 1)
            {
                int    readBytes       = 0;
                byte[] assetCommitment = spanBody.Slice(readBytes, 32).ToArray();
                readBytes += 32;

                ushort assetCommitmentsCount = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span);
                readBytes += 2;

                byte[][] assetCommitments = new byte[assetCommitmentsCount][];
                for (int i = 0; i < assetCommitmentsCount; i++)
                {
                    assetCommitments[i] = spanBody.Slice(readBytes, 32).ToArray();
                    readBytes          += 32;
                }

                byte[] e = spanBody.Slice(readBytes, 32).ToArray();
                readBytes += 32;

                byte[][] s = new byte[assetCommitmentsCount][];
                for (int i = 0; i < assetCommitmentsCount; i++)
                {
                    s[i]       = spanBody.Slice(readBytes, 32).ToArray();
                    readBytes += 32;
                }

                byte[] mask = spanBody.Slice(readBytes, 32).ToArray();
                readBytes += 32;

                byte[] assetId = spanBody.Slice(readBytes, 32).ToArray();
                readBytes += 32;

                SurjectionProof surjectionProof = new SurjectionProof
                {
                    AssetCommitments = assetCommitments,
                    Rs = new BorromeanRingSignature
                    {
                        E = e,
                        S = s
                    }
                };

                block = new AssetTransfer
                {
                    AssetCommitment = assetCommitment,
                    SurjectionProof = surjectionProof,
                    EcdhTuple       = new EcdhTupleCA
                    {
                        Mask    = mask,
                        AssetId = assetId
                    }
                };

                utxoConfidentialBase = block;

                return(spanBody.Slice(readBytes));
            }

            throw new BlockVersionNotSupportedException(version, BlockType);
        }
Пример #12
0
        private void ProcessDocumentSignRequest(DocumentSignRequest packet)
        {
            _clientCryptoService.DecodeEcdhTuple(packet.EcdhTuple, packet.TransactionPublicKey, out byte[] groupNameBlindingFactor, out byte[] documentHash, out byte[] issuer, out byte[] payload);
            string     sessionKey = payload.ToHexString();
            SpDocument spDocument = _dataAccessService.GetSpDocument(_accountId, documentHash.ToHexString());

            if (spDocument == null)
            {
                _idenitiesHubContext.Clients.Group(sessionKey).SendAsync("PushDocumentNotFound");
            }

            bool isEligibilityCorrect = CheckEligibilityProofs(packet.AssetCommitment, packet.EligibilityProof, issuer);

            if (!isEligibilityCorrect)
            {
                _idenitiesHubContext.Clients.Group(sessionKey).SendAsync("PushDocumentSignIncorrect", new { Code = 2, Message = "Eligibility proofs were wrong" }).Wait();
                return;
            }

            if (!ConfidentialAssetsHelper.VerifySurjectionProof(packet.SignerGroupRelationProof, packet.AssetCommitment, documentHash, BitConverter.GetBytes(spDocument.LastChangeRecordHeight)))
            {
                _idenitiesHubContext.Clients.Group(sessionKey).SendAsync("PushDocumentSignIncorrect", new { Code = 2, Message = "Signer group relation proofs were wrong" }).Wait();
                return;
            }

            SurjectionProof signatureGroupProof = null;
            string          groupIssuer         = null;

            foreach (var allowedSigner in spDocument.AllowedSigners)
            {
                byte[] groupAssetId            = _assetsService.GenerateAssetId(AttributeType.EmployeeGroup, allowedSigner.GroupIssuer + allowedSigner.GroupName);
                byte[] expectedGroupCommitment = ConfidentialAssetsHelper.GetAssetCommitment(groupAssetId, groupNameBlindingFactor);
                if (packet.AllowedGroupCommitment.Equals32(expectedGroupCommitment))
                {
                    byte[] groupCommitment = _gatewayService.GetEmployeeRecordGroup(allowedSigner.GroupIssuer.HexStringToByteArray(), packet.SignerGroupRelationProof.AssetCommitments[0]);
                    if (groupCommitment != null && ConfidentialAssetsHelper.VerifySurjectionProof(packet.AllowedGroupNameSurjectionProof, packet.AllowedGroupCommitment))
                    {
                        byte[]   diffBF                 = ConfidentialAssetsHelper.GetDifferentialBlindingFactor(groupNameBlindingFactor, allowedSigner.BlindingFactor.HexStringToByteArray());
                        byte[][] commitments            = spDocument.AllowedSigners.Select(s => s.GroupCommitment.HexStringToByteArray()).ToArray();
                        byte[]   allowedGroupCommitment = allowedSigner.GroupCommitment.HexStringToByteArray();
                        int      index = 0;

                        for (; index < commitments.Length; index++)
                        {
                            if (commitments[index].Equals32(allowedGroupCommitment))
                            {
                                break;
                            }
                        }

                        signatureGroupProof = ConfidentialAssetsHelper.CreateSurjectionProof(packet.AllowedGroupCommitment, commitments, index, diffBF);
                        groupIssuer         = allowedSigner.GroupIssuer;
                        break;
                    }
                }
            }

            if (signatureGroupProof == null)
            {
                _idenitiesHubContext.Clients.Group(sessionKey).SendAsync("PushDocumentSignIncorrect", new { Code = 2, Message = "Signer group relation proofs were wrong" }).Wait();
                return;
            }

            _transactionsService.IssueDocumentSignRecord(documentHash, spDocument.LastChangeRecordHeight, packet.AssetCommitment, packet.SignerGroupRelationProof, packet.AllowedGroupCommitment, groupIssuer.HexStringToByteArray(), packet.AllowedGroupNameSurjectionProof, signatureGroupProof, out ulong signatureRecordHeight);
            ulong signatureId = _dataAccessService.AddSpDocumentSignature(_accountId, spDocument.SpDocumentId, spDocument.LastChangeRecordHeight, signatureRecordHeight);

            _idenitiesHubContext.Clients.Group(_accountId.ToString(CultureInfo.InvariantCulture))
            .SendAsync("PushDocumentSignature",
                       new DocumentSignatureDto
            {
                DocumentId            = spDocument.SpDocumentId,
                DocumentHash          = spDocument.Hash,
                DocumentRecordHeight  = spDocument.LastChangeRecordHeight,
                SignatureRecordHeight = signatureRecordHeight
            });

            _idenitiesHubContext.Clients.Group(sessionKey)
            .SendAsync("PushDocumentSignature",
                       new DocumentSignatureDto
            {
                DocumentId            = spDocument.SpDocumentId,
                DocumentHash          = spDocument.Hash,
                DocumentRecordHeight  = spDocument.LastChangeRecordHeight,
                SignatureRecordHeight = signatureRecordHeight
            });
        }
Пример #13
0
        private async Task ProcessUniversalTransport(UniversalTransport universalTransport)
        {
            TaskCompletionSource <UniversalProofs> universalProofsTask = _universalProofsPool.Extract(universalTransport.KeyImage);

            try
            {
                UniversalProofs universalProofs = await universalProofsTask.Task.ConfigureAwait(false);

                IKey            commitmentKey        = universalProofs.IssuersAttributes.FirstOrDefault(a => a.Issuer.Equals(universalProofs.Issuer))?.RootAttribute.Commitment;
                SurjectionProof eligibilityProof     = universalProofs.IssuersAttributes.FirstOrDefault(a => a.Issuer.Equals(universalProofs.Issuer))?.RootAttribute.BindingProof;
                bool            isEligibilityCorrect = await CheckEligibilityProofs(commitmentKey.Value, eligibilityProof, universalProofs.Issuer.Value).ConfigureAwait(false);

                if (!isEligibilityCorrect && !string.IsNullOrEmpty(universalProofs.SessionKey))
                {
                    await _idenitiesHubContext.Clients.Group(universalProofs.SessionKey).SendAsync("EligibilityCheckFailed").ConfigureAwait(false);

                    return;
                }

                try
                {
                    await VerifyProofToAssociatedAttributeKnowledge(universalProofs, AttributesSchemes.ATTR_SCHEME_NAME_PASSWORD).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    string msg = ex.Message;

                    if (ex is AggregateException aex)
                    {
                        if (aex.InnerException is FlurlHttpException fex)
                        {
                            _logger.Error($"[{_accountId}]: Failed request '{fex.Call.Request.RequestUri}' with body '{fex.Call.RequestBody}'");
                        }
                        msg = aex.InnerException.Message;

                        _logger.Error($"[{_accountId}]: Failure at {nameof(ProcessUniversalTransport)}", aex.InnerException);
                    }
                    else
                    {
                        _logger.Error($"[{_accountId}]: Failure at {nameof(ProcessUniversalTransport)}", ex);
                    }

                    await _idenitiesHubContext.Clients.Group(universalProofs.SessionKey).SendAsync("ProtectionCheckFailed", msg).ConfigureAwait(false);

                    return;
                }

                switch (universalProofs.Mission)
                {
                case UniversalProofsMission.Authentication:
                    await ProcessUniversalProofsAuthentication(universalProofs).ConfigureAwait(false);

                    break;

                default:
                    break;
                }
            }
            catch (TimeoutException)
            {
                _logger.Error($"[{_accountId}]: Timeout during obtaining {nameof(UniversalProofs)} for key image {universalTransport.KeyImage}");
            }
        }
Пример #14
0
        private static void ReadCommitmentAndProof(ref Memory <byte> spanBody, ref int readBytes, out byte[] assetCommitment, out SurjectionProof surjectionProof)
        {
            assetCommitment = spanBody.Slice(readBytes, 32).ToArray();
            readBytes      += 32;

            surjectionProof = GetSurhectionProof(ref spanBody, ref readBytes);
        }
Пример #15
0
        private async Task <bool> CheckEligibilityProofs(Memory <byte> assetCommitment, SurjectionProof eligibilityProofs, Memory <byte> issuer)
        {
            _logger.LogIfDebug(() => $"[{AccountId}]: {nameof(CheckEligibilityProofs)} with assetCommitment={assetCommitment.ToHexString()}, issuer={issuer.ToHexString()}, eligibilityProofs={JsonConvert.SerializeObject(eligibilityProofs, new ByteArrayJsonConverter())}");

            try
            {
                await _spValidationsService.CheckEligibilityProofs(assetCommitment, eligibilityProofs, issuer).ConfigureAwait(false);
            }
            catch (CommitmentNotEligibleException)
            {
                _logger.Error($"[{AccountId}]: {nameof(CheckEligibilityProofs)} found commitment not eligible");
                return(false);
            }

            _logger.Debug($"[{AccountId}]: {nameof(CheckEligibilityProofs)} correct");
            return(true);
        }
Пример #16
0
        public (long registrationId, bool isNew) HandleAccount(long accountId, Memory <byte> assetCommitment, SurjectionProof authenticationProof)
        {
            if (_dataAccessService.GetServiceProviderRegistrationId(accountId, authenticationProof.AssetCommitments[0], out long registrationId))
            {
                bool isAuthenticationProofValid = ConfidentialAssetsHelper.VerifySurjectionProof(authenticationProof, assetCommitment.Span);

                if (!isAuthenticationProofValid)
                {
                    throw new SpAuthenticationProofsFailedException();
                }

                return(registrationId, false);
            }
            else
            {
                long id = _dataAccessService.AddServiceProviderRegistration(accountId, authenticationProof.AssetCommitments[0]);
                return(id, true);
            }
        }
Пример #17
0
        private static void ReadCommitmentAndProof(ref Memory <byte> spanBody, ref int readBytes, out byte[] assetCommitment, out SurjectionProof surjectionProof)
        {
            assetCommitment = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
            readBytes      += Globals.NODE_PUBLIC_KEY_SIZE;

            ReadSurjectionProof(ref spanBody, ref readBytes, out surjectionProof);
        }
Пример #18
0
        protected override Memory <byte> ParseTransactional(ushort version, Memory <byte> spanBody, uint assetsCount, out TransactionalBlockBase transactionalBlockBase)
        {
            TransactionalBlockBase block = null;

            if (version == 1)
            {
                int readBytes = 0;

                byte[] destinationKey = spanBody.Slice(readBytes, 32).ToArray();
                readBytes += 32;

                byte[] transactionPublicKey = spanBody.Slice(readBytes, 32).ToArray();
                readBytes += 32;

                byte[] assetId = spanBody.Slice(readBytes, 32).ToArray();
                readBytes += 32;

                byte[] assetCommitment = spanBody.Slice(readBytes, 32).ToArray();
                readBytes += 32;

                byte[][] assetCommitments = new byte[assetsCount][];
                for (int i = 0; i < assetsCount; i++)
                {
                    assetCommitments[i] = spanBody.Slice(readBytes, 32).ToArray();
                    readBytes          += 32;
                }

                byte[] e = spanBody.Slice(readBytes, 32).ToArray();
                readBytes += 32;

                byte[][] s = new byte[assetsCount][];
                for (int i = 0; i < assetsCount; i++)
                {
                    s[i]       = spanBody.Slice(readBytes, 32).ToArray();
                    readBytes += 32;
                }

                byte[] mask = spanBody.Slice(readBytes, 32).ToArray();
                readBytes += 32;
                byte[] asset = spanBody.Slice(readBytes, 32).ToArray();
                readBytes += 32;

                SurjectionProof surjectionProof = new SurjectionProof
                {
                    AssetCommitments = assetCommitments,
                    Rs = new BorromeanRingSignature
                    {
                        E = e,
                        S = s
                    }
                };

                block = new TransferAssetToUtxoBlock
                {
                    TransactionPublicKey = transactionPublicKey,
                    DestinationKey       = destinationKey,
                    AssetId         = assetId,
                    AssetCommitment = assetCommitment,
                    SurjectionProof = surjectionProof,
                    EcdhTuple       = new EcdhTupleCA
                    {
                        Mask    = mask,
                        AssetId = asset
                    }
                };

                transactionalBlockBase = block;
                return(spanBody.Slice(readBytes));
            }

            throw new BlockVersionNotSupportedException(version, BlockType);
        }
Пример #19
0
        private BlockBase CreateNonQuantitativeTransitionAssetTransferBlock(Account receiver, byte[] assetId, byte[] prevTransactionKey, byte[] prevCommitment, byte[] prevDestinationKey, int ringSize, ulong tagId, out byte[] otsk, out int pos)
        {
            if (!_clientState.IsConfidential())
            {
                otsk = null;
                pos  = -1;
                return(null);
            }

            byte[] otskAsset = ConfidentialAssetsHelper.GetOTSK(prevTransactionKey, _clientState.GetSecretViewKey(), _clientState.GetSecretSpendKey());
            otsk = otskAsset;
            byte[] keyImage        = ConfidentialAssetsHelper.GenerateKeyImage(otskAsset);
            byte[] secretKey       = ConfidentialAssetsHelper.GetRandomSeed();
            byte[] transactionKey  = ConfidentialAssetsHelper.GetTrancationKey(secretKey);
            byte[] destinationKey  = _hashCalculation.CalculateHash(receiver.PublicKey);
            byte[] blindingFactor  = ConfidentialAssetsHelper.GetRandomSeed();
            byte[] assetCommitment = ConfidentialAssetsHelper.GetAssetCommitment(assetId, blindingFactor);

            byte[] msg = ConfidentialAssetsHelper.FastHash256(BitConverter.GetBytes(tagId), keyImage, destinationKey, transactionKey, assetCommitment);

            Random random = new Random(BitConverter.ToInt32(secretKey, 0));

            GetCommitmentAndProofs(prevCommitment, prevDestinationKey, ringSize, tagId, random, out int actualAssetPos, out byte[][] assetCommitments, out byte[][] assetPubs);
            pos = actualAssetPos;

            UtxoUnspentBlock idCardBlock = _dataAccessService.GetUtxoUnspentBlocksByTagId(_idCardTagId).First();

            byte[] otskAffiliation            = ConfidentialAssetsHelper.GetOTSK(idCardBlock.TransactionKey, _clientState.GetSecretViewKey(), _clientState.GetSecretSpendKey());
            byte[] affiliationBlindingFactor  = ConfidentialAssetsHelper.GetRandomSeed();
            byte[] affiliationAssetCommitment = ConfidentialAssetsHelper.GetAssetCommitment(idCardBlock.AssetId, affiliationBlindingFactor);
            GetCommitmentAndProofs(idCardBlock.Output.Commitment, idCardBlock.Output.DestinationKey, ringSize, _idCardTagId, random, out int actualAffiliationPos, out byte[][] affiliationCommitments, out byte[][] affiliationPubs);

            BorromeanRingSignature borromeanRingSignature = ConfidentialAssetsHelper.GenerateBorromeanRingSignature(msg, affiliationPubs, actualAffiliationPos, otskAffiliation);

            SurjectionProof assetSurjectionProof       = ConfidentialAssetsHelper.CreateAssetRangeProof(assetCommitment, assetCommitments, actualAssetPos, blindingFactor);
            SurjectionProof affilaitionSurjectionProof = ConfidentialAssetsHelper.CreateAssetRangeProof(affiliationAssetCommitment, affiliationCommitments, actualAffiliationPos, affiliationBlindingFactor);

            List <TransactionalIncomingBlock> incomingBlocks    = _dataAccessService.GetIncomingBlocksByBlockType(BlockTypes.Transaction_IssueAssets);
            List <IssueAssetsBlock>           issueAssetsBlocks = incomingBlocks.Where(b => b.TagId == _idCardTagId).ToList().Select(b =>
            {
                return((IssueAssetsBlock)_blockParsersRepositoriesRepository.GetBlockParsersRepository(PacketType.Transactional).GetInstance(b.BlockType).Parse(b.Content));
            }).ToList();

            List <byte[]> rawIdCardAssetIds = issueAssetsBlocks.SelectMany(b => b.IssuedAssetIds).ToList();

            SurjectionProof affiliationEvidenceSurjectionProof = ConfidentialAssetsHelper.CreateNewIssuanceSurjectionProof(affiliationAssetCommitment, rawIdCardAssetIds.ToArray(), rawIdCardAssetIds.FindIndex(b => b.Equals32(idCardBlock.AssetId)), affiliationBlindingFactor);

            NonQuantitativeTransitionAssetTransferBlock block = new NonQuantitativeTransitionAssetTransferBlock
            {
                TagId                              = tagId,
                KeyImage                           = _identityKeyProvider.GetKey(keyImage),
                DestinationKey                     = destinationKey,
                TransactionPublicKey               = transactionKey,
                AssetCommitment                    = assetCommitment,
                SurjectionProof                    = assetSurjectionProof,
                AffiliationCommitment              = affiliationAssetCommitment,
                AffiliationPseudoKeys              = affiliationPubs,
                AffiliationSurjectionProof         = affilaitionSurjectionProof,
                AffiliationBorromeanSignature      = borromeanRingSignature,
                AffiliationEvidenceSurjectionProof = affiliationEvidenceSurjectionProof,
                EcdhTuple                          = ConfidentialAssetsHelper.CreateEcdhTupleCA(blindingFactor, assetId, secretKey, receiver.PublicKey),
                PublicKeys                         = assetPubs.Select(p => _identityKeyProvider.GetKey(p)).ToArray(),
                Signatures                         = ConfidentialAssetsHelper.GenerateRingSignature(msg, keyImage, assetPubs, otskAsset, actualAssetPos)
            };

            FillSyncData(block);
            FillRawData(block);

            return(block);
        }
Пример #20
0
        protected override Memory <byte> ParseUtxoConfidential(ushort version, Memory <byte> spanBody, out UtxoConfidentialBase utxoConfidentialBase)
        {
            UtxoConfidentialBase block = null;

            if (version == 1)
            {
                int readBytes = 0;

                ReadCommitmentAndProof(ref spanBody, ref readBytes, out byte[] assetCommitment, out SurjectionProof surjectionProof);
                ReadCommitmentAndProof(ref spanBody, ref readBytes, out byte[] affiliationAssetCommitment, out SurjectionProof affiliationSurjectionProof);

                ushort affiliationPseudoKeysCount = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Span.Slice(readBytes));
                readBytes += 2;

                byte[][] affiliationPseudoKeys = new byte[affiliationPseudoKeysCount][];
                for (int i = 0; i < affiliationPseudoKeysCount; i++)
                {
                    affiliationPseudoKeys[i] = spanBody.Slice(readBytes, 32).ToArray();
                    readBytes += 32;
                }

                byte[] e = spanBody.Slice(readBytes, 32).ToArray();
                readBytes += 32;

                ushort sCount = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Span.Slice(readBytes));
                readBytes += 2;

                byte[][] s = new byte[sCount][];
                for (int i = 0; i < sCount; i++)
                {
                    s[i]       = spanBody.Slice(readBytes, 32).ToArray();
                    readBytes += 32;
                }

                BorromeanRingSignature borromeanRingSignature = new BorromeanRingSignature {
                    E = e, S = s
                };

                SurjectionProof surjectionEvidenceProof = GetSurhectionProof(ref spanBody, ref readBytes);

                ReadEcdhTupleCA(ref spanBody, ref readBytes, out byte[] mask, out byte[] assetId);

                block = new NonQuantitativeTransitionAssetTransferBlock
                {
                    AssetCommitment                    = assetCommitment,
                    SurjectionProof                    = surjectionProof,
                    AffiliationCommitment              = affiliationAssetCommitment,
                    AffiliationSurjectionProof         = affiliationSurjectionProof,
                    AffiliationPseudoKeys              = affiliationPseudoKeys,
                    AffiliationBorromeanSignature      = borromeanRingSignature,
                    AffiliationEvidenceSurjectionProof = surjectionEvidenceProof,
                    EcdhTuple = new EcdhTupleCA
                    {
                        Mask    = mask,
                        AssetId = assetId
                    }
                };

                utxoConfidentialBase = block;

                return(spanBody.Slice(readBytes));
            }

            throw new BlockVersionNotSupportedException(version, BlockType);
        }
Пример #21
0
        protected override Memory <byte> ParseTransactional(ushort version, Memory <byte> spanBody, out TransactionalPacketBase transactionalBlockBase)
        {
            IssueGroupedAssets block = null;

            if (version == 1)
            {
                int readBytes = 0;

                ushort assetsIssuanceGroupsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span);
                readBytes += sizeof(ushort);

                ushort blindedAssetsIssuanceGroupsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span);
                readBytes += sizeof(ushort);

                AssetsIssuanceGroup[]        assetsIssuanceGroups        = new AssetsIssuanceGroup[assetsIssuanceGroupsLength];
                BlindedAssetsIssuanceGroup[] blindedAssetsIssuanceGroups = new BlindedAssetsIssuanceGroup[blindedAssetsIssuanceGroupsLength];

                for (int i = 0; i < assetsIssuanceGroupsLength; i++)
                {
                    uint groupId = BinaryPrimitives.ReadUInt32LittleEndian(spanBody.Slice(readBytes).Span);
                    readBytes += sizeof(uint);

                    ushort assetIdsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span);
                    readBytes += sizeof(ushort);

                    AssetIssuance[] assetIssuances = new AssetIssuance[assetIdsLength];

                    for (int j = 0; j < assetIdsLength; j++)
                    {
                        byte[] assetId = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                        readBytes += Globals.NODE_PUBLIC_KEY_SIZE;

                        byte strLen = spanBody.Slice(readBytes, 1).ToArray()[0];
                        readBytes++;

                        string issuedAssetInfo = Encoding.ASCII.GetString(spanBody.Slice(readBytes, strLen).ToArray());
                        readBytes += strLen;

                        assetIssuances[j] = new AssetIssuance
                        {
                            AssetId         = assetId,
                            IssuedAssetInfo = issuedAssetInfo
                        };
                    }

                    assetsIssuanceGroups[i] = new AssetsIssuanceGroup
                    {
                        GroupId        = groupId,
                        AssetIssuances = assetIssuances
                    };
                }

                for (int i = 0; i < blindedAssetsIssuanceGroupsLength; i++)
                {
                    uint groupId = BinaryPrimitives.ReadUInt32LittleEndian(spanBody.Slice(readBytes).Span);
                    readBytes += sizeof(uint);

                    ushort assetCommitmentsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span);
                    readBytes += sizeof(ushort);

                    byte[][] assetCommitments = new byte[assetCommitmentsLength][];

                    for (int j = 0; j < assetCommitmentsLength; j++)
                    {
                        assetCommitments[j] = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                        readBytes          += Globals.NODE_PUBLIC_KEY_SIZE;
                    }

                    AssetIssuance[] blindedAssetIssuances = new AssetIssuance[assetCommitmentsLength];
                    for (int j = 0; j < assetCommitmentsLength; j++)
                    {
                        byte[] assetId = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                        readBytes += Globals.NODE_PUBLIC_KEY_SIZE;

                        byte strLen = spanBody.Slice(readBytes, 1).ToArray()[0];
                        readBytes++;

                        string issuedAssetInfo = Encoding.ASCII.GetString(spanBody.Slice(readBytes, strLen).ToArray());
                        readBytes += strLen;

                        blindedAssetIssuances[i] = new AssetIssuance
                        {
                            AssetId         = assetId,
                            IssuedAssetInfo = issuedAssetInfo
                        };
                    }

                    IssuanceProof[] issuanceProofs = new IssuanceProof[assetCommitmentsLength];
                    for (int j = 0; j < assetCommitmentsLength; j++)
                    {
                        SurjectionProof surjectionProof = ReadSurjectionProof(spanBody.Slice(readBytes).Span, out int count);
                        readBytes += count;

                        byte[] mask = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                        readBytes += Globals.NODE_PUBLIC_KEY_SIZE;

                        issuanceProofs[j] = new IssuanceProof
                        {
                            SurjectionProof = surjectionProof,
                            Mask            = mask,
                        };
                    }

                    blindedAssetsIssuanceGroups[i] = new BlindedAssetsIssuanceGroup
                    {
                        GroupId          = groupId,
                        AssetCommitments = assetCommitments,
                        AssetIssuances   = blindedAssetIssuances,
                        IssuanceProofs   = issuanceProofs
                    };
                }

                byte strLen2 = spanBody.Slice(readBytes, 1).ToArray()[0];
                readBytes++;

                string issuanceInfo = Encoding.ASCII.GetString(spanBody.Slice(readBytes, strLen2).ToArray());
                readBytes += strLen2;

                ushort assetsGroupsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span);
                readBytes += sizeof(ushort);

                ushort blindedAssetGroupsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span);
                readBytes += sizeof(ushort);

                AssetsGroup[]        assetsGroups        = new AssetsGroup[assetsGroupsLength];
                BlindedAssetsGroup[] blindedAssetsGroups = new BlindedAssetsGroup[blindedAssetGroupsLength];

                for (int i = 0; i < assetsGroupsLength; i++)
                {
                    uint groupId = BinaryPrimitives.ReadUInt32LittleEndian(spanBody.Slice(readBytes).Span);
                    readBytes += sizeof(uint);

                    ushort assetIdsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span);
                    readBytes += sizeof(ushort);

                    byte[][] assetIds = new byte[assetIdsLength][];
                    ulong[]  amounts  = new ulong[assetIdsLength];

                    for (int j = 0; j < assetIdsLength; j++)
                    {
                        assetIds[j] = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                        readBytes  += Globals.NODE_PUBLIC_KEY_SIZE;

                        amounts[j] = BinaryPrimitives.ReadUInt64LittleEndian(spanBody.Slice(readBytes).Span);
                        readBytes += sizeof(ulong);
                    }

                    assetsGroups[i] = new AssetsGroup
                    {
                        GroupId      = groupId,
                        AssetIds     = assetIds,
                        AssetAmounts = amounts
                    };
                }

                for (int i = 0; i < blindedAssetGroupsLength; i++)
                {
                    uint groupId = BinaryPrimitives.ReadUInt32LittleEndian(spanBody.Slice(readBytes).Span);
                    readBytes += sizeof(uint);

                    ushort assetCommitmentsLength = BinaryPrimitives.ReadUInt16LittleEndian(spanBody.Slice(readBytes).Span);
                    readBytes += sizeof(ushort);

                    byte[][] assetCommitments = new byte[assetCommitmentsLength][];

                    for (int j = 0; j < assetCommitmentsLength; j++)
                    {
                        assetCommitments[j] = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray();
                        readBytes          += Globals.NODE_PUBLIC_KEY_SIZE;
                    }

                    blindedAssetsGroups[i] = new BlindedAssetsGroup
                    {
                        GroupId          = groupId,
                        AssetCommitments = assetCommitments
                    };
                }

                block = new IssueGroupedAssets
                {
                    AssetsIssuanceGroups        = assetsIssuanceGroups,
                    BlindedAssetsIssuanceGroups = blindedAssetsIssuanceGroups,
                    IssuanceInfo        = issuanceInfo,
                    AssetsGroups        = assetsGroups,
                    BlindedAssetsGroups = blindedAssetsGroups
                };

                transactionalBlockBase = block;
                return(spanBody.Slice(readBytes));
            }

            throw new BlockVersionNotSupportedException(version, BlockType);
        }