def test_parity(): key = key_1024 print("\nTest: parity") plaintext1 = bytes(b"Some plaintext ") + random_bytes(10) + bytes( b" anything can it be") plaintext2 = bytes(b"Some plaintext ") + random_bytes(10) + bytes( b" anything can it be2") ciphertext1 = h2b( subprocess.check_output([ "python", rsa_oracles_path, "encrypt", key.identifier, b2h(plaintext1) ]).strip().decode()) ciphertext2 = h2b( subprocess.check_output([ "python", rsa_oracles_path, "encrypt", key.identifier, b2h(plaintext2) ]).strip().decode()) key.texts.append({'cipher': b2i(ciphertext1)}) key.texts.append({'cipher': b2i(ciphertext2)}) msgs_recovered = parity(parity_oracle, key.publickey()) assert msgs_recovered[0] == b2i(plaintext1) assert msgs_recovered[1] == b2i(plaintext2) key.clear_texts()
def test_blinding(): global key_to_oracle key = key_2048 key_to_oracle = key print("\nTest: blinding(key, signing_oracle=signing_oracle)") for _ in range(10): msg_to_sign = b2i( random_bytes(randint(10, (key.size / 8) - 1)).replace( bytes(b'\n'), bytes(b''))) key.add_plaintext(msg_to_sign) signature = blinding(key, signing_oracle=signing_oracle) assert len(signature) == 1 is_correct = subprocess.check_output([ "python", rsa_oracles_path, "verify", key_to_oracle.identifier, i2h(msg_to_sign), i2h(signature[0]) ]).strip().decode() assert is_correct == 'True' key.clear_texts() print("\nTest: blinding(key, decryption_oracle=decryption_oracle)") for _ in range(10): plaintext = b2i( random_bytes(randint(10, (key.size / 8) - 1)).replace( bytes(b'\n'), bytes(b''))) ciphertext = key.encrypt(plaintext) key.add_ciphertext(ciphertext) plaintext_recovered = blinding(key, decryption_oracle=decryption_oracle) assert len(plaintext_recovered) == 1 assert plaintext_recovered[0] == plaintext key.clear_texts() key_to_oracle = None
def find_prefix_suffix_size(encryption_oracle, block_size=16): """Determine prefix and suffix sizes if ecb mode, sizes must be constant Rarely may fail (if random data that are send unhappily matches prefix/suffix) Args: encryption_oracle(callable) block_size(int) Returns: tuple(int,int): prefix_size, suffix_size """ blocks_to_send = 5 payload = random_bytes(1) * (blocks_to_send * block_size) enc_chunks = chunks(encryption_oracle(payload), block_size) log.debug("Encryption of length {}".format(blocks_to_send * block_size)) log.debug(print_chunks(enc_chunks)) for position_start in range(len(enc_chunks) - 1): if enc_chunks[position_start] == enc_chunks[position_start + 1]: for y in range(2, blocks_to_send - 1): if enc_chunks[position_start] != enc_chunks[position_start + y]: break else: log.success("Controlled payload start at chunk {}".format(position_start)) break else: log.critical_error("Position of controlled chunks not found") log.info('Finding prefix') changed_char = bytes([(payload[0] - 1)%256]) for aligned_bytes in range(block_size): payload_new = payload[:aligned_bytes] + changed_char + payload[aligned_bytes+1:] enc_chunks_new = chunks(encryption_oracle(payload_new), block_size) log.debug(print_chunks(chunks(payload_new, block_size))) log.debug(print_chunks(enc_chunks_new)) if enc_chunks_new[position_start] != enc_chunks[position_start]: prefix_size = position_start*block_size - aligned_bytes log.success("Prefix size: {}".format(prefix_size)) break else: log.critical_error("Size of prefix not found") log.info('Finding suffix') payload = random_bytes(1) * (block_size - (prefix_size % block_size)) # align to block_size encrypted = encryption_oracle(payload) suffix_size = len(encrypted) - len(payload) - prefix_size while True: payload += random_bytes(1) suffix_size -= 1 if len(encryption_oracle(payload)) > len(encrypted): log.success("Suffix size: {}".format(suffix_size)) break else: log.critical_error("Size of suffix not found") return prefix_size, suffix_size
def test_fake_ciphertext_decryption_oracle(amount=5): for _ in range(amount): new_plaintext = random_bytes(randint(1, 10)) new_plaintext_padded = add_padding(new_plaintext, block_size) print("Test small: cbc.fake_ciphertext(new_plaintext_padded, decryption_oracle=decryption_oracle)") new_ciphertext = cbc.fake_ciphertext(new_plaintext_padded, decryption_oracle=decryption_oracle) decrypted = h2b(subprocess.check_output( ['python', cbc_oracles_path, 'decrypt', b2h(new_ciphertext)]).strip().decode()) assert decrypted == new_plaintext for _ in range(amount): new_plaintext = random_bytes(randint(10, 50)) new_plaintext_padded = add_padding(new_plaintext, block_size) print("Test large: cbc.fake_ciphertext(new_plaintext_padded, decryption_oracle=decryption_oracle)") new_ciphertext = cbc.fake_ciphertext(new_plaintext_padded, decryption_oracle=decryption_oracle, padding_oracle=padding_oracle) decrypted = h2b(subprocess.check_output( ['python', cbc_oracles_path, 'decrypt', b2h(new_ciphertext)]).strip().decode()) assert decrypted == new_plaintext
def test_small_e_msg(): key = key_1024_small_e print("\nTest: small_e_msg") for _ in range(10): plaintext = b2i(random_bytes(10)) ciphertext = key.encrypt(plaintext) key.add_ciphertext(ciphertext) recovered_plaintext = small_e_msg(key) assert len(recovered_plaintext) == 1 assert recovered_plaintext[0] == plaintext key.clear_texts() for _ in range(10): plaintext = b2i(random_bytes(42)) ciphertext = key.encrypt(plaintext) key.add_ciphertext(ciphertext) recovered_plaintext = small_e_msg(key) assert len(recovered_plaintext) == 1 assert recovered_plaintext[0] == plaintext key.clear_texts()
def test_length_extension(): print("Test length extension sha1") for x in range(30): secret = random_bytes(random.randint(0, 130)) new_message = random_bytes(random.randint(0, 130)) old_hash = sha1(secret) new_hash, new_data = length_extension(old_hash, len(secret), new_message, type='sha1') assert sha1(secret + new_data) == new_hash print("Test length extension md4") for x in range(30): secret = random_bytes(random.randint(0, 130)) new_message = random_bytes(random.randint(0, 130)) old_hash = md4(secret) new_hash, new_data = length_extension(old_hash, len(secret), new_message, type='md4') assert md4(secret + new_data) == new_hash
def test_RSAKey(): print("\nTest: RSAKey") key = RSAKey.generate(2048) key2 = RSAKey(key.n, key.e) assert key2.n == key.n key2 = RSAKey(key.n, key.e, d=key.d) assert key2.p == key.p or key2.q == key.p key2 = RSAKey(key.n, key.e, p=key.q) assert key2.d == key.d for _ in range(10): tmp = random_bytes(randint(1, key.size // 8 - 10)) assert key.decrypt(key.encrypt(tmp)) == b2i(tmp)
def test_decrypt(): global constant, prefix_len, suffix_len, secret print( "test: ecb.decrypt(encryption_oracle_aes, constant, block_size=AES.block_size)" ) constant = True for x in range(20): prefix_len = random.randint(0, 90) secret = random_bytes(random.randint(1, 90)) print("Secret to guess(hex): {}".format(b2h(secret))) guessed_secret = ecb.decrypt(encryption_oracle_aes, constant, block_size=AES.block_size) assert secret == guessed_secret guessed_secret = ecb.decrypt(encryption_oracle_des, constant, block_size=DES3.block_size) assert secret == guessed_secret
def test_iv_as_key(from_test=1): global iv_as_key iv_as_key = True plaintext = random_bytes(randint(1, 40)) plaintext_padded = add_padding(plaintext, block_size) ciphertext = encrypt(plaintext, iv_as_key=iv_as_key) if from_test <= 1: print("Test 1: cbc.iv_as_key()") key = cbc.iv_as_key(ciphertext[AES.block_size:], plaintext_padded, padding_oracle=padding_oracle) assert key == KEY if from_test <= 2: print("Test 2: cbc.iv_as_key()") key = cbc.iv_as_key(ciphertext[AES.block_size:], plaintext_padded, decryption_oracle=decryption_oracle) assert key == KEY iv_as_key = False
def find_block_size(encryption_oracle, constant=True): """Determine block size if ecb mode Args: encryption_oracle(callable) constant(bool): True if prefix and suffix have constant length Returns: int """ if constant: log.debug("constant == True") payload = bytes(b'A') size = len(encryption_oracle(payload)) while True: payload += bytes(b'A') new_size = len(encryption_oracle(payload)) if new_size > size: log.info("block_size={}".format(new_size - size)) return new_size - size else: log.debug("constant == False") payload = bytes(b'A') max_size = len(encryption_oracle(payload)) possible_sizes = factors(max_size) possible_sizes.add(max_size) blocks_to_send = 5 for block_size in sorted(possible_sizes): """send payload of length x, so at least x-1 blocks should be identical""" payload = random_bytes(1) * (blocks_to_send*block_size) enc_chunks = chunks(encryption_oracle(payload), block_size) for x in range(len(enc_chunks)-1): if enc_chunks[x] == enc_chunks[x+1]: log.debug("Found two identical blocks at {}: {}".format(x, print_chunks(enc_chunks))) for y in range(2, blocks_to_send-1): if enc_chunks[x] != enc_chunks[x+y]: break else: log.info("block_size={}".format(block_size)) return block_size
def encryption_oracle_des(payload): global constant, prefix_len, suffix_len, secret if secret: if constant: payload = random_bytes(prefix_len) + payload + secret else: payload = random_bytes(random.randint(1, 50)) + payload + secret else: if constant: payload = random_bytes(prefix_len) + payload + random_bytes( suffix_len) else: payload = random_bytes(random.randint( 1, 50)) + payload + random_bytes(random.randint(1, 50)) payload = add_padding(payload, DES3.block_size) cipher = DES3.new(key_DES3, DES3.MODE_ECB) return cipher.encrypt(payload)
def decrypt(encryption_oracle, constant=True, block_size=16, prefix_size=None, secret_size=None, alphabet=None): """Given encryption oracle which produce ecb(prefix || our_input || secret), find secret Args: encryption_oracle(callable) constant(bool): True if prefix have constant length (secret must have constant length) block_size(int/None) prefix_size(int/None) secret_size(int/None) alphabet(string): plaintext space Returns: secret(string) """ log.debug("Start decrypt function") if not alphabet: alphabet = bytes(string.printable.encode()) if not block_size: block_size = find_block_size(encryption_oracle, constant) if constant: log.debug("constant == True") if not prefix_size or not secret_size: prefix_size, secret_size = find_prefix_suffix_size(encryption_oracle, block_size) """Start decrypt""" secret = bytes(b'') aligned_bytes = random_bytes(1) * (block_size - (prefix_size % block_size)) if len(aligned_bytes) == block_size: aligned_bytes = bytes(b'') aligned_bytes_suffix = random_bytes(1) * (block_size - (secret_size % block_size)) if len(aligned_bytes_suffix) == block_size: aligned_bytes_suffix = bytes(b'') block_to_find_position = -1 controlled_block_position = (prefix_size+len(aligned_bytes)) // block_size while len(secret) < secret_size: if (len(secret)+1) % block_size == 0: block_to_find_position -= 1 payload = aligned_bytes + aligned_bytes_suffix + random_bytes(1) + secret enc_chunks = chunks(encryption_oracle(payload), block_size) block_to_find = enc_chunks[block_to_find_position] log.debug("To guess at position {}:".format(block_to_find_position)) log.debug("Plain: " + print_chunks(chunks(bytes(b'P'*prefix_size) + payload + bytes(b'S'*secret_size), block_size))) log.debug("Encry: " + print_chunks(enc_chunks)+"\n") for guessed_char in range(256): guessed_char = bytes([guessed_char]) payload = aligned_bytes + add_padding(guessed_char + secret, block_size) enc_chunks = chunks(encryption_oracle(payload), block_size) log.debug("Plain: " + print_chunks(chunks(bytes(b'P'*prefix_size) + payload + bytes(b'S'*secret_size), block_size))) log.debug("Encry: " + print_chunks(enc_chunks)+"\n") if block_to_find == enc_chunks[controlled_block_position]: secret = guessed_char + secret log.debug("Found char, secret={}".format(repr(secret))) break else: log.critical_error("Char not found, try change alphabet. Secret so far: {}".format(repr(secret))) log.success("Secret(hex): {}".format(b2h(secret))) return secret else: log.debug("constant == False")
def bleichenbacher_signature_forgery(key, garbage='suffix', hash_function='sha1'): """Bleichenbacher's signature forgery based on bug in verify implementation Args: key(RSAKey): with small e and at least one plaintext garbage(string): middle: 00 01 ff garbage 00 ASN.1 HASH suffix: 00 01 ff 00 ASN.1 HASH garbage hash_function(string) Returns: dict: forged signatures, signatures[no] == signature(key.texts[no]['plain']) update key texts """ hash_asn1 = { 'md5': bytes( b'\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10' ), 'sha1': bytes(b'\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14'), 'sha256': bytes( b'\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20' ), 'sha384': bytes( b'\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30' ), 'sha512': bytes( b'\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40' ) } if garbage not in ['suffix', 'middle']: log.critical_error("Bad garbage position, must be suffix or middle") if hash_function not in list(hash_asn1.keys()): log.critical_error( "Hash function {} not implemented".format(hash_function)) if key.e > 3: log.debug("May not work, because e > 3") signatures = {} if garbage == 'suffix': for text_no in range(len(key.texts)): if 'plain' in key.texts[text_no] and 'cipher' not in key.texts[ text_no]: log.info("Forge for plaintext no {} ({})".format( text_no, key.texts[text_no]['plain'])) hash_callable = getattr(hashlib, hash_function)(i2b( key.texts[text_no] ['plain'])).digest() # hack to call hashlib.hash_function plaintext_prefix = bytes(b'\x00\x01\xff\x00') + hash_asn1[ hash_function] + hash_callable plaintext = plaintext_prefix + bytes( b'\x00' * (key.size // 8 - len(plaintext_prefix))) plaintext = b2i(plaintext) for round_error in range(-5, 5): signature, _ = gmpy2.iroot(plaintext, key.e) signature = int(signature + round_error) test_prefix = i2b(gmpy2.powmod(signature, key.e, key.n), size=key.size)[:len(plaintext_prefix)] if test_prefix == plaintext_prefix: log.info("Got signature: {}".format(signature)) log.debug("signature**e % n == {}".format( i2h(gmpy2.powmod(signature, key.e, key.n), size=key.size))) key.texts[text_no]['cipher'] = signature signatures[text_no] = signature break else: log.error( "Something wrong, can't compute correct signature") return signatures elif garbage == 'middle': for text_no in range(len(key.texts)): if 'plain' in key.texts[text_no] and 'cipher' not in key.texts[ text_no]: log.info("Forge for plaintext no {} ({})".format( text_no, key.texts[text_no]['plain'])) hash_callable = getattr(hashlib, hash_function)(i2b( key.texts[text_no] ['plain'])).digest() # hack to call hashlib.hash_function plaintext_suffix = bytes( b'\x00') + hash_asn1[hash_function] + hash_callable if b2i(plaintext_suffix) & 1 != 1: log.error( "Plaintext suffix is even, can't compute signature") continue # compute suffix signature_suffix = 0b1 for b in range(len(plaintext_suffix) * 8): if (signature_suffix** 3) & (1 << b) != b2i(plaintext_suffix) & (1 << b): signature_suffix |= 1 << b signature_suffix = i2b( signature_suffix)[-len(plaintext_suffix):] # compute prefix while True: plaintext_prefix = bytes(b'\x00\x01\xff') + random_bytes( key.size // 8 - 3) signature_prefix, _ = gmpy2.iroot(b2i(plaintext_prefix), key.e) signature_prefix = i2b( int(signature_prefix), size=key.size)[:-len(signature_suffix)] signature = b2i(signature_prefix + signature_suffix) test_plaintext = i2b(gmpy2.powmod(signature, key.e, key.n), size=key.size) if bytes(b'\x00' ) not in test_plaintext[2:-len(plaintext_suffix)]: if test_plaintext[:3] == plaintext_prefix[:3] and test_plaintext[ -len(plaintext_suffix):] == plaintext_suffix: log.info("Got signature: {}".format(signature)) key.texts[text_no]['cipher'] = signature signatures[text_no] = signature break else: log.error("Something wrong, signature={}," " signature**{}%{} is {}".format( signature, key.e, key.n, [(test_plaintext)])) break return signatures
def test_sha1(): print("Test: sha1") for x in range(30): tmp = random_bytes(random.randint(0, 256)) assert sha1(tmp) == hashlib.sha1(tmp).digest()
def encrypt(data, iv_as_key=False): iv = random_bytes(block_size) if iv_as_key: iv = KEY aes = AES.new(KEY, AES.MODE_CBC, iv) return iv + bytes(aes.encrypt(add_padding(data)))
from __future__ import absolute_import, division, print_function import random from builtins import range from Crypto.Cipher import AES, DES3 from CryptoAttacks.Block import ecb from CryptoAttacks.Utils import add_padding, b2h, log, random_bytes block_size = AES.block_size prefix_len = 13 suffix_len = 19 constant = True key_AES = random_bytes(AES.key_size[-1]) key_DES3 = random_bytes(DES3.key_size[-1]) secret = None def encryption_oracle_aes(payload): global constant, prefix_len, suffix_len, secret if secret: if constant: payload = random_bytes(prefix_len) + payload + secret else: payload = random_bytes(random.randint(1, 50)) + payload + secret else: if constant: payload = random_bytes(prefix_len) + payload + random_bytes( suffix_len)
def test_decrypt(from_test=1): original_plaintext = random_bytes(randint(1, 40)) original_ciphertext = encrypt(original_plaintext) original_plaintext = add_padding(original_plaintext, block_size) if from_test <= 1: print("Test 1: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True)") decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True) assert decrypted == original_plaintext if from_test <= 2: data = original_ciphertext[:-block_size - 1] + bytes(b'A') + original_ciphertext[-block_size:] print("Test 2: cbc.decrypt(data, padding_oracle=padding_oracle, is_correct=False)") decrypted = cbc.decrypt(data, padding_oracle=padding_oracle, is_correct=False) assert decrypted[-block_size:-1] == original_plaintext[-block_size:-1] if from_test <= 3: print("Test 3: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=False)") decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=False) assert decrypted[:-1] == original_plaintext[:-1] if from_test <= 4: iv = original_ciphertext[:block_size] data = original_ciphertext[block_size:] print("Test 4: cbc.decrypt(data, padding_oracle=padding_oracle, iv=iv)") decrypted = cbc.decrypt(data, padding_oracle=padding_oracle, iv=iv) assert decrypted == original_plaintext if from_test <= 5: if len(original_plaintext) > block_size: print("Test 5: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, amount=2)") decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, amount=2) assert decrypted == original_plaintext[-block_size * 2:] if from_test <= 6: print("Test 6: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, amount=1, is_correct=True)") decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, amount=1, is_correct=True) assert decrypted == original_plaintext[-block_size:] if from_test <= 7: print("Test 7: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True, \n \ known_plaintext=original_plaintext)") decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True, known_plaintext=original_plaintext) assert decrypted == original_plaintext if from_test <= 8: print("Test 8: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True, \n \ known_plaintext=original_plaintext[-4:])") decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True, known_plaintext=original_plaintext[-4:]) assert decrypted == original_plaintext if from_test <= 9: print("Test 9: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True, \n \ known_plaintext=original_plaintext[-7:], amount=1)") decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True, known_plaintext=original_plaintext[-7:], amount=1) assert decrypted == original_plaintext[-block_size:] if from_test <= 10: print("Test 10: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=False, \n \ known_plaintext=original_plaintext[-7:], amount=1)") decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=False, known_plaintext=original_plaintext[-7:], amount=1) assert decrypted == original_plaintext[-block_size:] if from_test <= 11: print("Test 11: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True, \n \ known_plaintext=original_plaintext[-block_size - 3:])") decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True, known_plaintext=original_plaintext[-block_size - 3:]) assert decrypted == original_plaintext if from_test <= 12: print("Test 12: cbc.decrypt(original_ciphertext, decryption_oracle=decryption_oracle, is_correct=True, \n \ known_plaintext=original_plaintext[-block_size - 3:])") decrypted = cbc.decrypt(original_ciphertext, decryption_oracle=decryption_oracle, known_plaintext=original_plaintext[-block_size - 3:], is_correct=True) assert decrypted == original_plaintext if from_test <= 13: print("Test 13: cbc.decrypt(original_ciphertext, decryption_oracle=decryption_oracle)") decrypted = cbc.decrypt(original_ciphertext, decryption_oracle=decryption_oracle) assert decrypted == original_plaintext
def test_bleichenbacher_signature_forgery(): key = key_1024_small_e print( "\nTest bleichenbacher_signature_forgery(key, garbage='suffix', hash_function='sha1')" ) for _ in range(10): message1 = bytes(b"Some plaintext ") + random_bytes(10) + bytes( b" anything can it be") message2 = bytes(b"Some plaintext ") + random_bytes(10) + bytes( b" anything can it be") key.add_plaintext(b2i(message1)) key.add_plaintext(b2i(message2)) forged_signatures = bleichenbacher_signature_forgery( key, garbage='suffix', hash_function='sha1') assert len(forged_signatures) == 2 verify_signature1 = subprocess.check_output([ "python", rsa_oracles_path, "verify_bleichenbacher_suffix", key.identifier, b2h(message1), i2h(forged_signatures[0]), 'sha1' ]).strip().decode() assert verify_signature1 == 'True' verify_signature2 = subprocess.check_output([ "python", rsa_oracles_path, "verify_bleichenbacher_suffix", key.identifier, b2h(message2), i2h(forged_signatures[1]), 'sha1' ]).strip().decode() assert verify_signature2 == 'True' key.clear_texts() print( "\nTest bleichenbacher_signature_forgery(key, garbage='middle', hash_function='sha1')" ) for _ in range(10): message1 = bytes(b"Some plaintext ") + random_bytes(10) + bytes( b" anything can it be") message2 = bytes(b"Some plaintext ") + random_bytes(10) + bytes( b" anything can it be") key.add_plaintext(b2i(message1)) key.add_plaintext(b2i(message2)) forged_signatures = bleichenbacher_signature_forgery( key, garbage='middle', hash_function='sha1') print(forged_signatures) # first plaintext signed if 0 in forged_signatures: verify_signature1 = subprocess.check_output([ "python", rsa_oracles_path, "verify_bleichenbacher_middle", key.identifier, b2h(message1), i2h(forged_signatures[0]), 'sha1' ]).strip().decode() assert verify_signature1 == 'True' # second plaintext signed if 1 in forged_signatures: verify_signature2 = subprocess.check_output([ "python", rsa_oracles_path, "verify_bleichenbacher_middle", key.identifier, b2h(message2), i2h(forged_signatures[1]), 'sha1' ]).strip().decode() assert verify_signature2 == 'True' key.clear_texts()