Skip to content

Instantly share code, notes, and snippets.

@fiddyspence
Created November 7, 2017 16:25
Show Gist options
  • Save fiddyspence/cbe9e9aa352a520e5cb1566427de67de to your computer and use it in GitHub Desktop.
Save fiddyspence/cbe9e9aa352a520e5cb1566427de67de to your computer and use it in GitHub Desktop.
// 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