Tags: golang cryptography math
Rating:
# The Most Worthy Distinction of Pain
```go
package main
import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
)
func readFlag() (string, error) {
	flag_file, err := os.Open("flag.txt")
	if err != nil {
		return "", err
	}
	defer flag_file.Close()
	scanner := bufio.NewScanner(flag_file)
	scanner.Scan()
	flag := scanner.Text()
	return flag, nil
}
func combine(flag []uint8) []uint16 {
	combined := []uint16{}
	for i := 0; i < len(flag); i += 2 {
		c := uint16(flag[i]) << 8
		if i+1 < len(flag) {
			c += uint16(flag[i+1])
		}
		combined = append(combined, c)
	}
	return combined
}
func encrypt(flag string) string {
	codex_file, err := os.Open("CROSSWD.TXT")
	if err != nil {
		return "!"
	}
	defer codex_file.Close()
	all_words := []string{}
	combined := combine([]uint8(flag))
	for _, c := range combined {
		all_words = append(all_words, encode_one(c, codex_file))
	}
	return strings.Join(all_words, " ")
}
func encode_one(c uint16, codex_file *os.File) string {
	codex_file.Seek(0, io.SeekStart)
	scanner := bufio.NewScanner(codex_file)
	for i := uint16(0); i < c; i++ {
		scanner.Scan()
	}
	return scanner.Text()
}
func main() {
	flag, err := readFlag()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(encrypt(flag))
}
```
it's all around the abyse of bit operations.
There, every second character was encrypted as follows:
ascii character code << 8 and add to it the ascii code of the next character (For example, 98 << 8 = 25088 + 121 = 25209), then, from the line number, which is equal to the received number, we take a word from the dictionary and substitute it into the ciphertext.
To decipher, it turns out we need to do the reverse operation: find a word in the dictionary, take its number, subtract the number X from it, and here stop, we don't know the number, that's where the abuz begins.
We can simply perform the reverse shift operation >>, without adding, and we will get the number to which we added (25088). For example, if we shift 25209 >> 8 = 98, and now if we shift 98 << 8, then we get 25088!!!! From here we get the following: 25209 - 25088 = 121, so we get all the numbers that are in even positions.
As part of the byuctf{testflag} test flag, it will be y c f t s f a }
And it's even easier to get odd ones, we just take the line numbers and move them (25209 >> 8 = 98)
```go
package main
import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
)
func readFlag() (string, error) {
	flagFile, err := os.Open("encrypted.txt")
	if err != nil {
		return "", err
	}
	defer flagFile.Close()
	scanner := bufio.NewScanner(flagFile)
	scanner.Scan()
	flag := scanner.Text()
	return flag, nil
}
func combine(flag []uint8) []uint16 {
	combined := []uint16{}
	for i := 0; i < len(flag); i += 2 {
		c := uint16(flag[i]) << 8
		if i+1 < len(flag) {
			c += uint16(flag[i+1])
		}
		combined = append(combined, c)
	}
	return combined
}
func revertCombine(flag []uint16) []uint16 {
	combined := []uint16{}
	for i := 0; i < len(flag); i += 1 {
		c := flag[i] >> 8
		combined = append(combined, c)
	}
	return combined
}
func encrypt(flag string) string {
	codex_file, err := os.Open("CROSSWD.TXT")
	if err != nil {
		return "!"
	}
	defer codex_file.Close()
	all_words := []string{}
	combined := combine([]uint8(flag))
	for _, c := range combined {
		all_words = append(all_words, encodeOne(c, codex_file))
	}
	return strings.Join(all_words, " ")
}
func encodeOne(c uint16, codex_file *os.File) string {
	codex_file.Seek(0, io.SeekStart)
	scanner := bufio.NewScanner(codex_file)
	for i := uint16(0); i < c; i++ {
		scanner.Scan()
	}
	return scanner.Text()
}
func getLineNumber(myString string) (int, error) {
	f, err := os.Open("CROSSWD.txt")
	if err != nil {
		return 0, err
	}
	defer f.Close()
scanner := bufio.NewScanner(f)
line := 1
	for scanner.Scan() {
		if scanner.Text() == myString {
			return line, nil
		}
		line++
	}
	if err := scanner.Err(); err != nil {
	}
	return 0, nil
}
func makeThatShit(flag_data []uint16) ([]uint16, []string) {
	result_flag := revertCombine(flag_data)
	second_flag_part := []string{}
	for i, c := range result_flag {
		c = c << 8
		second_flag_part = append(second_flag_part, string(flag_data[i]-uint16(c)))
	}
	return result_flag, second_flag_part
}
func main() {
	flag, err := readFlag()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(encrypt(flag))
	words := strings.Fields(flag)
	fmt.Println(words)
	flag_data := []uint16{}
	for _, c := range words {
		lineNumber, _ := getLineNumber(c)
		flag_data = append(flag_data, uint16(lineNumber))
	}
	fmt.Println(flag_data)
	first, second := makeThatShit(flag_data)
	for i := 0; i < len(first); i++ {
		print(string(first[i]), second[i])
	}
}
```