usingSystem;usingSystem.Collections.Generic;usingSystem.Diagnostics;usingSystem.IO;usingSystem.Security.Cryptography;usingDistributedPasswordCracker.Client.Models;usingDistributedPasswordCracker.Client.Utilities;namespaceDistributedPasswordCracker.Client{publicclassCracking{/// <summary>/// The algorithm used for encryption./// Must be exactly the same algorithm that was used to encrypt the passwords in the password file/// </summary>privatereadonlyHashAlgorithm_messageDigest;publicCracking(){_messageDigest=newSHA1CryptoServiceProvider();//_messageDigest = new MD5CryptoServiceProvider();// seems to be same speed}/// <summary>/// Runs the password cracking algorithm/// </summary>publicList<UserInfoClearText>RunCracking(string[]dictionary){Stopwatchstopwatch=Stopwatch.StartNew();List<UserInfo>userInfos=PasswordFileHandler.ReadPasswordFile("passwords.txt");Console.WriteLine("passwd opeend");List<UserInfoClearText>result=newList<UserInfoClearText>();for(inti=0;i<dictionary.Length;i++){StringdictionaryEntry=dictionary[i];IEnumerable<UserInfoClearText>partialResult=CheckWordWithVariations(dictionaryEntry,userInfos);result.AddRange(partialResult);}stopwatch.Stop();Console.WriteLine(string.Join(", ",result));Console.WriteLine("Out of {0} password {1} was found ",userInfos.Count,result.Count);Console.WriteLine();Console.WriteLine("Time elapsed: {0}",stopwatch.Elapsed);returnresult;}/// <summary>/// Generates a lot of variations, encrypts each of the and compares it to all entries in the password file/// </summary>/// <param name="dictionaryEntry">A single word from the dictionary</param>/// <param name="userInfos">List of (username, encrypted password) pairs from the password file</param>/// <returns>A list of (username, readable password) pairs. The list might be empty</returns>privateIEnumerable<UserInfoClearText>CheckWordWithVariations(StringdictionaryEntry,List<UserInfo>userInfos){List<UserInfoClearText>result=newList<UserInfoClearText>();//might be emptyStringpossiblePassword=dictionaryEntry;IEnumerable<UserInfoClearText>partialResult=CheckSingleWord(userInfos,possiblePassword);result.AddRange(partialResult);StringpossiblePasswordUpperCase=dictionaryEntry.ToUpper();IEnumerable<UserInfoClearText>partialResultUpperCase=CheckSingleWord(userInfos,possiblePasswordUpperCase);result.AddRange(partialResultUpperCase);StringpossiblePasswordCapitalized=StringUtilities.Capitalize(dictionaryEntry);IEnumerable<UserInfoClearText>partialResultCapitalized=CheckSingleWord(userInfos,possiblePasswordCapitalized);result.AddRange(partialResultCapitalized);StringpossiblePasswordReverse=StringUtilities.Reverse(dictionaryEntry);IEnumerable<UserInfoClearText>partialResultReverse=CheckSingleWord(userInfos,possiblePasswordReverse);result.AddRange(partialResultReverse);for(inti=0;i<100;i++){StringpossiblePasswordEndDigit=dictionaryEntry+i;IEnumerable<UserInfoClearText>partialResultEndDigit=CheckSingleWord(userInfos,possiblePasswordEndDigit);result.AddRange(partialResultEndDigit);}for(inti=0;i<100;i++){StringpossiblePasswordStartDigit=i+dictionaryEntry;IEnumerable<UserInfoClearText>partialResultStartDigit=CheckSingleWord(userInfos,possiblePasswordStartDigit);result.AddRange(partialResultStartDigit);}for(inti=0;i<10;i++){for(intj=0;j<10;j++){StringpossiblePasswordStartEndDigit=i+dictionaryEntry+j;IEnumerable<UserInfoClearText>partialResultStartEndDigit=CheckSingleWord(userInfos,possiblePasswordStartEndDigit);result.AddRange(partialResultStartEndDigit);}}returnresult;}/// <summary>/// Checks a single word (or rather a variation of a word): Encrypts and compares to all entries in the password file/// </summary>/// <param name="userInfos"></param>/// <param name="possiblePassword">List of (username, encrypted password) pairs from the password file</param>/// <returns>A list of (username, readable password) pairs. The list might be empty</returns>privateIEnumerable<UserInfoClearText>CheckSingleWord(IEnumerable<UserInfo>userInfos,StringpossiblePassword){char[]charArray=possiblePassword.ToCharArray();byte[]passwordAsBytes=Array.ConvertAll(charArray,PasswordFileHandler.GetConverter());byte[]encryptedPassword=_messageDigest.ComputeHash(passwordAsBytes);//string encryptedPasswordBase64 = System.Convert.ToBase64String(encryptedPassword);List<UserInfoClearText>results=newList<UserInfoClearText>();foreach(UserInfouserInfoinuserInfos){if(CompareBytes(userInfo.EntryptedPassword,encryptedPassword))//compares byte arrays{results.Add(newUserInfoClearText(userInfo.Username,possiblePassword));Console.WriteLine(userInfo.Username+" "+possiblePassword);}}returnresults;}/// <summary>/// Compares to byte arrays. Encrypted words are byte arrays/// </summary>/// <param name="firstArray"></param>/// <param name="secondArray"></param>/// <returns></returns>privatestaticboolCompareBytes(IList<byte>firstArray,IList<byte>secondArray){//if (secondArray == null)//{// throw new ArgumentNullException("firstArray");//}//if (secondArray == null)//{// throw new ArgumentNullException("secondArray");//}if(firstArray.Count!=secondArray.Count){returnfalse;}for(inti=0;i<firstArray.Count;i++){if(firstArray[i]!=secondArray[i])returnfalse;}returntrue;}}}