Example #1
0
        /// <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());
        }
Example #2
0
        /// <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());
        }
Example #3
0
        /// <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());
        }
Example #5
0
        /// <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());
        }
Example #6
0
        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());
        }
Example #7
0
        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);
            }
        }
Example #8
0
        /// <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");
                }
            }
        }
Example #9
0
        /// <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);
        }