def edit(ciphertext, key, offset, newtext): fixed_nounce = b"\x00\x00\x00\x00\x00\x00\x00\x00" nounce = bytearray(reversed(fixed_nounce)) counter = bytearray("".join(["\x00"] * 8).encode()) output = bytearray() nbBlock, remaining = int((offset % 16) / 16), offset % 16 for i in range(nbBlock): stream_key = nounce + counter increment_counter(counter) if remaining != 0 or nbBlock == 0: stream_key = nounce + counter increment_counter(counter) encrypted_stream_key = aes_encrypt_block(key, stream_key)[remaining:] print(len(encrypted_stream_key)) # 16 while len(newtext) > len(encrypted_stream_key): stream_key = nounce + counter increment_counter(counter) encrypted_stream_key.extend(aes_encrypt_block(key, stream_key)) # Read part # with "to_read" the number of bytes to read #original_plaintext = fixed_xor(encrypted_stream_key[:len(to_read)], ciphertext[offset:]) #return original_plaintext ciphertext = bytearray(ciphertext) ciphertext[offset:offset + len(newtext)] = fixed_xor( encrypted_stream_key, newtext) return ciphertext
def aes_encrypt_cbc(key, hex_data, iv): output = bytearray() if len(hex_data) % 16 != 0: len_pad = 16 - len(hex_data) % 16 hex_data = pkcs7padding(hex_data, len(hex_data) + len_pad) chunks = groupByBlocks(hex_data, 16) decrypted_chunk = iv for chunk in chunks: xored = fixed_xor(chunk, decrypted_chunk) decrypted_chunk = aes_encrypt_block(key, xored) output.extend(decrypted_chunk) return bytes(output)
def keyExpansion(key): expandedKey = [] expandedKey.extend(key) rconIteration = 1 while len(expandedKey) < 176: # 16bits key + 10 16bits round keys key_chunk = expandedKey[-4:] if len(expandedKey)%16==0: key_chunk = keyExpansion_core(key_chunk, rconIteration) rconIteration = rconIteration + 1 xored = fixed_xor(key_chunk, bytearray(expandedKey[-16:][:4])) expandedKey.extend(xored) return expandedKey
def aes_decrypt_cbc(key, hex_data, iv): output = bytearray() if len(hex_data) % 16 != 0: len_pad = 16 - len(hex_data) % 16 hex_data = pkcs7padding(hex_data, len(hex_data) + len_pad) chunks = groupByBlocks(hex_data, 16) last_chunk = iv for chunk in chunks: decrypted_chunk = aes_decrypt_block(key, chunk) xored = fixed_xor(decrypted_chunk, last_chunk) last_chunk = chunk output.extend(xored) return output
def mt_encrypt(seed, msg): msg = groupByBlocks(msg, 8) new_msg = bytearray() mt = [0] * 624 index = 0 index, mt = MT_initialize(seed, index, mt) for x, block in enumerate(msg): block = bytearray(block) index, mt, output = MT_extractu32(index, mt) index, mt, output2 = MT_extractu32(index, mt) output = bytearray.fromhex(hex(output)[2:].zfill(8)) output2 = bytearray.fromhex(hex(output2)[2:].zfill(8)) keystream = output + output2 new_msg.extend(fixed_xor(block, keystream)) return new_msg
def aes_encrypt_ctr(key, msg, nounce): assert len(key) == 16 assert len(nounce) == 8 # little endian stuff nounce = bytearray(reversed(nounce)) counter = bytearray("".join(["\x00"] * 8).encode()) output = bytearray() for block in groupByBlocks(msg, 16): stream_key = nounce + counter encrypted_stream_key = aes_encrypt_block(key, stream_key) output.extend(fixed_xor(encrypted_stream_key, block)) increment_counter(counter) return bytes(output)
from set3.challenge18 import aes_encrypt_ctr from set3.challenge18 import aes_decrypt_ctr from set2.challenge12 import randKey from set1.challenge3 import decryptSingleByteXor from set1.challenge2 import fixed_xor if __name__ == "__main__": const_key = randKey() fixed_nounce = b"\x00\x00\x00\x00\x00\x00\x00\x00" with open("set3/19.txt") as f: b64_data_set = f.read() lines = [base64.b64decode(x) for x in b64_data_set.split("\n")[:-1]] encrypted_lines = [] for line in lines: encrypted_lines.append(aes_encrypt_ctr(const_key, line, fixed_nounce)) max_len = max([len(x) for x in encrypted_lines]) keystream = bytearray() for i in range(max_len): ith_block = bytearray([x[i] for x in encrypted_lines if len(x) > i]) score, key, decrypted = decryptSingleByteXor(ith_block) keystream.append(key[0]) sorted(lines, key=len) for line, encrypted_line in zip(sorted(lines, key=len), sorted(encrypted_lines, key=len)): print("expected", line.decode()) print("found ", fixed_xor(encrypted_line, keystream).decode()) print("\n")
safeString = bytearray() for c in string: if c in unreserved_set: safeString.append(c) else: hexString = hex(c)[2:].zfill(2) encoded = bytearray(b"%"+hexString.encode()) safeString.extend(encoded) return safeString def encryption_oracle(unsafeString): to_prepend = b"comment1=cooking%20MCs;userdata=" to_append = b";comment2=%20like%20a%20pound%20of%20bacon" string = percent_encode(unsafeString) string = to_prepend + string + to_append string = pkcs7pad(string) encrypted = aes_encrypt_cbc(const_key, string, iv) return encrypted def isAdmin(encrypted): string = aes_decrypt_cbc(const_key, encrypted, iv) string = unpad_validation(string) return (b";admin=true;" in string) if __name__ == "__main__": plaintext_toscramble = b"yellow_submarineyellow_submarineyellow_submarine" encrypted = bytearray(encryption_oracle(plaintext_toscramble)) a = fixed_xor(b"yellow_submarine", b"nawao;admin=true") encrypted[16*3:16*4] = fixed_xor(encrypted[16*3:16*4], a) print(isAdmin(encrypted))
def singleByteXor(msg, key): key_repeated = bytearray([key] * len(msg)) message_candidate = fixed_xor(key_repeated, msg) return bytearray(message_candidate)
print(len(encrypted_stream_key)) # 16 while len(newtext) > len(encrypted_stream_key): stream_key = nounce + counter increment_counter(counter) encrypted_stream_key.extend(aes_encrypt_block(key, stream_key)) # Read part # with "to_read" the number of bytes to read #original_plaintext = fixed_xor(encrypted_stream_key[:len(to_read)], ciphertext[offset:]) #return original_plaintext ciphertext = bytearray(ciphertext) ciphertext[offset:offset + len(newtext)] = fixed_xor( encrypted_stream_key, newtext) return ciphertext if __name__ == "__main__": with open("set4/25.txt") as f: b64_data = f.read() msg = base64.b64decode(b64_data) key = b"YELLOW SUBMARINE" decrypted = aes_decrypt_ecb(key, msg) const_key = randKey() fixed_nounce = b"\x00\x00\x00\x00\x00\x00\x00\x00" encrypted = aes_encrypt_ctr(const_key, decrypted, fixed_nounce) len(encrypted) attacker_encrypted = edit(encrypted, const_key, 0, b"\x00" * len(encrypted)) guessed_stream_key = attacker_encrypted decrypted = fixed_xor(encrypted, guessed_stream_key) print(decrypted.decode())
def repeatedKeyXor(msg_hexString, key_hexString): repeatedKey = repeatKey(key_hexString, len(msg_hexString)) return fixed_xor(msg_hexString, repeatedKey)
if __name__ == "__main__": plaintext_toscramble = b"yy8888888888888888888888888" encrypted = bytearray(encryption_oracle(plaintext_toscramble)) string = aes_decrypt_cbc(const_key, encrypted, iv) # string = unpad_validation(string) # encrypted[16*1:16*2] = bytearray(b"\x00")*16 encrypted[16*2:16*3] = encrypted[16*0:16*1] isAdmin(encrypted) # print Error gotFromError = bytearray(b'comment1=cookingj\r:\x81\xfd\xe4\xdf\xb2\x8f\x93w\xba\x95\\b\x83\xd1\xc9J\xc9I\xbc_ka\xb3e\xfb\xdc\x0ea[\xa3\xfd\x1fgTeQ\xbe\x02\xa7wF"*\xe1\xa9ent2=pound') supposedly_key = fixed_xor(gotFromError[0:16], gotFromError[32:48]) print(supposedly_key == iv) print(supposedly_key == const_key) # Proof p1^p3 = key ? # # From CBC we know that # A(p1^iv)=C1 # A(p3^C2)=C3 # A(C1)^iv = p1 # p3 = A(C3)^C2 # # Then we deduce # p1^p3 = A(C3)^C2^A(C1)^iv #
def addRoundKey(state, roundKey): return fixed_xor(state, roundKey)
def test_fixed_xor(self): self.assertEqual( challenge2.fixed_xor(self.hex1, self.hex2), '746865206b696420646f6e277420706c6179' )