Friedman TestThe Friedman Test is used if you already know that a message was encrypted with Vigenère cipher. It uses the Index of Coincidence (IC) to compute the approximate length of the key. Once you have the length the cipher can be cracked using Kasiski examination and frequency analyses. Friedman Test is a great help for this.
If you have not heard anything about IC please read this thread first:
Frequency Analysis and Index of CoincidenceIf you want a message to try this out, take this (key length is five):
TFNMJBDCRITVVAFSRCJIFDPINNNMKAPELIWTTPYQFUIWJSJBIXULMGPXRZWNFDQXOPICRSALAERNVVKJHRVKJOJQIMBKBISTZKLZFSMVWPSWXJSLVXJSYIPYFERSWVEVLNFCBHFTDMRXDYTMHIVOIMJIVJZFIMMSFESSRQCQDNFIBISDFUTZUVZWTGZMAFSJQGMOZKLYTFAMHIKMVTCJQIIBQCWYJDUXJFZVQJOJKLRVJAXJEFKLRFYZWJJEIPXFZVIRBJKLNOV
This is the Java source for FriedmanTest (nothing complicated since I already made the IC class):
public class FriedmanTest implements Analysis {
//language is needed for the language specific IC
private Language language;
public FriedmanTest(Language language) {
this.language = language;
}
//returns the computed key length
@Override
public String analyse(String code) {
IndexOfCoincidence ic = new IndexOfCoincidence();
ic.analyse(code);
double kappaRandom = ic.computeKappaRandom();
double kappaText = ic.computeKappaText();
long n = code.length();
double kappaExpected = language.getIC() / ic.amountOfCharacters();
double keyLength = computeKeyLength(kappaRandom, kappaText,
kappaExpected, n);
return "computed key length: " + keyLength;
}
//uses the formula for the approximate key length
private double computeKeyLength(double kappaRandom, double kappaText,
double kappaExpected, long n) {
return ((kappaExpected - kappaRandom) * n)
/ ((n - 1) * kappaText - kappaRandom * n + kappaExpected);
}
}
The enums in Java are pretty useful for saving some language specific data:
public enum Language {
ENGLISH(1.73, "English"),
GERMAN(2.05, "German"),
FRENCH(2.02, "French"),
ITALIAN(1.94, "Italian"),
PORTUGUESE(1.94, "Portuguese"),
RUSSIAN(1.76, "Russian"),
SPANISH(1.94, "Spanish"),
UNKNOWN(2.0, "Unknown");
private double ic;
private String name;
private Language(double ic, String name) {
this.ic = ic;
this.name = name;
}
public double getIC() {
return ic;
}
@Override
public String toString() {
return name;
}
}
Deque