Challenge 16: CBC bitflipping attacks
Problem
CBC bitflipping attacksGenerate a random AES key.
Combine your padding code and CBC code to write two functions.
The first function should take an arbitrary input string, prepend the string:
"comment1=cooking%20MCs;userdata=".. and append the string:
";comment2=%20like%20a%20pound%20of%20bacon"The function should quote out the ";" and "=" characters.
The function should then pad out the input to the 16-byte AES block length and encrypt it under the random AES key.
The second function should decrypt the string and look for the characters ";admin=true;" (or, equivalently, decrypt, split the string on ";", convert each resulting string into 2-tuples, and look for the "admin" tuple).
Return true or false based on whether the string exists.
If you've written the first function properly, it should not be possible to provide user input to it that will generate the string the second function is looking for. We'll have to break the crypto to do that.
Instead, modify the ciphertext (without knowledge of the AES key) to accomplish this.
You're relying on the fact that in CBC mode, a 1-bit error in a ciphertext block:
Completely scrambles the block the error occurs inProduces the identical 1-bit error(/edit) in the next ciphertext block.
Code
package challenge16
import ( "crypto/aes" c10 "cryptopals/Set2/challenge10" c11 "cryptopals/Set2/challenge11" c9 "cryptopals/Set2/challenge9" "fmt" "log" "strings")
var key []byte
const prefix = "comment1=cooking%20MCs;userdata="const suffix = ";comment2=%20like%20a%20pound%20of%20bacon"
func init() { key = c11.RandBytes(16)}
func Challenge16() { cipher, iv := EncryptOracle([]byte("test0000000000003admin=true"))
forge := byte(';') ^ byte('3') cipher[32] ^= forge
isAdmin := DecryptOracle(cipher, iv) fmt.Printf("isAdmin = %+v\n", isAdmin)}
func EncryptOracle(input []byte) ([]byte, []byte) {
src := append([]byte(prefix), input...) src = append(src, []byte(suffix)...)
keySize := len(key) block, err := aes.NewCipher([]byte(key)) if err != nil { log.Fatal(err) } src = c9.PKCS(src, keySize) dst := make([]byte, len(src)) iv := c11.RandBytes(16) c10.Encrypt_CBC(block, iv, dst, src) return dst, iv}
const adminCheck = ";admin=true;"
func DecryptOracle(cipher, iv []byte) bool {
block, err := aes.NewCipher([]byte(key)) if err != nil { log.Fatal(err) }
dst := make([]byte, len(cipher)) c10.Decrypt_CBC(block, iv, dst, cipher)
pt, err := c9.UnpadPKCS(dst) if err != nil { log.Fatal(err) } return strings.Contains(string(pt), adminCheck)}