Matasano Crypto Challenges - Set 1 - Challenge 3 - Solved in Go

written in cryptopals, go, matasano, programming

This is the solution I came up with in Go for Set 1 / Challenge 3 of the matasano crypto challenges.

This one was a little more difficult than the previous two, on the off-chance that you’re reading this post shortly after it was published; I plan to come back tomorrow and detail my thought process / how I came to a solution so stay tuned for an update.

Code after the break…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package main

import hex "encoding/hex"
import "fmt"
import "sort"

func main() {
    sourceString := "1b37373331363f78151b7f2b783431333d78397828372d363c78373" +
                    "e783a393b3736"
    sourceHex, _ := hex.DecodeString(sourceString)

    // This is an array of every 'character' that may be the key used to
    // decode the source string
    decoderArray := make([]byte, 94)

    // This is the array where we'll store a 'score' for each key used
    // in the previous array
    scoreArray := make([]int, 94)
    scoreMap := make(map[int]string)

    for i, _ := range decoderArray {
        finalHex := make([]byte, 0)

        for _, v := range sourceHex {
            finalHex = append(finalHex, byte(i + 32) ^ v)
        }

        finalString := string(finalHex)
        scoreArray[i] = scoreString(finalString)
        scoreMap[i] = finalString
    }

    sortedScoreArray := make([]int, 94)
    copy(sortedScoreArray, scoreArray)

    sort.Ints(sortedScoreArray)
    sort.Sort(sort.Reverse(sort.IntSlice(sortedScoreArray)))

    highestScore := sortedScoreArray[0]
    var decoderIndex int

    for i, v := range scoreArray {
        if v == highestScore {
            decoderIndex = i
        }
    }

    fmt.Println(scoreMap[decoderIndex])
}

func scoreString(target string) int {
    score := 0

    for _, v := range target {

        switch {
        case byte(v) < 0x65:
            score = score - 1
        }

        switch string(v) {
        case "e":
            score = score + 5
        case "t":
            score = score + 5
        case "a":
            score = score + 4
        case "o":
            score = score + 4
        case "i":
            score = score + 4
        }
    }

    return score
}

Running this will output the expected result, like so:

1
2
Pu:~ nate$ go run Set1Challenge3.go
Cooking MC's like a pound of bacon

http://cryptopals.com/sets/1/challenges/3/

http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance

http://en.wikipedia.org/wiki/Letter_frequency

http://en.wikipedia.org/wiki/ASCII


Comments