예제 #1
0
func BreakXorRepeating(ciphertext []byte, keysizes []int) ([]byte, error) {
	if len(ciphertext) == 0 {
		return nil, errors.New("empty ciphertext")
	}
	if len(keysizes) == 0 {
		return nil, errors.New("no keysizes given")
	}

	var bestScore = 0.0
	var plaintext []byte

	for _, size := range keysizes {
		split, _ := bytes.SplitIntoBlocks(ciphertext, size)
		transposed, err := blocks.Transpose(split)
		if err != nil {
			return nil, err
		}

		key := make([]byte, size)
		for i, block := range transposed {
			popular, _ := bytes.Popular(block, 1)
			key[i] = popular[0]
		}

		decrypted, _ := bytes.XorRepeatingKey(ciphertext, key)
		score := utils.EnglishScore(string(decrypted))

		if score > bestScore {
			plaintext = decrypted
			bestScore = score
		}
	}
	return plaintext, nil
}
예제 #2
0
func TestFindKeysizes(t *testing.T) {
	input := []byte("And you're going to do it all anew. Better run for the hills.")
	tooShort := []byte("Too short")
	empty := []byte("")
	key := []byte("YELLOW")
	size := len(key)
	n := 3

	// Invalid inputs
	encrypted, _ := bytes.XorRepeatingKey(tooShort, key)
	_, err := FindKeysizes(encrypted, n, 3, 10)
	if err.Error() != "input not long enough for analysis" {
		t.Error("should fail if ciphertext is not 4x as long as maxSize")
	}
	_, err = FindKeysizes(empty, n, 3, 10)
	if err.Error() != "empty input ciphertext" {
		t.Error("should fail given a nil ciphertext")
	}
	_, err = FindKeysizes(encrypted, n, 10, 3)
	if err.Error() != "minSize > maxSize" {
		t.Error("should fail if minSize > maxSize")
	}
	_, err = FindKeysizes(encrypted, 0, 3, 10)
	if err.Error() != "n must be > 0" {
		t.Error("should fail if n == 0")
	}

	// Valid input
	encrypted, err = bytes.XorRepeatingKey(input, key)
	keysizes, err := FindKeysizes(encrypted, n, 3, 10)
	if err != nil {
		t.Error(err)
	}
	if len(keysizes) != n {
		t.Error("expected %d keysizes, got %d", n, len(keysizes))
	}

	guessed := false
	for i := range keysizes {
		if keysizes[i] == size {
			guessed = true
		}
	}
	if !guessed {
		t.Error("guessed wrong key length")
	}
}
예제 #3
0
// Implement repeating-key XOR
func c5() (actual, expected Result) {
	input := []byte("Burning 'em, if you ain't quick and nimble\nI go crazy when I hear a cymbal")
	expected = "0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f"
	key := []byte("ICE")

	encrypted, err := bytes.XorRepeatingKey(input, key)
	if err != nil {
		log.Fatal(err)
	}

	encryptedStr := hex.EncodeToString(encrypted)
	return encryptedStr, expected
}
예제 #4
0
// Detect single-character XOR
func c4() (actual, expected Result) {
	expected = string([]byte{110, 79, 87, 0, 84, 72, 65, 84, 0, 84, 72, 69, 0, 80, 65, 82, 84, 89, 0, 73, 83, 0, 74, 85, 77, 80, 73, 78, 71, 42})

	input, err := ioutil.ReadFile("input/4.txt")
	if err != nil {
		panic(err)
	}

	lines := strings.Split(string(input), "\n")
	var bestScore = 0.0
	var plaintext string

	// Find the most popular byte in each line
	for i := 0; i < len(lines)-1; i++ {
		line, err := hex.DecodeString(lines[i])
		if err != nil {
			log.Println(err)
			continue
		}

		key, err := bytes.Popular(line, 1)
		if err != nil {
			log.Println(err)
			continue
		}

		decrypted, err := bytes.XorRepeatingKey(line, key)
		if err != nil {
			log.Println(err)
			continue
		}

		// Score each string for how likely it is English
		decryptedStr := string(decrypted)
		score := utils.EnglishScore(decryptedStr)
		if score > bestScore {
			bestScore = score
			plaintext = decryptedStr
		}
	}
	return plaintext, expected
}
예제 #5
0
/* Single-byte XOR cipher
* Given a string that has been XOR'd against a single character, find
* the key and decrypt the string.
 */
func c3() (actual, expected Result) {
	input := "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736"
	expected = string([]byte{99, 79, 79, 75, 73, 78, 71, 0, 109, 99, 7, 83, 0, 76, 73, 75, 69, 0, 65, 0, 80, 79, 85, 78, 68, 0, 79, 70, 0, 66, 65, 67, 79, 78})

	ciphertext, err := hex.DecodeString(input)
	if err != nil {
		panic(err)
	}

	// Assume the most popular byte in the ciphertext is the key
	key, err := bytes.Popular(ciphertext, 1)
	if err != nil {
		log.Fatal(err)
	}

	result, err := bytes.XorRepeatingKey(ciphertext, key)
	if err != nil {
		log.Fatal(err)
	}

	return string(result), expected
}