/// <param name="reqReceivedFromInP2pMode">is not null for packets between registered peers</param> public byte[] Encode_OpionallySignNeighborHMAC(ConnectionToNeighbor reqReceivedFromInP2pMode) { BinaryProcedures.CreateBinaryWriter(out var ms, out var writer); writer.Write((byte)PacketTypes.Failure); byte flags = 0; if (reqReceivedFromInP2pMode == null) { flags |= Flag_EPtoA; } writer.Write(flags); if (reqReceivedFromInP2pMode != null) { NeighborToken32 = reqReceivedFromInP2pMode.RemoteNeighborToken32; NeighborToken32.Encode(writer); } ReqP2pSeq16.Encode(writer); writer.Write((byte)ResponseCode); if (reqReceivedFromInP2pMode != null) { this.NeighborHMAC = reqReceivedFromInP2pMode.GetNeighborHMAC(this.GetSignedFieldsForNeighborHMAC); this.NeighborHMAC.Encode(writer); } return(ms.ToArray()); }
/// <param name="connectionToNeighbor">is null for A->EP mode</param> public byte[] Encode_OptionallySignNeighborHMAC(ConnectionToNeighbor connectionToNeighborNullable) { BinaryProcedures.CreateBinaryWriter(out var ms, out var writer); writer.Write((byte)PacketTypes.RegisterAck2); byte flags = 0; if (connectionToNeighborNullable == null) { flags |= Flag_AtoEP; } writer.Write(flags); if (connectionToNeighborNullable != null) { NeighborToken32 = connectionToNeighborNullable.RemoteNeighborToken32; NeighborToken32.Encode(writer); } GetSharedSignedFields(writer, true, true); ReqP2pSeq16.Encode(writer); if (connectionToNeighborNullable != null) { connectionToNeighborNullable.GetNeighborHMAC(this.GetSignedFieldsForNeighborHMAC).Encode(writer); } return(ms.ToArray()); }
/// <param name="reqReceivedFromInP2pMode">is not null for packets between registered peers</param> public byte[] Encode_OpionallySignNeighborHMAC(ConnectionToNeighbor reqReceivedFromInP2pMode) { BinaryProcedures.CreateBinaryWriter(out var ms, out var writer); writer.Write((byte)PacketTypes.RegisterAck1); byte flags = 0; if (reqReceivedFromInP2pMode == null) { flags |= Flag_EPtoA; } writer.Write(flags); if (reqReceivedFromInP2pMode != null) { NeighborToken32 = reqReceivedFromInP2pMode.RemoteNeighborToken32; NeighborToken32.Encode(writer); } GetSharedSignedFields(writer, true, true); if (reqReceivedFromInP2pMode != null) { ReqP2pSeq16.Encode(writer); this.NeighborHMAC = reqReceivedFromInP2pMode.GetNeighborHMAC(this.GetSignedFieldsForNeighborHMAC); this.NeighborHMAC.Encode(writer); } else { BinaryProcedures.EncodeIPEndPoint(writer, RequesterEndpoint); } return(ms.ToArray()); }
/// <param name="connectionToNeighbor">is not null for packets between registered peers</param> public byte[] Encode_OptionallySignNeighborHMAC(ConnectionToNeighbor connectionToNeighbor) { BinaryProcedures.CreateBinaryWriter(out var ms, out var writer); writer.Write((byte)PacketTypes.RegisterConfirmation); Flags = 0; if (connectionToNeighbor == null) { Flags |= Flag_AtoEP; } writer.Write(Flags); if (connectionToNeighbor != null) { NeighborToken32 = connectionToNeighbor.RemoteNeighborToken32; NeighborToken32.Encode(writer); } writer.Write(ReqTimestamp64); RequesterRegistrationId.Encode(writer); ResponderRegistrationConfirmationSignature.Encode(writer); RequesterRegistrationConfirmationSignature.Encode(writer); ReqP2pSeq16.Encode(writer); if (connectionToNeighbor != null) { this.NeighborHMAC = connectionToNeighbor.GetNeighborHMAC(this.GetSignedFieldsForNeighborHMAC); this.NeighborHMAC.Encode(writer); } return(ms.ToArray()); }
/// <param name="connectionToNeighborNullable">is not null for packets between registered peers. if set, the procedure sets NeighborToken32 and NeighborHMAC</param> public byte[] Encode_OptionallySignNeighborHMAC(ConnectionToNeighbor connectionToNeighborNullable) { PacketProcedures.CreateBinaryWriter(out var ms, out var writer); writer.Write((byte)PacketTypes.RegisterReq); byte flags = 0; if (connectionToNeighborNullable == null) { flags |= Flag_AtoEP; } if (DirectionVectorNullable != null) { flags |= Flag_DirectionVectorExists; } writer.Write(flags); if (connectionToNeighborNullable != null) { NeighborToken32 = connectionToNeighborNullable.RemoteNeighborToken32; NeighborToken32.Encode(writer); } GetSharedSignedFields(writer, true); if (connectionToNeighborNullable == null) { if (ProofOfWork2.Length != 64) { throw new ArgumentException(); } writer.Write(ProofOfWork2); } writer.Write(NumberOfHopsRemaining); writer.Write(NumberOfRandomHopsRemaining); ReqP2pSeq16.Encode(writer); if (connectionToNeighborNullable != null) { NeighborHMAC = connectionToNeighborNullable.GetNeighborHMAC(this.GetSignedFieldsForNeighborHMAC); NeighborHMAC.Encode(writer); } return(ms.ToArray()); }
public byte[] Encode_SetP2pFields(ConnectionToNeighbor transmitToNeighbor) { PacketProcedures.CreateBinaryWriter(out var ms, out var w); w.Write((byte)PacketTypes.InviteReq); byte flags = 0; w.Write(flags); ReqP2pSeq16 = transmitToNeighbor.GetNewRequestP2pSeq16_P2P(); NeighborToken32 = transmitToNeighbor.RemoteNeighborToken32; NeighborToken32.Encode(w); GetSignedFieldsForNeighborHMAC(w); NeighborHMAC = transmitToNeighbor.GetNeighborHMAC(GetSignedFieldsForNeighborHMAC); NeighborHMAC.Encode(w); return(ms.ToArray()); }
public NeighborPeerAckPacket(byte[] nextHopResponsePacketData) { var reader = PacketProcedures.CreateBinaryReader(nextHopResponsePacketData, 1); ReqP2pSeq16 = RequestP2pSequenceNumber16.Decode(reader); var flags = reader.ReadByte(); if ((flags & FlagsMask_MustBeZero) != 0) { throw new NotImplementedException(); } if ((flags & Flag_EPtoA) == 0) { NeighborToken32 = NeighborToken32.Decode(reader); } ResponseCode = (ResponseOrFailureCode)reader.ReadByte(); if ((flags & Flag_EPtoA) == 0) { NeighborHMAC = HMAC.Decode(reader); } }
/// <summary> /// initializes parameters to transmit direct (p2p) packets form requester A to neighbor N /// </summary> public void Decrypt_ack1_ToResponderTxParametersEncrypted_AtRequester_DeriveSharedDhSecret(Logger logger, RegisterRequestPacket req, RegisterAck1Packet ack1) { SharedDhSecret = _engine.CryptoLibrary.DeriveEcdh25519SharedSecret(LocalEcdhe25519PrivateKey, ack1.ResponderEcdhePublicKey.Ecdh25519PublicKey); #region iv, key BinaryProcedures.CreateBinaryWriter(out var ms, out var writer); req.GetSharedSignedFields(writer, true); ack1.GetSharedSignedFields(writer, false, false); var iv = _engine.CryptoLibrary.GetHashSHA256(ms.ToArray()).Take(16).ToArray(); ms.Write(SharedDhSecret, 0, SharedDhSecret.Length); var aesKey = _engine.CryptoLibrary.GetHashSHA256(ms.ToArray()); // here SHA256 is used as KDF, together with common fields from packets, including both ECDH public keys and timestamp #endregion var toNeighborTxParametersDecrypted = new byte[ack1.ToResponderTxParametersEncrypted.Length]; _engine.CryptoLibrary.ProcessAesCbcBlocks(false, aesKey, iv, ack1.ToResponderTxParametersEncrypted, toNeighborTxParametersDecrypted); // parse toNeighborTxParametersDecrypted using (var reader = new BinaryReader(new MemoryStream(toNeighborTxParametersDecrypted))) { RemoteEndpoint = BinaryProcedures.DecodeIPEndPoint(reader); RemoteNeighborToken32 = NeighborToken32.Decode(reader); RemoteNatBehaviour = NatBehaviourModel.Decode(reader); var magic16 = reader.ReadUInt16(); if (magic16 != Magic16_responderToRequester) { throw new BrokenCipherException(); } } if (logger.WriteToLog_detail_enabled) { if (logger.WriteToLog_detail_enabled) { logger.WriteToLog_detail($"decrypted remote responder endpoint={RemoteEndpoint}, remoteNeighborToken={RemoteNeighborToken32} from ACK1"); } } }
/// <summary>initializes parameters to transmit direct (p2p) packets form neighbor N to requester A</returns> public void Decrypt_ack2_ToRequesterTxParametersEncrypted_AtResponder_InitializeP2pStream(Logger logger, RegisterRequestPacket req, RegisterAck1Packet ack1, RegisterAck2Packet ack2) { #region key, iv PacketProcedures.CreateBinaryWriter(out var ms, out var writer); req.GetSharedSignedFields(writer, true); ack1.GetSharedSignedFields(writer, true, true); ack2.GetSharedSignedFields(writer, false, false); var iv = _engine.CryptoLibrary.GetHashSHA256(ms.ToArray()).Take(16).ToArray(); ms.Write(SharedDhSecret, 0, SharedDhSecret.Length); var aesKey = _engine.CryptoLibrary.GetHashSHA256(ms.ToArray()); // here SHA256 is used as KDF, together with common fields from packets, including both ECDH public keys and timestamp #endregion var toRequesterTxParametersDecrypted = new byte[ack2.ToRequesterTxParametersEncrypted.Length]; _engine.CryptoLibrary.ProcessAesCbcBlocks(false, aesKey, iv, ack2.ToRequesterTxParametersEncrypted, toRequesterTxParametersDecrypted); // parse toRequesterTxParametersDecrypted using (var reader = new BinaryReader(new MemoryStream(toRequesterTxParametersDecrypted))) { RemoteEndpoint = PacketProcedures.DecodeIPEndPoint(reader); RemoteNeighborToken32 = NeighborToken32.Decode(reader); var magic16 = reader.ReadUInt16(); if (magic16 != Magic16_ipv4_requesterToResponder) { throw new BrokenCipherException(); } } if (logger.WriteToLog_detail_enabled) { logger.WriteToLog_detail($"decrypted remote requester endpoint={RemoteEndpoint}, remoteNeighborToken={RemoteNeighborToken32} from ACK2"); } InitializeP2pStream(req, ack1, ack2); }