Created
November 7, 2017 16:25
-
-
Save fiddyspence/cbe9e9aa352a520e5cb1566427de67de to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// cryptopals 1.6 | |
package main | |
import ( | |
"os" | |
"fmt" | |
"encoding/base64" | |
"math" | |
"strings" | |
"io/ioutil" | |
"strconv" | |
"encoding/hex" | |
) | |
func makeRange(min, max int) []byte { | |
a := make([]byte, max-min+1) | |
for i := range a { | |
a[i] = byte(i) | |
} | |
return a | |
} | |
func readfile(file string) []byte { | |
dat, err := ioutil.ReadFile(file) | |
if err != nil { | |
panic(err) | |
} | |
return dat | |
} | |
func bitSetCount(v byte) byte { | |
v = (v & 0x55) + ((v>>1) & 0x55) | |
v = (v & 0x33) + ((v>>2) & 0x33) | |
return (v + (v>>4)) & 0xF | |
} | |
func hammingdistance (byteone, bytetwo []byte) float32 { | |
diff := float32(0) | |
for i, c := range byteone { | |
bitdiff := bitSetCount(c ^ bytetwo[i]) | |
bitdiffint, _ := strconv.Atoi(fmt.Sprintf("%d", bitdiff)) | |
bitdifffloat := float32(bitdiffint) | |
diff += bitdifffloat | |
} | |
return diff | |
} | |
func main () { | |
filetoread := os.Args[1] | |
cleartext := readfile(filetoread) | |
base64decodeddata , _ := base64.StdEncoding.DecodeString(fmt.Sprintf("%s",cleartext)) | |
data := []byte(base64decodeddata) | |
keysize := 10 | |
maxkeysize := 40 | |
bestkeyscore := float32(maxkeysize) | |
bestkeysize := keysize | |
keymap := make(map[int]float32) | |
rounds := 4 | |
for i := keysize ; i < maxkeysize + 1 ; i++ { | |
thiskeyscore := float32(0) | |
j := float32(i) | |
for p := 0 ; p < rounds ; p++ { | |
thiskeyscore += hammingdistance ([]byte(data[p * i : (p * i) + i - 1 ]) , []byte(data[ p * i + i : p * i + i + i ])) | |
} | |
if thiskeyscore / float32(rounds) / j < bestkeyscore { | |
bestkeyscore = thiskeyscore / float32(rounds) / j | |
bestkeysize = i | |
} | |
keymap[i] = thiskeyscore / 4.0 / j | |
} | |
fmt.Printf("Best key score: %f\n", bestkeyscore) | |
fmt.Printf("Best key size: %d\n", bestkeysize) | |
blockmap := splitblocks(bestkeysize, data) | |
charblockmap := arrangeblocks(bestkeysize, blockmap) | |
fmt.Printf("Charblockmap array length: %d\n", len(charblockmap)) | |
rotatingkey := make([]byte, bestkeysize) | |
for i, j := range charblockmap { | |
rotatingkey[i] = scoreastring(j, i) | |
} | |
thekey, _ := hex.DecodeString(fmt.Sprintf("%x", rotatingkey)) | |
fmt.Printf("%s\n", thekey) | |
finaltext := decrypttextwithrotatingkey(rotatingkey, data) | |
fmt.Printf("%s\n", finaltext) | |
} | |
func decrypttextwithrotatingkey (key []byte, text []byte) string { | |
decryptedtext := "" | |
keycount := 0 | |
keylength := float64(len(key)) | |
for _, c := range text { | |
currentkey := key[keycount] | |
foo := fmt.Sprintf("%x", c ^ currentkey) | |
bar, _ := hex.DecodeString(foo) | |
decryptedtext += fmt.Sprintf("%s", bar) | |
keycount ++ | |
if math.Remainder(float64(keycount) , keylength) == 0 { | |
keycount = 0 | |
} | |
} | |
return decryptedtext | |
} | |
func scoreastring(xorstring []byte, round int) byte { | |
xorbytes := makeRange(0,255) | |
bestscore := 0.0 | |
bestbyte := byte(0) | |
for _, c := range xorbytes { | |
targetbytearray := make([]byte, len(xorstring)) | |
score := 0.0 | |
fullstring := "" | |
for i, b := range xorstring { | |
targetbytearray[i] = b ^ c | |
hexstring := fmt.Sprintf("%x", targetbytearray[i]) | |
foo, _ := hex.DecodeString(hexstring) | |
thischar := fmt.Sprintf("%s", targetbytearray[i]) | |
fullstring += thischar | |
score += scoretext(fmt.Sprintf("%s", foo)) | |
} | |
if score > bestscore { | |
bestscore = score | |
bestbyte = c | |
} | |
} | |
return bestbyte | |
} | |
func arrangeblocks(bestkeysize int, blocks [][]byte) [][]byte { | |
fmt.Printf("Arranging %d blocks\n", len(blocks)) | |
blockreturn := make([][]byte, bestkeysize) | |
for i, _ := range blockreturn { | |
blockreturn[i] = make([]byte, len(blocks)) | |
fmt.Printf("Each blockreturn byte array is %d\n", len(blockreturn[i])) | |
} | |
for i, v := range blocks { | |
for j, w := range v { | |
blockreturn[j][i] = w | |
} | |
} | |
fmt.Printf("Returning %s", len(blockreturn)) | |
return blockreturn | |
} | |
func splitblocks (blocksize int, data []byte) [][]byte { | |
fmt.Printf("Data length %d, Blocksize %d \n", len(data), blocksize) | |
blockcount := 0 | |
if math.Remainder(float64(len(data)) , float64(blocksize)) > 0 { | |
blockcount = (len(data) / blocksize) + 1 | |
} else { | |
blockcount = len(data) / blocksize | |
} | |
bytearrayarray := make([][]byte, blockcount) | |
datacount := 0 | |
thisbitofdata := make([]byte, blocksize) | |
for i, _ := range bytearrayarray { | |
start := i * blocksize | |
end := start + blocksize | |
datacount += (end - start) | |
if end > len(data) { | |
thisbitofdata = data[start:] | |
} else { | |
thisbitofdata = data[start:end] | |
} | |
fmt.Printf("Length of blocksize %d %d\n", len(thisbitofdata), thisbitofdata) | |
bytearrayarray[i] = thisbitofdata | |
} | |
fmt.Printf("Total data %d\n", datacount) | |
return bytearrayarray | |
} | |
func scoretext(inchar string) float64 { | |
scores := map[string]float64{ | |
"a": 0.0651738, | |
"b": 0.0124248, | |
"c": 0.0217339, | |
"d": 0.0349835, | |
"e": 0.1041442, | |
"f": 0.0197881, | |
"g": 0.0158610, | |
"h": 0.0492888, | |
"i": 0.0558094, | |
"j": 0.0009033, | |
"k": 0.0050529, | |
"l": 0.0331490, | |
"m": 0.0202124, | |
"n": 0.0564513, | |
"o": 0.0596302, | |
"p": 0.0137645, | |
"q": 0.0008606, | |
"r": 0.0497563, | |
"s": 0.0515760, | |
"t": 0.0729357, | |
"u": 0.0225134, | |
"v": 0.0082903, | |
"w": 0.0171272, | |
"x": 0.0013692, | |
"y": 0.0145984, | |
"z": 0.0007836, | |
" ": 0.1918182, | |
} | |
return scores[strings.ToLower(inchar)] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment