Beispiel #1
0
        internal byte[] EncryptHttpMessage(byte[] httpMessage, FfRequest request)
        {
            Debug.WriteLine("Encrypting HTTP message using AES-256-GCM with PBKDF2");

            var salt = new byte[16];

            this.rng.GetBytes(salt);
            var derivedKey = KeyDerivation.Pbkdf2(
                password: this.config.PreSharedKey,
                salt: salt,
                prf: KeyDerivationPrf.HMACSHA256,
                iterationCount: this.config.Pbkdf2Iterations,
                numBytesRequested: 256 / 8
                );

            var iv = new byte[12];

            this.rng.GetBytes(iv);
            var tag        = new byte[16];
            var cipherText = new byte[httpMessage.Length];


            using (var aesGcm = new AesGcm(derivedKey))
            {
                aesGcm.Encrypt(iv, httpMessage, cipherText, tag);
            }

            request.Options.Add(new FfRequestOption()
            {
                OptionType = FfRequestOption.Type.TYPE_ENCRYPTION_MODE,
                Value      = new byte[] { (byte)FfEncryptionMode.AES_256_GCM }
            });

            request.Options.Add(new FfRequestOption()
            {
                OptionType = FfRequestOption.Type.TYPE_ENCRYPTION_IV,
                Value      = iv
            });

            request.Options.Add(new FfRequestOption()
            {
                OptionType = FfRequestOption.Type.TYPE_ENCRYPTION_TAG,
                Value      = tag
            });

            request.Options.Add(new FfRequestOption()
            {
                OptionType = FfRequestOption.Type.TYPE_KEY_DERIVE_MODE,
                Value      = new byte[] { (byte)FfKeyDeriveMode.PBKDF2 }
            });

            request.Options.Add(new FfRequestOption()
            {
                OptionType = FfRequestOption.Type.TYPE_KEY_DERIVE_SALT,
                Value      = salt
            });

            return(cipherText);
        }
Beispiel #2
0
        internal List <UdpPacket> PacketiseRequest(FfRequest request)
        {
            var  packets     = new List <UdpPacket>();
            uint bytesLeft   = (uint)request.Payload.Length;
            uint chunkOffset = 0;

            while (bytesLeft > 0)
            {
                var packet = new byte[MAX_PACKET_LENGTH];
                int i      = 0;

                this.WriteNumber <ushort>(packet, (ushort)request.Version, ref i);
                this.WriteNumber <ulong>(packet, request.RequestId, ref i);
                this.WriteNumber <uint>(packet, (uint)request.Payload.Length, ref i);
                this.WriteNumber <uint>(packet, chunkOffset, ref i);
                // Defer writing chunk length (int16)
                int chunkLengthOffset = i;
                i += 2;

                if (chunkOffset == 0)
                {
                    this.WriteOptions(packet, request.Options, ref i);
                }
                else
                {
                    // Only first packet has options so write EOL option for non initial packets
                    packet[i++] = (byte)FfRequestOption.Type.TYPE_EOL;
                    this.WriteNumber <ushort>(packet, 0, ref i);
                }

                ushort chunkLength = (ushort)Math.Min(bytesLeft, MAX_PACKET_LENGTH - i);

                Buffer.BlockCopy(request.Payload, (int)chunkOffset, packet, i, chunkLength);
                i += chunkLength;

                // Write chunk length
                this.WriteNumber <ushort>(packet, chunkLength, ref chunkLengthOffset);

                bytesLeft   -= chunkLength;
                chunkOffset += chunkLength;

                packets.Add(new UdpPacket()
                {
                    Packet = packet,
                    Length = i
                });
            }

            return(packets);
        }
Beispiel #3
0
        internal byte[] EncryptHttpMessage(byte[] httpMessage, FfRequest request)
        {
            Debug.WriteLine("Encrypting HTTP message using AES-256-GCM");

            var iv = new byte[12];

            this.rng.GetBytes(iv);
            var tag        = new byte[16];
            var cipherText = new byte[httpMessage.Length];

            var paddedKey = new byte[32];
            var keyBytes  = Encoding.UTF8.GetBytes(this.config.PreSharedKey);

            Buffer.BlockCopy(keyBytes, 0, paddedKey, 0, keyBytes.Length);

            using (var aesGcm = new AesGcm(paddedKey))
            {
                aesGcm.Encrypt(iv, httpMessage, cipherText, tag);
            }

            request.Options.Add(new FfRequestOption()
            {
                OptionType = FfRequestOption.Type.TYPE_ENCRYPTION_MODE,
                Value      = new byte[] { (byte)FfEncryptionMode.AES_256_GCM }
            });

            request.Options.Add(new FfRequestOption()
            {
                OptionType = FfRequestOption.Type.TYPE_ENCRYPTION_IV,
                Value      = iv
            });

            request.Options.Add(new FfRequestOption()
            {
                OptionType = FfRequestOption.Type.TYPE_ENCRYPTION_TAG,
                Value      = tag
            });

            return(cipherText);
        }
Beispiel #4
0
        internal async Task <List <UdpPacket> > CreateRequestPackets(HttpRequestMessage httpRequest)
        {
            Debug.WriteLine("Sending HTTP request using FfClient");

            var requestIdBytes = new byte[8];

            this.rng.GetBytes(requestIdBytes);

            var request = new FfRequest()
            {
                Version   = FfRequestVersion.V1,
                RequestId = BitConverter.ToUInt64(requestIdBytes)
            };

            if (httpRequest.RequestUri.Scheme.ToLower() == "https")
            {
                request.Options.Add(new FfRequestOption()
                {
                    OptionType = FfRequestOption.Type.TYPE_HTTPS,
                    Value      = new byte[] { 1 }
                });
            }

            byte[] httpMessage = await this.SerializeHttpMessage(httpRequest);

            if (!string.IsNullOrEmpty(this.config.PreSharedKey))
            {
                httpMessage = this.EncryptHttpMessage(httpMessage, request);
            }

            request.Options.Add(new FfRequestOption()
            {
                OptionType = FfRequestOption.Type.TYPE_EOL
            });

            request.Payload = httpMessage;

            return(this.PacketiseRequest(request));
        }
Beispiel #5
0
        private void CreateRequestSecureOptions(FfRequest request, HttpRequestMessage httpRequest)
        {
            if (httpRequest.RequestUri.Scheme.ToLower() == "https")
            {
                request.SecureOptions.Add(new FfRequestOption()
                {
                    OptionType = FfRequestOption.Type.TYPE_HTTPS,
                    Value      = new byte[] { 1 }
                });
            }

            request.SecureOptions.Add(new FfRequestOption()
            {
                OptionType = FfRequestOption.Type.TYPE_TIMESTAMP,
                Value      = this.GetCurrentTimestampBytes()
            });

            request.SecureOptions.Add(new FfRequestOption()
            {
                OptionType = FfRequestOption.Type.TYPE_EOL
            });
        }
Beispiel #6
0
        internal async Task <List <UdpPacket> > CreateRequestPackets(HttpRequestMessage httpRequest)
        {
            Debug.WriteLine("Sending HTTP request using FfClient");

            var requestIdBytes = new byte[8];

            this.rng.GetBytes(requestIdBytes);

            var request = new FfRequest()
            {
                Version   = FfRequestVersion.V1,
                RequestId = BitConverter.ToUInt64(requestIdBytes)
            };

            this.CreateRequestSecureOptions(request, httpRequest);

            byte[] secureOptions = this.SerializeRequestOptions(request.SecureOptions);
            byte[] httpMessage   = await this.SerializeHttpMessage(httpRequest);

            byte[] payload = new byte[secureOptions.Length + httpMessage.Length];
            Buffer.BlockCopy(secureOptions, 0, payload, 0, secureOptions.Length);
            Buffer.BlockCopy(httpMessage, 0, payload, secureOptions.Length, httpMessage.Length);

            if (!string.IsNullOrEmpty(this.config.PreSharedKey))
            {
                payload = this.EncryptPayload(payload, request);
            }

            request.Options.Add(new FfRequestOption()
            {
                OptionType = request.SecureOptions.Count == 0 ? FfRequestOption.Type.TYPE_EOL : FfRequestOption.Type.TYPE_BREAK
            });

            request.Payload = payload;

            return(this.PacketiseRequest(request));
        }