fork download
  1. # Question 1
  2. # An attacker intercepts the following ciphertext (hex encoded):
  3.  
  4. # 20814804c1767293b99f1d9cab3bc3e7 ac1e37bfb15599e5f40eef805488281d
  5.  
  6. # He knows that the plaintext is the ASCII encoding of the message "Pay Bob 100$" (excluding the quotes).
  7. # He also knows that the cipher used is CBC encryption with a random IV using AES as the underlying block cipher.
  8. # Show that the attacker can change the ciphertext so that it will decrypt to "Pay Bob 500$". What is the resulting ciphertext (hex encoded)?
  9. # This shows that CBC provides no integrity.
  10.  
  11. import sys
  12.  
  13. def main():
  14. # input
  15. cypherText = "20814804c1767293b99f1d9cab3bc3e7 ac1e37bfb15599e5f40eef805488281d".split(' ')
  16.  
  17. # set the CBC parts. The first part is the IV
  18. cypherTextIV = cypherText[0].decode('hex')
  19. cypherTextC0 = cypherText[1].decode('hex')
  20.  
  21. # define plaintexts
  22. plainText = "Pay Bob 100$"
  23. plainTextTarget = "Pay Bob 500$"
  24.  
  25. # define paddings
  26. paddingNum1 = str(len(cypherTextC0) - len(plainText))
  27. padding1 = "".join([paddingNum1] * int(paddingNum1))
  28.  
  29. paddingNum2 = str(len(cypherTextC0) - len(plainTextTarget))
  30. padding2 = "".join([paddingNum2] * int(paddingNum2))
  31.  
  32. # append to plaintext the paddings
  33. plainText += padding1
  34. plainTextTarget += padding2
  35.  
  36. # XOR the plaintext to determine the value to XOR with
  37. xorredPlainText = strxor(plainText, plainTextTarget)
  38.  
  39. # Since the decription of c[0] is XORed with IV to retrieve the plaintext xor the IV with the desired mutation
  40. newIV = strxor(xorredPlainText, cypherTextIV)
  41.  
  42. # new CBC
  43. print "New CBC\n",newIV.encode('hex'), cypherText[1]
  44.  
  45. # Output:
  46. # New CBC
  47. # 20814804c1767293bd9f1d9cab3bc3e7 ac1e37bfb15599e5f40eef805488281d
  48.  
  49.  
  50. # xor two strings of different lengths
  51. def strxor(a, b):
  52. if len(a) > len(b):
  53. return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a[:len(b)], b)])
  54. else:
  55. return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b[:len(a)])])
  56.  
  57.  
  58. main()
Success #stdin #stdout 0.04s 63912KB
stdin
Standard input is empty
stdout
New CBC
20814804c1767293bd9f1d9cab3bc3e7 ac1e37bfb15599e5f40eef805488281d