|
|
@ -15,7 +15,7 @@ |
|
|
|
{ |
|
|
|
{ |
|
|
|
const string SourcePhrase = "poultry outwits ants"; |
|
|
|
const string SourcePhrase = "poultry outwits ants"; |
|
|
|
|
|
|
|
|
|
|
|
const int MaxWordsInPhrase = 3; |
|
|
|
const int MaxWordsInPhrase = 4; |
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
/// <summary> |
|
|
|
/// Main entry point |
|
|
|
/// Main entry point |
|
|
@ -33,14 +33,16 @@ |
|
|
|
"665e5bcb0c20062fe8abaaf4628bb154", |
|
|
|
"665e5bcb0c20062fe8abaaf4628bb154", |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var expectedHashesAsVectors = expectedHashes.Select(hash => new Vector<byte>(StringToByteArray(hash))).ToArray(); |
|
|
|
var expectedHashesAsVectors = expectedHashes.Select(hash => new Vector<byte>(HexadecimalStringToByteArray(hash))).ToArray(); |
|
|
|
|
|
|
|
|
|
|
|
foreach (var result in AddHashes(processor.GeneratePhrases(ReadInput()))) |
|
|
|
var result = processor.GeneratePhrases(ReadInput()) |
|
|
|
|
|
|
|
.Select(phraseBytes => new { phraseBytes, hashVector = ComputeHashVector(phraseBytes) }) |
|
|
|
|
|
|
|
.Where(tuple => expectedHashesAsVectors.Contains(tuple.hashVector)) |
|
|
|
|
|
|
|
.Select(tuple => new { phrase = Encoding.ASCII.GetString(tuple.phraseBytes), hash = VectorToHexadecimalString(tuple.hashVector) }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var phraseInfo in result) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (expectedHashesAsVectors.Contains(result.Item2)) |
|
|
|
Console.WriteLine($"Found phrase for {phraseInfo.hash}: {phraseInfo.phrase} (spent {stopwatch.Elapsed})"); |
|
|
|
{ |
|
|
|
|
|
|
|
Console.WriteLine($"Found phrase: {Encoding.ASCII.GetString(result.Item1)} (spent {stopwatch.Elapsed})"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
stopwatch.Stop(); |
|
|
|
stopwatch.Stop(); |
|
|
@ -48,7 +50,7 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Code taken from http://stackoverflow.com/a/321404/831314 |
|
|
|
// Code taken from http://stackoverflow.com/a/321404/831314 |
|
|
|
private static byte[] StringToByteArray(string hex) |
|
|
|
private static byte[] HexadecimalStringToByteArray(string hex) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return Enumerable.Range(0, hex.Length) |
|
|
|
return Enumerable.Range(0, hex.Length) |
|
|
|
.Where(x => x % 2 == 0) |
|
|
|
.Where(x => x % 2 == 0) |
|
|
@ -56,15 +58,7 @@ |
|
|
|
.ToArray(); |
|
|
|
.ToArray(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static IEnumerable<Tuple<byte[], Vector<byte>>> AddHashes(IEnumerable<byte[]> input) |
|
|
|
private static Vector<byte> ComputeHashVector(byte[] input) |
|
|
|
{ |
|
|
|
|
|
|
|
foreach (var line in input) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
yield return Tuple.Create(line, ComputeHash(line)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static Vector<byte> ComputeHash(byte[] input) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
var digest = new MD5Digest(); |
|
|
|
var digest = new MD5Digest(); |
|
|
|
digest.BlockUpdate(input, 0, input.Length); |
|
|
|
digest.BlockUpdate(input, 0, input.Length); |
|
|
@ -73,6 +67,11 @@ |
|
|
|
return new Vector<byte>(hash); |
|
|
|
return new Vector<byte>(hash); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static string VectorToHexadecimalString(Vector<byte> hash) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return string.Concat(Enumerable.Range(0, 16).Select(i => hash[i].ToString("x2"))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static IEnumerable<byte[]> ReadInput() |
|
|
|
private static IEnumerable<byte[]> ReadInput() |
|
|
|
{ |
|
|
|
{ |
|
|
|
string line; |
|
|
|
string line; |
|
|
|