func TestFrequencyAttack(t *testing.T) { const ( charset = "abcdefghijklmnopqrstuvwxyz" ) message, err := ioutil.ReadFile(os.Getenv("GOPATH") + "src/github.com/karlek/tombraid/message.txt") csLen := len(charset) for i := 0; i < csLen; i++ { cipher, err := broken.Caesar(charset, message, i) if err != nil { return err } chars := frequency.EnglishAnalysis(cipher) if err != nil { return err } guesses, err := FrequencyAttack(chars, charset, cipher) if err != nil { return t.Errorf("FrequencyAttack(%v, %v, %v, %v) = %v, want %v\n\n", chars, charset, cipher, unciphered, message) } for _, unciphered := range guesses { if unciphered == message { return nil } } } }
func FrequencyAttack(chars []string, charset, cipher string) (guesses []string, err error) { // for _, commonChar := range frequency.Top3 { for _, char := range chars { pos := strings.Index(charset, char) if pos == -1 { return nil, errorsutil.Errorf("Character `%c` is not present in charset: `%s`", char, charset) } commonCharPos := strings.Index(charset, commonChar) if commonCharPos == -1 { return nil, errorsutil.Errorf("Character `%c` is not present in charset: `%s`", commonChar, charset) } unwindBy := commonCharPos - pos unciphered, err := broken.Caesar(charset, cipher, unwindBy) if err != nil { return nil, err } guesses = append(guesses, unciphered) } } return guesses, nil }
func breakCaesar() (err error) { buf, err := ioutil.ReadFile(os.Getenv("GOPATH") + "/src/github.com/karlek/tombraid/message.txt") if err != nil { return err } message := string(buf) csLen := len(charset) isFreqBroken := false isBruteBroken := false for i := 0; i < csLen; i++ { cipher, err := broken.Caesar(charset, message, i) if err != nil { return err } commonChars := frequency.EnglishAnalysis(cipher) freqGuesses, err := caesar.FrequencyAttack(commonChars, charset, cipher) if err != nil { return err } bruteGuesses, err := caesar.BruteAttack(charset, cipher) if err != nil { return err } for _, guess := range freqGuesses { if guess == message { isFreqBroken = true } } for _, guess := range bruteGuesses { if guess == message { isBruteBroken = true } } } switch { case isFreqBroken && isBruteBroken: fmt.Println("All attacks successful!") case isFreqBroken: fmt.Println("Only frequency attack worked!") case isBruteBroken: fmt.Println("Only brute force attack worked!") default: fmt.Println("No attack broke the cipher!") } return nil }
// Preforms a brute force attack by shifting the cipher foreach // character in the charset func BruteAttack(charset, cipher string) (guesses []string, err error) { csLen := len(charset) for i := 0; i < csLen; i++ { newCipher, err := broken.Caesar(charset, cipher, i) if err != nil { return nil, err } guesses = append(guesses, newCipher) } return guesses, nil }