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 } }; }
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); }
private void WriteCommitmentAndProof(BinaryWriter bw, byte[] commitment, SurjectionProof surjectionProof) { if (commitment != null) { bw.Write(commitment); } WriteSurjectionProof(bw, surjectionProof); }
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; } }
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]); } }
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()); }
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(); } }
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]); } }
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); }
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); }
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); }
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 }); }
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}"); } }
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); }
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); }
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); } }
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); }
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); }
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); }
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); }
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); }