コード例 #1
0
ファイル: aes.go プロジェクト: taravancil/cryptopals
// AesOracle prepends and appends 5-10 random bytes to a plaintext,
// encrypts the plaintext under a predetermined BlockMode, then
// returns the detected BlockMode
func AesOracle(plaintext []byte, encrypter cipher.BlockMode) string {
	// Generate random bytes to prepend/append to plaintext
	prependBytes, _ := bytes.Random(r.Intn(5) + 5)
	appendBytes, _ := bytes.Random(r.Intn(5) + 5)

	plaintext = append(prependBytes, plaintext...)
	plaintext = append(plaintext, appendBytes...)
	plaintext, _ = blocks.Pkcs7(plaintext, aes.BlockSize)

	ciphertext := make([]byte, len(plaintext))
	modifiedCiphertext := make([]byte, len(plaintext))

	// Modify the first block of the plaintext
	modified := plaintext
	modified[0] = byte(255)
	encrypter.CryptBlocks(ciphertext, plaintext)
	encrypter.CryptBlocks(modifiedCiphertext, modified)

	// If the second block in the modified ciphertext is affected by a
	// change in the first block of the plaintext, return CBC mode
	if ciphertext[16] != modifiedCiphertext[16] {
		return "CBC"
	}
	return "ECB"
}
コード例 #2
0
ファイル: aes.go プロジェクト: taravancil/cryptopals
func AppendSecretEncryptEcb(plaintext, key []byte, prefix bool) []byte {
	if prefix == true {
		if len(prefixBytes) == 0 {
			prefixBytes, _ = bytes.Random(r.Intn(99) + 1)
		}
		plaintext = append(prefixBytes, plaintext...)
	}

	secret, _ := base64.StdEncoding.DecodeString("Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK")

	plaintext = append(plaintext, secret...)
	ciphertext, _ := EcbEncrypt(plaintext, key)
	return ciphertext
}
コード例 #3
0
ファイル: aes.go プロジェクト: taravancil/cryptopals
func RandomAesMode() (cipher.BlockMode, string, error) {
	block, err := aes.NewCipher(NewAesKey())
	if err != nil {
		return nil, "", err
	}
	mode := r.Intn(2)
	if mode == 1 {
		iv, _ := bytes.Random(aes.BlockSize)
		encrypter := cipher.NewCBCEncrypter(block, iv)
		return encrypter, "CBC", nil
	}
	encrypter := NewECBEncrypter(block)
	return encrypter, "ECB", nil
}
コード例 #4
0
ファイル: cryptopals.go プロジェクト: taravancil/cryptopals
/* CBC bitflipping attack
* Create a function, that given an input, prepends:
* "comment1=cooking%20MCs;userdata="
* and appends:
* ";comment2=%20like%20a%20pound%20of%20bacon"
* , quotes out the ; and =, and pads and encrypts it under AES CBC.
* Another function should decrypt the string and return true if
* ";admin=true;" exists in the string. Modify the ciphertext to
* make the second funcion return true.
 */
func c16() (actual, expected Result) {
	key := crypto.NewAesKey()

	input := "XadminXtrue"
	inputBytes := []byte(input)
	str := profile.ProcessComment(input)

	iv, _ := bytes.Random(aes.BlockSize)
	encrypted, err := crypto.CbcEncrypt([]byte(str), key, iv)
	if err != nil {
		panic(err)
	}

	// Flip the targeted bytes ("X"s in the input string)
	encrypted[16] = encrypted[16] ^ 59 ^ inputBytes[0]
	encrypted[22] = encrypted[22] ^ 61 ^ inputBytes[6]

	hasAdmin := profile.HasAdmin(encrypted, key, iv)
	return hasAdmin, true
}
コード例 #5
0
ファイル: cryptopals.go プロジェクト: taravancil/cryptopals
/* ECB cut and paste
* Make a profile_for function that takes an email address and returns
* a user object encoded cookie-style ([email protected]&uid=10).
* Encrypt the encoded profile with AES ECB, and *supply* this to the
* "attacker". Find a way to create a valid admin profile.
 */
func c13() (actual, expected Result) {
	expected = "email=XXXXXXXXXXXXXX&uid=1&role=admin"
	key, _ := bytes.Random(aes.BlockSize)

	// A 14 byte-long email address will put role= at the end of the second block
	attackEmail := string(stdBytes.Repeat([]byte("X"), 14))
	// admin padded w/ 10 bytes will put admin at the beginning of the second block
	attackEmail2 := string(stdBytes.Repeat([]byte("X"), 10)) + "admin"

	profile1 := profile.New(attackEmail)
	profile2 := profile.New(attackEmail2)

	encrypted1, err := profile.Encrypt([]byte(profile1), key)
	if err != nil {
		log.Println(err)
	}
	encrypted2, err := profile.Encrypt([]byte(profile2), key)
	if err != nil {
		log.Println(err)
	}

	// Use first two blocks of encrypted1 and thirdBlock of encrypted2 to
	// create the attack ciphertext
	adminProfile := encrypted1[0:32]
	thirdBlock := encrypted2[16:32]
	adminProfile = append(adminProfile, thirdBlock...)

	decrypted, err := profile.Decrypt(adminProfile, key)
	if err != nil {
		log.Fatal(err)
	}

	// Parse the modified ciphertext and encode the admin profile
	parsed := profile.Parse(string(decrypted))
	encoded := profile.Encode(parsed)

	return encoded, expected
}
コード例 #6
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)
}
コード例 #7
0
ファイル: aes.go プロジェクト: taravancil/cryptopals
// NewAesKey generates a random AES key
func NewAesKey() []byte {
	key, _ := bytes.Random(aes.BlockSize)
	return key
}