Me aburrí anoche, solo toma alrededor de 1 minuto forzar la fuerza bruta en una palabra-lista de 27143 palabras.
String |Key |Encrypted |Decrypted
-------------------+-------------------+-------------------+-------------------
ANAL |PREACH |PEEL |PEEP
ANTS |BEHOLD |BRAG |BROW
AURA |JOKER |JIBE |JUTE
AWRY |TARIFF |TWIG |TEAK
BLOC |SPORADIC |TACT |REAP
BINS |JAYWALK |KILO |ISLE
CANE |REROUTE |TEES |PEEK
CANE |ROACH |TONG |PONY
CARP |RODENT |TOUT |POMP
CART |FAULTED |HALE |DADS
CART |FIELDED |HIVE |DINS
CART |PENMANSHIP |REEF |NEWT
CAPE |TETHER |VEIL |REED
CUED |BURBLE |DOVE |ZANY
DENS |WEAKEN |ZINC |TANS
DENT |GEOLOGICAL |JIBE |DABS
DENT |PEEL |SIRE |MARS
DEAN |PERFECTED |SIRS |MARS
FADS |WAIL |BALD |RAFT
FATS |GABLE |LAUD |BAIT
FATS |WAYLAID |BARD |RAFT
FAWN |ROOFED |WOKS |MOSS
FEUD |METHODICAL |RINK |HAZE
HART |WAIL |DAZE |PARS
GAPE |NOTHINGNESS |TOIL |HOED
GASH |JOLLIED |PODS |DOTE
HIPS |AMPLER |HUED |TEAT
GALA |MARS |SACS |GAGS
HAUL |YOGA |FOAL |ROMP
HURL |LUMPED |SODA |EAVE
JELL |BEAD |KILO |SAPS
LARD |SONOROUS |DOER |HOWL
LASH |COLLABORATE |NODS |ROTE
LATH |RAILED |CABS |GAPE
LINT |SMALLPOX |DUNE |HENS
LONE |LABORATORIES |WOOS |AMOK
MATH |TOLLED |FOES |HOSE
MATS |HELLISH |TEED |VEST
MAIM |UNSKILLED |GNAW |INKY
LAVA |RAGS |CABS |GALS
MALT |FIELDED |RIPE |TITS
MUSH |BULLDOG |NODS |PATE
MAMA |BADE |NAPE |PARE
MAMA |DABS |PANS |RAPS
MAMA |DISSATISFACTION |PIES |RIGS
MAMA |FADS |RAPS |TARS
MAMA |FUSSED |RUES |TUGS
MAMA |RAPS |DABS |FADS
MAMA |RODENT |DOPE |FORE
MAMA |TOSSED |FOES |HOGS
NAPE |POROUS |COGS |COCK
OUCH |BURLAP |POTS |NAPE
OUST |FOLLIES |TIDE |RUTS
LAIR |COWBOY |NOES |ROOK
PAIL |GELD |VETO |REDS
LIEU |EMIGRANT |PUMA |TEEM
PANS |SURLIER |HUED |DUET
PAPA |EELS |TEAS |PEWS
PAPA |HARSHER |WAGS |SACS
OKRA |MONSOON |AYES |YEWS
PARE |QUIVER |FUZZ |BURR
OXEN |SHIFTIER |GEMS |EKES
MART |FAILINGS |RAZE |TARS
PEPS |HAPLESS |WEED |SWAT
PACT |HECKLE |WEED |SEAR
MASH |DOLL |PODS |ROTE
MASH |FOLLIES |RODS |TOTE
PREY |GROCER |VISA |RAKE
PUMA |DUDS |SOPS |OARS
PUMA |GOSSAMER |VIES |RUGS
QUAY |RUNGS |HONE |BANI
RAYS |CANKER |TALC |LAPS
PAWN |SORRIER |HONE |DOVE
PAWN |WORRISOME |LONE |HOVE
RUNE |JOYOUS |AILS |SULK
RUNT |QUARANTINE |HONK |ZANY
PEAL |PREHISTORIC |EVES |ANEW
PEEK |SERUM |HIVE |DANK
RUED |SUPPER |JOTS |BALM
SNUB |DRYS |VEST |LEER
SASH |VOLLEY |NODS |DOTE
SNAP |UNREAL |MART |CARP
SAUNA |DEXTERITY |VERGE |LEDGE
TOOT |HOTLY |ACHE |OAFS
TANS |MEALIER |FEND |TENT
TUNA |MOOS |FIBS |TUBS
TUNA |WORSEN |PIES |DUES
TART |MAILBOXES |FAZE |TARS
TOTS |HILLBILLIES |AWED |OUST
TONG |AIRY |TWEE |HUES
VENT |BEFALL |WIST |GASH
WAXY |LEPROSY |HEMP |PEST
WANE |XENOPHOBIA |TEAS |BEAK
WANNA |LAIRS |HAVES |PAVES
YUCK |FUTURES |DOVE |HARK
VATS |MULL |HUED |RUST
YARN |FAIRIES |DAZE |HARE
WAFT |HAUL |DAZE |LAPS
Usé english-words.35
de esta lista de palabras . También me limité a palabras de 4 letras o más. Puedes usar un diccionario más grande para obtener más resultados.
Aquí está el programa para forzar la lista bruta.
//Program.cs - Runs the Vigenere brute forcer and displays the result.
using System;
using System.Diagnostics;
using System.IO;
using System.Collections.Generic;
using System.Linq;
namespace Sandbox_Console
{
class Program
{
public static void Main()
{
Stopwatch runtime = new Stopwatch();
runtime.Start();
var vigenere = new Vigenere(@"C:\scowl\final\english-words.10", @"C:\scowl\final\english-words.20", @"C:\scowl\final\english-words.35",
@"C:\scowl\final\english-words.40", @"C:\scowl\final\english-words.50", @"C:\scowl\final\english-words.55",
@"C:\scowl\final\english-words.60", @"C:\scowl\final\american-words.10", @"C:\scowl\final\american-words.20",
@"C:\scowl\final\american-words.35", @"C:\scowl\final\american-words.40", @"C:\scowl\final\american-words.50",
@"C:\scowl\final\american-words.55", @"C:\scowl\final\american-words.60");
Console.WriteLine("Wordlist size: {0:N0}", vigenere.WordListSize);
//Console.WriteLine("{0,-19}|{1,-19}|{2,-19}|{3,-19}", "String", "Key", "Encrypted", "Decrypted");
//Console.WriteLine("{0,-19}+{1,-19}+{2,-19}+{3,-19}", new String('-', 19), new String('-', 19), new String('-', 19), new String('-', 19));
//vigenere.StartTest();
vigenere.JibberishKeys();
List<Vigenere.TwoStrings> resultsForFile = new List<Vigenere.TwoStrings>();
foreach (var result in vigenere.Results.GetConsumingEnumerable())
{
//Console.WriteLine("{0,-19}|{1,-19}|{2,-19}|{3,-19}", result.Word, result.Key, Vigenere.Encrypt(result.Word, result.Key), Vigenere.Decrypt(result.Word, result.Key));
resultsForFile.Add(result);
ShowOnlyProgress(vigenere, resultsForFile.Count);
}
runtime.Stop();
Console.WriteLine("Done in {0}", runtime.Elapsed);
using (var sr = new StreamWriter("WordKeys.txt", false))
{
sr.WriteLine("Wordlist size: {0:N0}", vigenere.WordListSize);
sr.WriteLine("Build time: {0}", runtime.Elapsed);
sr.WriteLine("{0,-19}|{1,-19}|{2,-19}|{3,-19}", "String", "Key", "Encrypted", "Decrypted");
sr.WriteLine("{0,-19}+{1,-19}+{2,-19}+{3,-19}", new String('-', 19), new String('-', 19), new String('-', 19), new String('-', 19));
foreach (var result in resultsForFile.OrderBy(a => a.Word).ThenBy(a=> a.Key))
{
sr.WriteLine("{0,-19}|{1,-19}|{2,-19}|{3,-19}", result.Word, result.Key, Vigenere.Encrypt(result.Word, result.Key), Vigenere.Decrypt(result.Word, result.Key));
}
}
Console.ReadLine();
}
static public void ShowOnlyProgress(Vigenere vigenere, int count)
{
Console.CursorTop = 1;
Console.CursorLeft = 0;
Console.WriteLine("Processed Records: {0:N0}", vigenere.ProcessedRecords);
Console.WriteLine("Found Pairs: {0:N0}", count);
}
}
}
.
//Vigenere.cs - Written by Scott Chamberlain
//Brute forces a Vingenere encryption to find pairs where S, the encrypted
// and decrypted output of S are English words.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Threading;
namespace Sandbox_Console
{
class Vigenere
{
public Vigenere(params string[] wordLists)
{
_WordList = new HashSet<string>();
foreach(var wordList in wordLists)
{
using (var wordListStream = new System.IO.StreamReader(wordList))
{
string line;
while ((line = wordListStream.ReadLine()) != null)
{
line = line.ToUpperInvariant();
if(line.Contains('\'') == false //No Apostrophes
&& line.Length >= 4) // Words 4 or longer.
_WordList.Add(Regex.Replace(line, "[^A-Z]", "")); //Replace all non letter chars then add to wordlist.
}
}
}
//Create the Vigenère square
Results = new BlockingCollection<TwoStrings>();
ResultSeen = new ConcurrentDictionary<TwoStrings, object>();
_processedRecords = 0;
}
const int ALPHABIT_SIZE = 26;
const int LETTER_OFFSET = 'A';
HashSet<string> _WordList;
public int WordListSize { get { return _WordList.Count; } }
static Lazy<char[,]> _CryptTable = new Lazy<char[,]>( () =>
{
var tmpTable = new char[ALPHABIT_SIZE, ALPHABIT_SIZE];
for (int i = 0; i < ALPHABIT_SIZE; i++)
{
for (int j = 0; j < ALPHABIT_SIZE; j++)
{
tmpTable[i, j] = (char)(((i + j) % ALPHABIT_SIZE) + LETTER_OFFSET);
}
}
return tmpTable;
});
static Lazy<char[,]> _DecryptTable = new Lazy<char[,]>( () =>
{
var tmpTable = new char[ALPHABIT_SIZE, ALPHABIT_SIZE];
for (int i = 0; i < ALPHABIT_SIZE; i++)
{
for (int j = 0; j < ALPHABIT_SIZE; j++)
{
int result = i - j;
if (result < 0)
result = ALPHABIT_SIZE + result;
tmpTable[i, j] = (char)(result + LETTER_OFFSET);
}
}
return tmpTable;
});
public BlockingCollection<TwoStrings> Results { get; private set; }
public class TwoStrings : IEquatable<TwoStrings>
{
public TwoStrings(string word, string key)
{
this.Word = word;
this.Key = key;
}
public string Word {get; private set;}
public string Key {get; private set;}
public bool Equals(TwoStrings other)
{
if (other == null)
return false;
if (this.Word == other.Word)
{
if (this.Key == other.Key)
return true;
else
{
//If the word is shorter than the key, only compare keys up to the length of the word.
var thisLen = this.Word.Length;
if (thisLen > this.Key.Length)
thisLen = this.Key.Length;
var otherLen = other.Word.Length;
if (otherLen > other.Word.Length)
otherLen = other.Key.Length;
return this.Key.Substring(0, thisLen) == other.Key.Substring(0, otherLen);
}
}
else
{
return false;
}
}
private int TrimmedKeyHashCode()
{
if (this.Key.Length <= this.Word.Length)
return this.Key.GetHashCode();
else
return this.Key.Substring(0, this.Word.Length).GetHashCode();
}
public override bool Equals(object obj)
{
return this.Equals(obj as TwoStrings);
}
public override int GetHashCode()
{
//Use unchecked to suppress arithmetic overflow exceptions
unchecked
{
return 7 +
(this.Word.GetHashCode() * 11) +
(TrimmedKeyHashCode() * 13);
}
}
}
public ConcurrentDictionary<TwoStrings, object> ResultSeen;
private int _processedRecords;
public int ProcessedRecords { get { return _processedRecords; } }
public void StartTest()
{
Task.Factory.StartNew(() =>
{
Parallel.ForEach(_WordList, TestWord);
Results.CompleteAdding();
}, TaskCreationOptions.LongRunning);
}
private void TestWord(string word)
{
foreach (string key in _WordList)
{
if (_WordList.Contains(Encrypt(word, key)) &&
_WordList.Contains(Decrypt(word, key)))
{
var testResult = new TwoStrings(word, key);
if(ResultSeen.TryAdd(testResult, null) == true) //Check that we don't have a similar key already.
Results.Add(testResult);
}
}
Interlocked.Increment(ref _processedRecords);
}
public static string Encrypt(string word, string key)
{
int keyLength = key.Length;
StringBuilder sb = new StringBuilder(word);
for (int i = 0; i < sb.Length; i++)
{
sb[i] = _CryptTable.Value[key[i % keyLength] - LETTER_OFFSET, sb[i] - LETTER_OFFSET];
}
return sb.ToString();
}
public static string Decrypt(string word, string key)
{
int keyLength = key.Length;
StringBuilder sb = new StringBuilder(word);
for (int i = 0; i < sb.Length; i++)
{
sb[i] = _DecryptTable.Value[key[i % keyLength] - LETTER_OFFSET, sb[i] - LETTER_OFFSET];
}
return sb.ToString();
}
//does the same as TestWord but the key does not need to be in the dictionary.
public void JibberishKeys()
{
Task.Factory.StartNew(() =>
{
Parallel.ForEach(_WordList, TestJibberish);
Results.CompleteAdding();
}, TaskCreationOptions.LongRunning);
}
private void TestJibberish(string word)
{
HashSet<string> keyList = new HashSet<string>();
//Build the list of all possible keys;
foreach (var keyGenWord in _WordList)
{
//Prevent a key of "AAAAA"
if (keyGenWord != word)
{
//Due to the behavior of the table
//"word == Decrypt(encryptedWord, key)" and "key == Decrypt(word, EncryptedWord)" are both true.
keyList.Add(Decrypt(word, keyGenWord));
}
}
foreach (string key in keyList)
{
//We don't need to check the wordlist for the encrypted version as that word is what generated
// the key in the first place.
if (_WordList.Contains(Decrypt(word, key)))
{
var testResult = new TwoStrings(word, key);
if (ResultSeen.TryAdd(testResult, null) == true) //Check that we don't have a similar key already.
Results.Add(testResult);
}
}
Interlocked.Increment(ref _processedRecords);
}
}
}