/// <summary> /// Loads the encrypted part of the .mrb file into the Club /// </summary> public void LoadEncryptedSection() { /********************************** * HOW ENCRYPTION IN MARIMBA WORKS* * One part of the .mrb file is encrypted, the other is not * The part that is not encrypted is login information * A user will try to login with their password * The double-hash of the password is used to check the hash is correct * If correct, login will retrieve the key the rest of the file is encrypted with * That key is stored by being xor'd with the single hash of the password * As long as the password is unknown and SHA-256 is preimage resistant, this should be secure * The rest of the file is encrypted in 256-bit AES * The key is retreived, and the rest of the file is decrypted * The file is loaded into Marimba as normally would be * If a user changes their password, the key xor'd with the single hash is redone * If an admin updates the key, everyone gets their key/hash thing updated * This can easily be done if the key is known since xor is linear * */ // DECRYPT ENCRYPTED SECTION using (Aes aesAlg = Aes.Create()) { aesAlg.Key = this.aesInfo.Key; aesAlg.IV = this.aesInfo.IV; // Create a decrytor to perform the stream transform. ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); // Create the streams used for decryption. using (MemoryStream memoryStream = new MemoryStream(cipherText)) { using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) { using (StreamReader reader = new StreamReader(cryptoStream)) { // read the membership list iMember = Convert.ToInt16(reader.ReadLine()); for (int i = 0; i < iMember; i++) members[i] = new Member(reader); short numTerms = Convert.ToInt16(reader.ReadLine()); listTerms = new List<Term>(numTerms); for (int i = 0; i < numTerms; i++) { Term nextTerm = new Term(reader); listTerms.Add(nextTerm); } // read the budget stuff int iBudget = Convert.ToInt32(reader.ReadLine()); this.budget = new List<BudgetItem>(iBudget + BudgetBuffer); List<int> assetToDepIndices = new List<int>(iBudget); for (int i = 0; i < iBudget; i++) { BudgetItem newItem = new BudgetItem(); newItem.value = Convert.ToDouble(reader.ReadLine()); newItem.name = reader.ReadLine(); newItem.dateOccur = new DateTime(Convert.ToInt64(reader.ReadLine())); newItem.dateAccount = new DateTime(Convert.ToInt64(reader.ReadLine())); newItem.cat = reader.ReadLine(); newItem.type = (TransactionType)Convert.ToInt32(reader.ReadLine()); newItem.term = Convert.ToInt32(reader.ReadLine()); newItem.comment = ClsStorage.ReverseCleanNewLine(reader.ReadLine()); budget.Add(newItem); assetToDepIndices.Add(Convert.ToInt32(reader.ReadLine())); } int k = 0; foreach (BudgetItem item in this.budget) { int assetToDepIndex = assetToDepIndices[k]; item.depOfAsset = (assetToDepIndex == -1) ? null : this.budget[assetToDepIndex]; k++; } int iHistory = Convert.ToInt32(reader.ReadLine()); historyList = new List<HistoryItem>(iHistory + HistoryBuffer); for (int i = 0; i < iHistory; i++) { HistoryItem nextItem = new HistoryItem(reader); historyList.Add(nextItem); } // read email if (fileVersion >= 2) { emailAddress = reader.ReadLine(); imapServerAddress = reader.ReadLine(); this.bImap = Convert.ToBoolean(reader.ReadLine()); smptServerAddress = reader.ReadLine(); smtpRequiresSSL = Convert.ToInt32(reader.ReadLine()); imapRequiresSSL = Convert.ToBoolean(reader.ReadLine()); } } } } // remove cipherText from storage cipherText = null; } this.clubEmail = new Email(emailAddress, Properties.Settings.Default.emailPassword, imapServerAddress, this.bImap, smptServerAddress, smtpRequiresSSL, imapRequiresSSL); }
/// <summary> /// Returns the index of the last common member between two memberlists /// </summary> /// <param name="low">Low index</param> /// <param name="high">High index</param> /// <param name="memberlist1">First array of members</param> /// <param name="memberlist2">Second array of members</param> /// <returns>Returns index of last common member</returns> public static int lastCommonMember(int low, int high, Member[] memberlist1, Member[] memberlist2) { // found the first differing member if (low >= high) { if (memberlist1[low].email == memberlist2[low].email) return low; else return low - 1; } else { int mid = (low + high) / 2; if (memberlist1[low].email == memberlist2[low].email && memberlist1[mid].email == memberlist2[mid].email) return lastCommonMember(mid + 1, high, memberlist1, memberlist2); else return lastCommonMember(low, mid - 1, memberlist1, memberlist2); } }
/// <summary> /// Adds a member to the club member list /// this version is kept for legacy purposes to open old data. /// Potentially updates an old member instead of adding a new member /// </summary> /// <param name="strFName">First name</param> /// <param name="strLName">Last name</param> /// <param name="type">Type of member</param> /// <param name="uiID">ID number to give to this member</param> /// <param name="iFaculty">Faculty of member</param> /// <param name="strInstrument">Instrument which this member plays</param> /// <param name="strEmail">Email of user</param> /// <param name="strOther">Other info</param> /// <param name="signup">Time that this member signed up</param> /// <returns>Whether a strictly new member is added; if an old member is updated, this return false</returns> public bool AddMember(string strFName, string strLName, Member.MemberType type, uint uiID, int iFaculty, string strInstrument, string strEmail, string strOther, DateTime signup) { // before adding, check if it is a duplicate member // a matching student number or email address will be the judge of this for (int i = 0; i < iMember; i++) if (this.members[i].email == strEmail || (this.members[i].uiStudentNumber == uiID && uiID != 0)) { this.members[i].EditMember(strFName, strLName, type, uiID, iFaculty, strInstrument, strEmail, strOther, members[i].signupTime, -1); return false; } this.members[iMember] = new Member(strFName, strLName, type, uiID, iFaculty, strInstrument, strEmail, strOther, signup, -1); iMember++; return true; }