public static AuthKey CreateLocalKey(byte[] password, byte[] salt)
 => new AuthKey(
     KDF.PKCS5_PBKDF2_HMAC_SHA1(
         pass: password ?? EmptyPassword,
         salt: salt,
         iter: password == null ? Constants.LocalKeyNoPwdIterCount : Constants.LocalKeyIterCount,
         keylen: Constants.NeededAuthKeySize));
 public User(string name, string passHash, byte[] salt, long balance, bool generatePass = false, List <Transaction> transactionHistory = null, bool admin = false)
 {
     History         = transactionHistory ?? new List <Transaction>();
     Balance         = balance;
     Name            = name;
     IsAdministrator = admin;
     Salt            = Convert.ToBase64String(salt);
     PasswordHash    = generatePass ? Convert.ToBase64String(KDF.PBKDF2(KDF.HMAC_SHA1, Encoding.UTF8.GetBytes(passHash), Encoding.UTF8.GetBytes(Salt), 8192, 320)) : passHash;
 }
 public bool Authenticate(string password)
 => Convert.ToBase64String(KDF.PBKDF2(KDF.HMAC_SHA1, Encoding.UTF8.GetBytes(password), Encoding.UTF8.GetBytes(Salt), 8192, 320)).Equals(PasswordHash);
Esempio n. 4
0
        static void Main(string[] args)
        {
            Console.Write("Enter your personal password: "******"Generating authentication code...");

            // Generate a password-based Message Authentication Code (with salt to prevent rainbowtables) to verify the user identity against the server
            // This string will be used as our database key: a (pseudo-)unique identifier which, for all intents and purposes, can be as public as we like since it doesn't do an attacker any good to know it
            string auth = Support.ToHexString(KDF.PBKDF2(KDF.HMAC_SHA1, key.ToUTF8Bytes(), "NoRainbow".ToUTF8Bytes(), 8192, 128));

            // Create private encryption/decryption algorithm for processing private (encrypted) data stored on server
            Rijndael128    privCrypt = new Rijndael128(key);
            RandomProvider provider  = new CryptoRandomProvider();

            bool connected = false;
            bool load      = false;
            // AES key used for communication is randomly chosen by generating anywhere between 1 and 511 random bytes as the password for PBKDF2-HMAC-SHA1
            NetClient client = new NetClient(new Rijndael128(provider.GetBytes(provider.NextInt(511) + 1).ToUTF8String()), ParseIP(), ParsePort(), (string message, out bool keepAlive) =>
            {
                if (message.StartsWith("M-"))
                {
                    // Handle a blank response
                    if (message.Length == 2)
                    {
                        Console.WriteLine("No messages exist with your password");
                    }
                    else
                    {
                        string[] msgs = null;
                        try
                        {
                            msgs = Support.DeserializeString(message.Substring(2));
                        }
                        catch (Exception) { Console.WriteLine("The server seems to have sent an incorrect message. The stored messages could not be read!"); }

                        foreach (var cmsg in msgs)
                        {
                            try
                            {
                                // Decrypt each message with the supplied decryptor
                                byte[] messages_pad = privCrypt.Decrypt(Convert.FromBase64String(cmsg));
                                int len             = Support.ReadInt(messages_pad, 0);
                                string messages     = messages_pad.SubArray(4, len + 4).ToUTF8String();
                                Console.WriteLine(messages);
                            }
                            catch (Exception) { /* Ignore corrupt message (maybe do something else here?) */ }
                        }


                        Console.WriteLine("\nPress any key to continue...");
                        Console.ReadKey();
                        Console.Clear();
                    }
                    load = false;
                }

                // Tell the client object to keep the connection alive
                keepAlive = true;

                // Don't respond
                return(null);
            }, cli =>
            {
                Console.WriteLine("Connected to server!");
                connected = true;
            });

            // Server-connection-attempt loop (mostly just UI/UX stuff)
            do
            {
                try
                {
                    Console.WriteLine("Connecting to server...");
                    client.Connect(); // <----- Only important line in this entire loop
                    break;
                }
                catch (Exception)
                {
                    Console.Write("The server rejected the connection (probably because the server isn't running). Try again? (Y/n): ");
                    if (Console.In.ReadYNBool("n"))
                    {
                        Console.WriteLine("OK. Exiting...");
                        Thread.Sleep(2500);
                        Environment.Exit(0);
                    }
                    Console.Clear();
                }
            } while (true);

            while (!connected)
            {
                Thread.Sleep(125);
            }

            Console.WriteLine();

            bool alive = true;

            while (alive)
            {
                // Show selection menu
                switch (DoSelect())
                {
                case 1:
                {
                    // Get and send a message to the server
                    Console.Clear();
                    Console.Write("Message to send to server: ");
                    string message = Console.ReadLine();
                    if (message.Length == 0)
                    {
                        message = "\0";                              // Blank messages are parsed as a null byte
                    }
                    // Encrypt the message with our personal AES object (which hopefully only we know)
                    byte[] toSend = privCrypt.Encrypt(NetSupport.WithHeader(message.ToUTF8Bytes()));

                    // Send to the server
                    if (!client.TrySend("S-" + auth + "-" + Convert.ToBase64String(toSend)))
                    {
                        Console.WriteLine("Unfortunately, an error ocurred when attempting to send your message to the server :(");
                    }
                    break;
                }

                case 2:
                {
                    // Send a request to the server for a list of all messages associated with the hex key we generated in the beginning
                    Console.Clear();
                    Console.WriteLine("Loading messages...");

                    // Send the "Load" command along with our db key
                    if (!client.TrySend("L-" + auth))
                    {
                        Console.WriteLine("Unfortunately, an error ocurred when attempting to send your message to the server :(");
                    }
                    load = true;
                    while (load)
                    {
                        Thread.Sleep(125);
                    }
                    break;
                }

                case 3:
                    Console.WriteLine("Exiting...");

                    // Await client disconnection
                    try { client.Disconnect(); }
                    catch (Exception) { }

                    // Stop program
                    Environment.Exit(0);
                    break;
                }
            }

            while (client.IsAlive)
            {
                Thread.Sleep(250);
            }
        }