Esempio n. 1
0
        // Hash-based Message Authentication Codes: generates a code for verifying the sender of a message and the like
        public static byte[] HMAC(byte[] key, byte[] message, HashFunction func, int blockSizeBytes)
        {
            if (key.Length > blockSizeBytes)
            {
                key = func(key);
            }
            else if (key.Length < blockSizeBytes)
            {
                byte[] b = new byte[blockSizeBytes];
                Array.Copy(key, b, key.Length);
                key = b;
            }

            byte[] o_key_pad = new byte[blockSizeBytes]; // Outer padding
            byte[] i_key_pad = new byte[blockSizeBytes]; // Inner padding
            for (int i = 0; i < blockSizeBytes; ++i)
            {
                // Combine padding with key
                o_key_pad[i] = (byte)(key[i] ^ 0x5c);
                i_key_pad[i] = (byte)(key[i] ^ 0x36);
            }
            return(func(Support.Concatenate(o_key_pad, func(Support.Concatenate(message, i_key_pad)))));
        }
Esempio n. 2
0
 // Deserialize RSA data (for key distribution (but the other end (how many parentheses deep can I go?)))
 public static RSA Deserialize(byte[] function, out int read)
 {
     byte[][] rd = Support.DeserializeBytes(function, 2);
     read = rd[0].Length + rd[1].Length + 8;
     return(new RSA(rd[0], rd[1]));
 }
Esempio n. 3
0
 // Serialize (for public key distribution)
 public byte[] Serialize() => Support.SerializeBytes(new byte[][] { e.ToByteArray(), n.ToByteArray() });
Esempio n. 4
0
 public static byte[] FromHeaded(byte[] msg, int offset) => msg.SubArray(offset + 4, offset + 4 + Support.ReadInt(msg, offset));
Esempio n. 5
0
        protected internal bool SyncListener(ref bool cryptoEstablished, ref int mLen, out bool acceptedData, Queue <byte> ibuf, byte[] buffer)
        {
            if (cryptoEstablished)
            {
                lock (messageBuffer)
                {
                    foreach (byte[] message in messageBuffer)
                    {
                        Connection.Send(NetSupport.WithHeader(message));
                    }
                    messageBuffer.Clear();
                }
            }
            if (acceptedData = Connection.Available > 0)
            {
                int read = Connection.Receive(buffer);
                ibuf.EnqueueAll(buffer, 0, read);
            }
            if (mLen == 0 && ibuf.Count >= 4)
            {
                mLen = Support.ReadInt(ibuf.Dequeue(4), 0);
            }
            if (mLen != 0 && ibuf.Count >= mLen)
            {
                // Got a full message. Parse!
                byte[] message = ibuf.Dequeue(mLen);

                if (!cryptoEstablished)
                {
                    if (ServerSide)
                    {
                        try
                        {
                            if (Crypto == null)
                            {
                                Crypto = Rijndael128.Deserialize(decrypt.Decrypt(message), out int _);
                            }
                            else
                            {
                                CBC = new PCBC(Crypto, decrypt.Decrypt(message));
                            }
                        }
                        catch (Exception) {
                            Console.WriteLine("A fatal error ocurrd when attempting to establish a secure channel! Stopping...");
                            Thread.Sleep(5000);
                            Environment.Exit(-1);
                        }
                    }
                    else
                    {
                        // Reconstruct RSA object from remote public keys and use it to encrypt our serialized AES key/iv
                        RSA asymm = RSA.Deserialize(message, out int _);
                        Connection.Send(NetSupport.WithHeader(asymm.Encrypt(Crypto.Serialize())));
                        Connection.Send(NetSupport.WithHeader(asymm.Encrypt(CBC.IV)));
                    }
                    if (CBC != null)
                    {
                        cryptoEstablished = true;
                        onConn(this);
                    }
                }
                else
                {
                    // Decrypt the incoming message
                    byte[] read = Crypto.Decrypt(message);

                    // Read the decrypted message length
                    int mlenInner = Support.ReadInt(read, 0);

                    // Send the message to the handler and get a response
                    string response = handler(read.SubArray(4, 4 + mlenInner).ToUTF8String(), out bool live);

                    // Send the response (if given one) and drop the connection if the handler tells us to
                    if (response != null)
                    {
                        Connection.Send(NetSupport.WithHeader(Crypto.Encrypt(NetSupport.WithHeader(response.ToUTF8Bytes()))));
                    }
                    if (!live)
                    {
                        Running = false;
                        try
                        {
                            Connection.Close();
                        }
                        catch (Exception) { }
                        return(true);
                    }
                }

                // Reset expexted message length
                mLen = 0;
            }
            return(false);
        }
Esempio n. 6
0
        // Password-Based Key Derivation Function 2. Used to generate "pseudorandom" keys from a given password and salt using a certain PRF applied a certain amount of times (iterations).
        // dklen specified the "derived key length" in bytes. It is recommended to use a high number for the iterations variable (somewhere around 4096 is the standard for SHA1 currently)
        public static byte[] PBKDF2(PRF function, byte[] password, byte[] salt, int iterations, int dklen)
        {
            byte[] dk   = new byte[0]; // Create a placeholder for the derived key
            uint   iter = 1;           // Track the iterations

            while (dk.Length < dklen)
            {
                // F-function
                // The F-function (PRF) takes the amount of iterations performed in the opposite endianness format from what C# uses, so we have to swap the endianness
                byte[] u    = function(password, Support.Concatenate(salt, Support.WriteToArray(new byte[4], Support.SwapEndian(iter), 0)));
                byte[] ures = new byte[u.Length];
                Array.Copy(u, ures, u.Length);
                for (int i = 1; i < iterations; ++i)
                {
                    // Iteratively apply the PRF
                    u = function(password, u);
                    for (int j = 0; j < u.Length; ++j)
                    {
                        ures[j] ^= u[j];
                    }
                }

                // Concatenate the result to the dk
                dk = Support.Concatenate(dk, ures);

                ++iter;
            }

            // Clip aby bytes past what we needed (yes, that's really what the standard is)
            return(dk.ToLength(dklen));
        }
Esempio n. 7
0
        public static byte[] SHA1(byte[] message)
        {
            // Initialize buffers
            uint h0 = 0x67452301;
            uint h1 = 0xEFCDAB89;
            uint h2 = 0x98BADCFE;
            uint h3 = 0x10325476;
            uint h4 = 0xC3D2E1F0;

            // Pad message
            int ml = message.Length + 1;

            byte[] msg = new byte[ml + ((960 - (ml * 8 % 512)) % 512) / 8 + 8];
            Array.Copy(message, msg, message.Length);
            msg[message.Length] = 0x80;
            long len = message.Length * 8;

            for (int i = 0; i < 8; ++i)
            {
                msg[msg.Length - 1 - i] = (byte)((len >> (i * 8)) & 255);
            }
            //Support.WriteToArray(msg, message.Length * 8, msg.Length - 8);
            //for (int i = 0; i <4; ++i) msg[msg.Length - 5 - i] = (byte)(((message.Length*8) >> (i * 8)) & 255);

            int chunks = msg.Length / 64;

            // Perform hashing for each 512-bit block
            for (int i = 0; i < chunks; ++i)
            {
                // Split block into words
                uint[] w = new uint[80];
                for (int j = 0; j < 16; ++j)
                {
                    w[j] |= (uint)((msg[i * 64 + j * 4] << 24) | (msg[i * 64 + j * 4 + 1] << 16) | (msg[i * 64 + j * 4 + 2] << 8) | (msg[i * 64 + j * 4 + 3] << 0));
                }

                // Expand words
                for (int j = 16; j < 80; ++j)
                {
                    w[j] = Rot(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
                }

                // Initialize chunk-hash
                uint
                    a = h0,
                    b = h1,
                    c = h2,
                    d = h3,
                    e = h4;

                // Do hash rounds
                for (int t = 0; t < 80; ++t)
                {
                    uint tmp = Rot(a, 5) + func(t, b, c, d) + e + K(t) + w[t];
                    e = d;
                    d = c;
                    c = Rot(b, 30);
                    b = a;
                    a = tmp;
                }
                h0 += a;
                h1 += b;
                h2 += c;
                h3 += d;
                h4 += e;
            }

            return(Support.WriteContiguous(new byte[20], 0, Support.SwapEndian(h0), Support.SwapEndian(h1), Support.SwapEndian(h2), Support.SwapEndian(h3), Support.SwapEndian(h4)));
        }