// find lowest Hamming Distance for each possible keysize from MIN_KEYSIZE to MAX_KEYSIZE // Note: With minimal samples, you may not get the correct lowest calculated value. (using 1 or 2 for example) public static IEnumerable <HammingScore> FindProbableKeySize(byte[] cipherBytes, int minKeySize = 1, int maxKeySize = 40, int numSamples = 6, int topCnt = 3) { var hamList = new List <HammingScore>(); if (numSamples < 1) { throw new ArgumentException("Number of samples must be one or greater"); } int minCipherSizeReq = (numSamples + 1) * maxKeySize; if (minCipherSizeReq > cipherBytes.Length) { throw new ArgumentException($"Cipher bytes must be at least {minCipherSizeReq} bytes to accomodate number of samples."); } for (int keySize = minKeySize; keySize <= maxKeySize; keySize++) { uint runTot = 0; for (int sampleNum = 0; sampleNum < numSamples; sampleNum++) { int startNdx = sampleNum * keySize; runTot += MHString.HammingDistance(cipherBytes, startNdx, startNdx + keySize, keySize); } double avg = Math.Round(((double)runTot / (double)(keySize * numSamples)), 5); hamList.Add(new HammingScore(keySize, numSamples, avg)); } return(hamList.OrderBy(h => h.AvgScore).Take(topCnt).ToList()); }