//reads contact info from database and creates Contact objects
        private void loadContacts()
        {
            contactsList.Clear();                                         //empty list, if reading from database might as well reload everything

            SQLiteDataReader reader = db.retrieve("SELECT * FROM Users"); //gets all user records
            //if(reader.HasRows) //if any data was read from the DB

            Contact contact;                                                   //temporary contact object to add to list

            while (reader.Read())                                              //iterate over each tuple returned from the database
            {
                int    ID           = Convert.ToInt32((long)reader["userID"]); //sqlite handles primary key field as int64
                byte[] encUsername  = (byte[])reader["username"];
                byte[] encIPAddress = (byte[])reader["IPAddress"];
                byte[] IV           = (byte[])reader["IV"];                               //initialisation vector encUsername and ecnIPAddress were encrypted with

                byte[] masterKey = Globals.getMasterKey();                                //decrypts and gets master key

                string username  = CryptoUtility.AESDecrypt(encUsername, masterKey, IV);  //decrypt username
                string IPAddress = CryptoUtility.AESDecrypt(encIPAddress, masterKey, IV); //decrypt IPAddress

                contact = new Contact(ID, username, IPAddress);                           //puts contact info into object
                contactsList.Add(contact);
            }
        }
示例#2
0
        /// <summary>
        /// Takes the ID of a key in the database and returns a byte array containing the key.
        /// This method uses caching as it will be used frequently, this is to prevent unnecessary database reads.
        /// </summary>
        /// <param name="keyID">ID of key to fetch from keys table</param>
        /// <returns>byte[] containing key</returns>
        public byte[] getKey(int keyID)
        {
            if (isCached(keyID))                  //check if the key has been cached already
            {
                return(retrieveFromCache(keyID)); //return cached key
            }
            else //otherwise get key from database and store it in cache
            {
                SQLiteDataReader reader = db.retrieve($"SELECT AESKey, IV FROM Keys WHERE keyID = {keyID}"); //will get only one entry
                if (!reader.HasRows)                                                                         //no entry with <keyID>
                {
                    return(new byte[0]);                                                                     //return empty byte array
                }
                reader.Read();                                                                               //prepares reader to extract values

                byte[] encKey = (byte[])reader["AESKey"];                                                    //extract encrypted key
                byte[] IV     = (byte[])reader["IV"];                                                        //extract initialisation vector it was encrypted with

                byte[] key = decryptKey(encKey, IV);                                                         //decrypt key
                storeInCache(keyID, key);                                                                    //store in cache
                return(key);                                                                                 //return decrypted key
            }
        }
        /// <summary>
        /// Takes a contact and returns a list containg all messages exchanged between local and contact.
        /// </summary>
        /// <param name="contact">Contace for which to get history of exchanges messages</param>
        /// <returns>List of messages associated with the provided contact</returns>
        public List <Message> getMessageHistory(Contact contact)
        {
            List <Message> messages = new List <Message>();
            Message        message; //temp var to hold messages before being put into list

            //for <contactID> select every message, initialisation vector to decrypt the message, the ID of the key it's encrypted with, and bool if it was sent or received
            SQLiteDataReader reader = db.retrieve($"SELECT sent, message, IV, keyID FROM Messages WHERE (conversationID = \"{contact.ID}\")");

            //API BUG - SELECT with explicit fields fails ONLY when the fields are in brackets, lord knows why

            while (reader.Read())                                                //iterate over all existing records
            {
                bool   sent            = (bool)reader["sent"];                   //extract if message was sent or received
                byte[] encMessageBytes = (byte[])reader["message"];              //extract message
                byte[] messageIV       = (byte[])reader["IV"];                   //extract initialisation vector for message
                int    keyID           = Convert.ToInt32((long)reader["keyID"]); //extract ID of key that encrypted message. sqlite handles forien keys to primary keys as int64.

                byte[] messageKey = keyManager.getKey(keyID);                    //gets plain key from manager (must be discarded once done with)

                //passes encrypted message bytes, plain key and IV to CryptoUtility and gets decrypted message in return
                string messageString = CryptoUtility.AESDecrypt(encMessageBytes, messageKey, messageIV);

                messageKey = null; //garbage collect key bytes

                int senderID;
                int targetID;

                if (sent) //message was sent by local
                {
                    senderID = 0;
                    targetID = contact.ID;
                }
                else //message was sent by contact
                {
                    senderID = contact.ID;
                    targetID = 0;
                }

                message = new Message(messageString, senderID, targetID); //create the message object
                messages.Add(message);                                    //store it in list
            }

            return(messages);
        }