/// <param name="waitNhaFromNeighborNullable">is used to verify NPACK.NeighborHMAC</param> internal async Task <NeighborPeerAckPacket> OptionallySendUdpRequestAsync_Retransmit_WaitForNeighborPeerAck(string completionActionVisibleId, byte[] requestPacketDataNullable, IPEndPoint responderEndpoint, RequestP2pSequenceNumber16 reqP2pSeq16, ConnectionToNeighbor waitNhaFromNeighborNullable = null, Action <BinaryWriter> npaRequestFieldsForNeighborHmacNullable = null) { var npaScanner = NeighborPeerAckPacket.GetScanner(reqP2pSeq16, waitNhaFromNeighborNullable, npaRequestFieldsForNeighborHmacNullable); if (WriteToLog_udp_deepDetail_enabled) { WriteToLog_udp_deepDetail($"waiting for NPACK, scanner: {MiscProcedures.ByteArrayToString(npaScanner.ResponseFirstBytes)} npaSeq={reqP2pSeq16}"); } var nextHopResponsePacketData = await SendUdpRequestAsync_Retransmit( new PendingLowLevelUdpRequest(completionActionVisibleId, responderEndpoint, npaScanner, DateTimeNowUtc, Configuration.UdpLowLevelRequests_ExpirationTimeoutS, requestPacketDataNullable, Configuration.UdpLowLevelRequests_InitialRetransmissionTimeoutS, Configuration.UdpLowLevelRequests_RetransmissionTimeoutIncrement )); if (nextHopResponsePacketData == null) { string desc = "no NPACK response to DRP request '"; if (requestPacketDataNullable != null) { desc += (PacketTypes)requestPacketDataNullable[0]; } desc += $"' - timeout expired ({Configuration.UdpLowLevelRequests_ExpirationTimeoutS}s) completionAction={completionActionVisibleId}"; if (waitNhaFromNeighborNullable != null) { desc += $", neighbor={waitNhaFromNeighborNullable}"; } throw new DrpTimeoutException(desc); } var nextHopResponsePacket = new NeighborPeerAckPacket(nextHopResponsePacketData); if (nextHopResponsePacket.ResponseCode != ResponseOrFailureCode.accepted) { if (WriteToLog_udp_deepDetail_enabled) { WriteToLog_udp_deepDetail($"got NPACK with {nextHopResponsePacket.ResponseCode} throwing exception"); } throw new RequestRejectedException(nextHopResponsePacket.ResponseCode); } return(nextHopResponsePacket); }
/// <summary> /// is executed by engine thread /// </summary> /// <returns> /// true if the response is linked to request, and the packet is processed /// </returns> bool PendingUdpRequests_ProcessPacket(IPEndPoint responderEndpoint, byte[] udpData, DateTime receivedAtUtc) { using var tracker = CreateTracker("PendingUdpRequests_ProcessPacket"); tracker.Details = $"count={_pendingLowLevelUdpRequests.Count}"; // todo optimize this by storing pending requests indexed for (var item = _pendingLowLevelUdpRequests.First; item != null; item = item.Next) { var request = item.Value; if (WriteToLog_udp_deepDetail_enabled) { WriteToLog_udp_deepDetail($"matching to pending request... responderEndpoint={responderEndpoint}, " + $"udpData={MiscProcedures.ByteArrayToString(udpData)} ({(PacketTypes)udpData[0]}) " + $"hash={MiscProcedures.GetArrayHashCodeString(udpData)}, " + $"request={request}" // + $" ResponseScanner.ResponseFirstBytes={MiscProcedures.ByteArrayToString(request.ResponseScanner.ResponseFirstBytes)}" ); } try { if (request.ResponderEndpoint.Equals(responderEndpoint) && request.ResponseScanner.Scan(this, udpData)) { tracker.Details += $"; completed {request.CompletionActionVisibleId}"; _pendingLowLevelUdpRequests.Remove(item); request.ResponseReceivedAtUtc = receivedAtUtc; tracker.Dispose(); using (var tr2 = CreateTracker(request.CompletionActionVisibleId)) request.TaskCompletionSource.SetResult(udpData); return(true); } } catch (Exception exc) { HandleExceptionInEngineThread(exc); } } // WriteToLog_udp_detail($"match to pending request was not found for packet from {responderEndpoint}, udpData={MiscProcedures.ByteArrayToString(udpData)}"); return(false); }
public override string ToString() => MiscProcedures.ByteArrayToString(Ed25519publicKey);
public override string ToString() => MiscProcedures.ByteArrayToString(hmacSha256);
void IDrpRegisteredPeerApp.OnReceivedInvite(RegistrationId remoteRegistrationId, byte[] contactInvitationToken, out UserId remoteUserIdNullable, out UserCertificate localUserCertificateWithPrivateKey, out bool autoReply) { remoteUserIdNullable = null; var contact = GetUnconfirmedContactByToken(contactInvitationToken); if (contact == null) { _userAppEngine.WriteToLog_needsAtttention($"unconfirmed contact was not found by contactInvitationToken={MiscProcedures.ByteArrayToString(contactInvitationToken)}"); autoReply = false; localUserCertificateWithPrivateKey = null; } else { _userAppEngine.WriteToLog_higherLevelDetail($"unconfirmed contact '{contact.UserAliasID}' was found by contactInvitationToken={MiscProcedures.ByteArrayToString(contactInvitationToken)}"); autoReply = true; localUserCertificateWithPrivateKey = User.LocalUserCertificate; localUserCertificateWithPrivateKey.AssertHasPrivateKey(); localUserCertificateWithPrivateKey.AssertIsValidNow(_userAppEngine.Engine.CryptoLibrary, User.UserID, _userAppEngine.Engine.DateTimeNowUtc); } }
const ushort Magic16_ipv4_requesterToResponder = 0xBFA4; // is used to validate decrypted data // IAuthenticatedEncryptor Encryptor; // IAuthenticatedDecryptor Decryptor; /// <summary> /// initializes SharedAuthKeyForHMAC /// </summary> public void InitializeP2pStream(RegisterRequestPacket req, RegisterAck1Packet ack1, RegisterAck2Packet ack2) { if (_disposed) { throw new ObjectDisposedException(ToString()); } _req = req; _ack1 = ack1; _ack2 = ack2; var ms = new MemoryStream(); using (var writer = new BinaryWriter(ms)) { req.GetSharedSignedFields(writer, true); ack1.GetSharedSignedFields(writer, true, true); ack2.GetSharedSignedFields(writer, false, true); // var iv = cryptoLibrary.GetHashSHA256(ms.ToArray()); // todo use for p2p encryption ms.Write(SharedDhSecret, 0, SharedDhSecret.Length); SharedAuthKeyForNeighborHMAC = _engine.CryptoLibrary.GetHashSHA256(ms.ToArray()); // here SHA256 is used as KDF, together with common fields from packets, including both ECDH public keys and timestamp if (_engine.WriteToLog_p2p_detail_enabled) { _engine.WriteToLog_p2p_detail2(this, $"initialized P2P stream: SharedAuthKeyForHMAC={MiscProcedures.ByteArrayToString(SharedAuthKeyForNeighborHMAC)}", req); } //Encryptor = cryptoLibrary.CreateAesEncyptor(iv, aesKey); //Decryptor = cryptoLibrary.CreateAesDecyptor(iv, aesKey); } }
public override string ToString() => $"{RequesterEndpoint}-{MiscProcedures.ByteArrayToString(RequestData)}";
public override string ToString() => $"key={RequestKey}: {MiscProcedures.ByteArrayToString(ResponseUdpPayloadData)}";
public Func <byte[], bool> OptionalFilter; // verifies NPACK.NeighborHMAC, ignores invalid HMACs // returns false to ignore the processed response packet public bool Scan(DrpPeerEngine engine, byte[] udpData) // may throw parser exception { if (!MiscProcedures.EqualByteArrayHeader(ResponseFirstBytes, udpData, IgnoredByteAtOffset1)) { if (engine.WriteToLog_udp_deepDetail_enabled) { engine.WriteToLog_udp_deepDetail($"packet does not match to ResponseFirstBytes={MiscProcedures.ByteArrayToString(ResponseFirstBytes)} ({(PacketTypes)ResponseFirstBytes[0]}) udpData={MiscProcedures.ByteArrayToString(udpData)} ({(PacketTypes)udpData[0]})" ); } return(false); } if (OptionalFilter != null) { if (!OptionalFilter(udpData)) { //if (engine.WriteToLog_udp_deepDetail_enabled) engine.WriteToLog_udp_lightPain($"packet did not pass OptionalFilter"); return(false); } } return(true); }