I'm stuck on a part of an assignment for one of my programming classes. I believe the solution is pretty straightforward, but for whatever reason I cannot grasp it.
The goal of the assignment is to modify the ciphertext so that the dollar amount is strictly increased. The classes encrypt and decrypt are given and cannot be edited, code is added to attack. Attack acts as a middleman and retrieves the output from encrypt before decrypt is called. Note that the key is retrieved from a reused file, ergo the same key is used for each encrypt and decrypt. Also we can assume we know the layout of the message.
My initial reaction was that because we know that the key is the same and because we have the plaintext, ciphertext, and IV in attack, there must be a simple solution to modifying the ciphertext. I've tried computing a new tag after modifying the ciphertext, but the ciphertext is dependent on previous input (IV) so that doesn't work. Am I right to assume there is a relatively simple solution?
Note: Not necessarily looking for a fully coded answer, just want some guidance in the approach to this problem. TA office hours was a mess with everything online :(
Thanks!
#### EXAMPLE KEY #####
2D7F8E92A8E7109258C879F878E12387
######################
class encrypt
import sys
import os
import Crypto.Cipher.AES
import hashlib
f = open(sys.argv[1], 'r')
key = f.readline()
key = bytes.fromhex(key[:32])
f.close()
message = \
"""AMOUNT: $ 10.00
Originating Acc Holder: Doe
Orgininating Acc #82123-098370
I authorized the above amount to be transferred to the account #38108-443280
held by a student at the National Bank of the Cayman Islands.
"""
iv = os.urandom(16)
cipher = Crypto.Cipher.AES.new(key, Crypto.Cipher.AES.MODE_CBC, IV=iv)
ciphertext = cipher.encrypt(message.encode()).hex()
tag = hashlib.sha256(message.encode()).hexdigest()
print(iv.hex() + ciphertext + tag)
class decrypt
import sys
import Crypto.Cipher.AES
import hashlib
f = open(sys.argv[1], 'r')
key = f.readline()
key = bytes.fromhex(key[:32])
f.close()
ciphertextWithTag = bytes.fromhex(sys.argv[2]) # bytes.fromhex($CT)
if len(ciphertextWithTag) < 16+16+32:
print("Ciphertext is too short!")
sys.exit(0)
iv = ciphertextWithTag[:16]
ciphertext = ciphertextWithTag[:len(ciphertextWithTag)-32] # with iv
tag = ciphertextWithTag[len(ciphertextWithTag)-32:]
cipher = Crypto.Cipher.AES.new(key, Crypto.Cipher.AES.MODE_CBC, IV=iv)
plaintext = cipher.decrypt(ciphertext[16:]) # here [16:] has spare apart iv
if tag.hex() != hashlib.sha256(plaintext).hexdigest():
print("Invalid tag!")
else:
print("Verified message")
print(plaintext.decode())
class attack
import sys
ciphertextWithTag = bytes.fromhex(sys.argv[1])
if len(ciphertextWithTag) < 16+16+32:
print("Ciphertext is too short!")
sys.exit(0)
iv = ciphertextWithTag[:16]
ciphertext = ciphertextWithTag[:len(ciphertextWithTag)-32]
tag = ciphertextWithTag[len(ciphertextWithTag)-32:]
# TODO: Modify the input so the transfer amount is more lucrative to the recipient
# TODO: Print the new encrypted message
# you can change the print content if necessary
print(ciphertext.hex() + tag.hex())
Look at the very first block decrypted using CBC mode
PlainText = Decrypt(CipherText, Key) ^ IV.
You know the PlainText you know the IV, and you have a new text FakeText that you want to create. It should be pretty clear how to change IV to a new IV' so that you end up with FakeText instead of a PlainText. You don't care what the results of the decryption are, just that it's some constant.
Beyond that, it's your homework.