コード例 #1
0
ファイル: crypto.go プロジェクト: taravancil/cryptopals
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
ファイル: cryptopals.go プロジェクト: taravancil/cryptopals
/* CBC padding oracle
* Write a CBC padding oracle that decrypts a ciphertext and detects
* if the plaintext is padded properly with PKCS#7. Choose a random line
* from 17.txt, encrypt it, then decrypt it using the oracle.
 */
func c17() (actual, expected Result) {
	input, _ := ioutil.ReadFile("input/17.txt")
	strs := strings.Split(string(input), "\n")
	str := strs[r.Intn(10)]
	decodedStr, _ := base64.StdEncoding.DecodeString(str)

	if crypto.GlobalAesKey == nil {
		crypto.GlobalAesKey = crypto.NewAesKey()
	}
	key := crypto.GlobalAesKey
	iv, _ := bytes.Random(aes.BlockSize)

	ciphertext, err := crypto.CbcEncrypt([]byte(decodedStr), key, iv)
	if err != nil {
		log.Fatal(err)
	}

	blocks, err := bytes.SplitIntoBlocks(ciphertext, aes.BlockSize)
	if err != nil {
		log.Fatal(err)
	}

	var plaintext []byte

	for n := 0; n < len(blocks); n++ {
		block := blocks[n]
		controlled := make([]byte, aes.BlockSize)
		plaintextBlock := make([]byte, aes.BlockSize)
		intermediate := make([]byte, aes.BlockSize)
		prevBlock := make([]byte, aes.BlockSize)

		if n == 0 {
			prevBlock = iv
		} else {
			prevBlock = blocks[n-1]
		}

		for i := aes.BlockSize - 1; i >= 0; i-- {
			paddingLen := aes.BlockSize - i
			paddingByte := byte(paddingLen)

			// Set the last paddingLen bytes of controlled to so that when decrypted,
			// each will be a valid padding byte.
			for j := 0; j < paddingLen; j++ {
				controlled[i+j] = paddingByte ^ intermediate[i+j]
			}

			for b := 0; b <= 256; b++ {
				controlled[i] = byte(b)
				controlled := append(controlled, block...)
				valid, _ := crypto.CbcPaddingOracle(controlled, iv)
				if valid {
					// The padding is valid and we control the ith byte of the
					// block XORed with the intermediate state. XOR is an inverse
					// operation so finding the ith byte of the intermediate state
					// is as simple as:
					intermediate[i] = paddingByte ^ controlled[i]
					break
				}
			}
			plaintextBlock[i] = prevBlock[i] ^ intermediate[i]
		}
		plaintext = append(plaintext, plaintextBlock...)
	}

	decrypted, _ := crypto.CbcDecrypt(ciphertext, key, iv)
	return string(plaintext), string(decrypted)
}