<commit_before>package main

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

import (
	"fmt"
	"strconv"
)

func main() {
	a := "this is a test"
	b := "wokka wokka!!!"
	if strHamDist(a, b) != 37 {
		panic("strHamDist func is broken!")
	}

	btext := []byte(ciphertext)
	possibles := []int{}
	for i := 2; i < 41; i++ {

		first := btext[0:i]
		second := btext[i : 2*i]
		s1 := string(first)
		s2 := string(second)
		hd := strHamDist(s1, s2)
		normHD := float64(hd) / float64(i)
		if normHD < 2.8 {
			possibles = append(possibles, i)
		}

	}
	for _, v := range possibles {
		blocks := blocksplit([]byte(ciphertext), v)
		tblocks := transpose(blocks, v)
		_ = tblocks

	}

}

func transpose(blocks [][]byte, size int) [][]byte {
	fmt.Println(blocks)
	tblocks := [][]byte{}
	for i := 0; i < size; i++ {
		t := []byte{}
		tblocks = append(tblocks, t)
	}
	for _, v := range blocks {
		for a, b := range v {
			m := a % size
			tblocks[m] = append(tblocks[m], b)
		}

	}
	return tblocks
}

func blocksplit(source []byte, size int) [][]byte {
	r := [][]byte{}
	slen := len(source)
	for i := 0; i < slen; i += size {
		block := source[i : i+size]
		r = append(r, block)
	}

	return r
}

func strHamDist(s1, s2 string) int {

	t := 0
	for k, v := range s1 {

		n1 := int64(v)
		n2 := int64(s2[k])
		b1 := strconv.FormatInt(n1, 2)
		b2 := strconv.FormatInt(n2, 2)
		b1 = fmt.Sprintf("%07d", b1)
		b2 = fmt.Sprintf("%07d", b2)

		for k := range b1 {
			if b1[k] != b2[k] {
				t += 1
			}
		}

	}
	return t
}

var ciphertext = `HUIfTQsPAh9PE048GmllH0kcDk4TAQsHThsBFkU2AB4BSWQgVB0dQzNTTmVS
BgBHVBwNRU0HBAxTEjwMHghJGgkRTxRMIRpHKwAFHUdZEQQJAGQmB1MANxYG
DBoXQR0BUlQwXwAgEwoFR08SSAhFTmU+Fgk4RQYFCBpGB08fWXh+amI2DB0P
QQ1IBlUaGwAdQnQEHgFJGgkRAlJ6f0kASDoAGhNJGk9FSA8dDVMEOgFSGQEL
QRMGAEwxX1NiFQYHCQdUCxdBFBZJeTM1CxsBBQ9GB08dTnhOSCdSBAcMRVhI
CEEATyBUCHQLHRlJAgAOFlwAUjBpZR9JAgJUAAELB04CEFMBJhAVTQIHAh9P
G054MGk2UgoBCVQGBwlTTgIQUwg7EAYFSQ8PEE87ADpfRyscSWQzT1QCEFMa
TwUWEXQMBk0PAg4DQ1JMPU4ALwtJDQhOFw0VVB1PDhxFXigLTRkBEgcKVVN4
Tk9iBgELR1MdDAAAFwoFHww6Ql5NLgFBIg4cSTRWQWI1Bk9HKn47CE8BGwFT
QjcEBx4MThUcDgYHKxpUKhdJGQZZVCFFVwcDBVMHMUV4LAcKQR0JUlk3TwAm
HQdJEwATARNFTg5JFwQ5C15NHQYEGk94dzBDADsdHE4UVBUaDE5JTwgHRTkA
Umc6AUETCgYAN1xGYlUKDxJTEUgsAA0ABwcXOwlSGQELQQcbE0c9GioWGgwc
AgcHSAtPTgsAABY9C1VNCAINGxgXRHgwaWUfSQcJABkRRU8ZAUkDDTUWF01j
OgkRTxVJKlZJJwFJHQYADUgRSAsWSR8KIgBSAAxOABoLUlQwW1RiGxpOCEtU
YiROCk8gUwY1C1IJCAACEU8QRSxORTBSHQYGTlQJC1lOBAAXRTpCUh0FDxhU<commit_msg>added needed functions from ch4, added TODO base base64<commit_after>package main

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

import (
	"encoding/hex"
	"fmt"
	"strconv"
	"strings"
)

type result struct {
	RawText   string
	Key       string
	Score     int
	Decrypted string
}

const tkeys = "<KEY>"

func main() {
	a := "this is a test"
	b := "wokka wokka!!!"
	if strHamDist(a, b) != 37 {
		panic("strHamDist func is broken!")
	}

	//TODO
	//ciphertext needs to be decoded from base64
	btext := []byte(ciphertext)
	possibles := []int{}
	for i := 2; i < 41; i++ {

		first := btext[0:i]
		second := btext[i : 2*i]
		s1 := string(first)
		s2 := string(second)
		hd := strHamDist(s1, s2)
		normHD := float64(hd) / float64(i)
		if normHD < 2.8 {
			possibles = append(possibles, i)
		}

	}
	for _, v := range possibles {
		blocks := blocksplit([]byte(ciphertext), v)
		tblocks := transpose(blocks, v)
		_ = tblocks

	}

}

func transpose(blocks [][]byte, size int) [][]byte {
	fmt.Println(blocks)
	tblocks := [][]byte{}
	for i := 0; i < size; i++ {
		t := []byte{}
		tblocks = append(tblocks, t)
	}
	for _, v := range blocks {
		for a, b := range v {
			m := a % size
			tblocks[m] = append(tblocks[m], b)
		}

	}
	return tblocks
}

func blocksplit(source []byte, size int) [][]byte {
	r := [][]byte{}
	slen := len(source)
	for i := 0; i < slen; i += size {
		block := source[i : i+size]
		r = append(r, block)
	}

	return r
}

func strHamDist(s1, s2 string) int {

	t := 0
	for k, v := range s1 {

		n1 := int64(v)
		n2 := int64(s2[k])
		b1 := strconv.FormatInt(n1, 2)
		b2 := strconv.FormatInt(n2, 2)
		b1 = fmt.Sprintf("%07d", b1)
		b2 = fmt.Sprintf("%07d", b2)

		for k := range b1 {
			if b1[k] != b2[k] {
				t += 1
			}
		}

	}
	return t
}

func processPhrase(phrase string) result {
	r := result{}
	msg := phrase
	var key byte
	var highest = 0

	for _, v := range tkeys {
		key = byte(v)

		hexData, err := hex.DecodeString(msg)
		if err != nil {
			fmt.Println(err)
			return r
		}

		result := []byte{}

		for k := range hexData {
			r := hexData[k] ^ key
			result = append(result, r)
		}
		score := scorePhrase(strings.ToUpper(string(result)))
		if score > highest {
			highest = score
			r.Key = string(key)
			r.RawText = phrase
			r.Score = score
			r.Decrypted = string(result)
		}
	}

	return r
}

func scorePhrase(words string) int {
	result := 0
	freq := make(map[string]int)
	check1 := []string{"E", "T", "A"}
	check2 := []string{"O", "I", "N"}
	check3 := []string{"S", "H", "R", " "}
	check4 := []string{"D", "L", "U"}
	_, _, _ = check2, check3, check4
	length := float64(len(words))
	for _, v := range words {
		k := string(v)
		if c, ok := freq[k]; ok {
			freq[k] = c + 1
		} else {
			freq[k] = 1
		}
	}

	for _, c := range check1 {
		if float64(freq[c])/length > .017 {
			result += 4
		}

	}
	for _, c := range check2 {
		if float64(freq[c])/length > .017 {
			result += 3
		}
	}
	for _, c := range check3 {
		if float64(freq[c])/length > .017 {
			result += 2
		}
	}
	for _, c := range check4 {
		if float64(freq[c])/length > .017 {
			result++
		}
	}

	return result
}

var ciphertext = `<KEY>
{'fraction_non_alphanumeric': 0.1559633027522936, 'fraction_numerical': 0.042093901780895844, 'mean_word_length': 3.5387755102040814, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '717193', 'n_tokens_mistral': 2899, 'n_tokens_neox': 2592, 'n_words': 526}