利用受损的One Time Pad

时间:2015-10-30 18:40:56

标签: python xor

我编写了一些Python 3脚本来利用一次性密钥,其中密钥已被多次使用。

当我将它应用于一些较短的测试用例时,它会产生正确的结果。 但是,当我尝试将它应用于更长的密码时,我感觉它不能正常工作,因为我无法扩展有希望的字符串。 这是PICNIC,还是代码中还有错误?

   # -*- coding: UTF-8 -*-
import binascii

with open("ciphers.txt") as f:
    ciphers = list(map(str.strip, f.readlines()))

# print(ciphers)
""" words which were already looked up """
occurred_words = []

xor_cipher_list = []
occurrence_count_list = [0] * 200
occurred_twoples = []


# print(ciphers)


def xor_ciphers(cipher_strings):
    """
    :param cipher_strings: the cipher strings in hex to xor together
    :return: the xord ciphers(hex, string)
    xors the 10 cipher strings, two at a time
    """
    cipher_hash_list = [int(ciphers[i], 16) ^ int(ciphers[i + 1], 16) for i in (range(0, len(ciphers) - 1, 2))]
    # print([hex(hr)[2:] for hr in cipher_hash_list])
    return [hex(hr)[2:] for hr in cipher_hash_list]


def crib_to_hex_string(try_word):
    """
    :param try_word: ascii string
    :return: hex string
    turns the crib attempt word inta a hex string
    """
    crib_hex = ''.join(format(ord(letter), '02x') for letter in try_word)
    return crib_hex


def adjust_cipher_length(hex_crib_length):
    """
    :param hex_crib_length: the length of the crib to adjust to
    :return: a list of all the positions of the ciphers to check the crib against
    """
    hex_list = [hash_cipher[i:i + min(hex_crib_length, len(hash_cipher))] for hash_cipher in xor_cipher_list for i in
                range(0, len(hash_cipher) - min(hex_crib_length, len(hash_cipher)) + 1, 1)]
    return hex_list


def attempt_to_decipher(hex_crib_string, hash_to_check_against):
    """
    :param hex_crib_string: the hex crib string
    :param hash_to_check_against: list of the xord, hex, in the right size ciphers
    :return: byte stream of the decoded hex result of the xor
    xors the crib with one hash of the list and returns the value
    """
    smaller_length = min(len(hex_crib_string), len(hash_to_check_against))
    decipher_attempt = int(hex_crib_string, 16) ^ int(hash_to_check_against, 16)
    decipher_attempt = hex(decipher_attempt)[2:].zfill(smaller_length)
    # print(decipher_attempt, end=": ")
    return binascii.unhexlify(decipher_attempt)


def look_up(attempted_decoded_byte_stream):
    """
    :param attempted_decoded_byte_stream: an ascii byte stream of the attempted decode
    :return:nothing, recurses on success
    looks the ascii string up, on success tries whole process again with new word
    """
    global decoded_string
    try:
        decoded_string = str(attempted_decoded_byte_stream, "ASCII")
    except UnicodeDecodeError:
        "Not able to decode"
    if decoded_string not in occurred_words:
        occurred_words.append(decoded_string)
        print(decoded_string)


def try_with(try_word):
    """
    :param try_word: string of word to try with
    :return: nothing
    controller of the script, first turns everything into right format, then xors it and prints it
    """
    """ turn the cribword to a hex string """
    hex_crib_string = crib_to_hex_string(try_word)
    # print(hex_crib_string)
    hex_crib_length = len(hex_crib_string)

    """ adjust the ciphers to right length """
    cipher_adjusted_length_list = adjust_cipher_length(hex_crib_length)
    # print(xor_cipher_list)
    # print(cipher_adjusted_length_list)
    """ xors and looks up """
    for cipher in cipher_adjusted_length_list:
        attempted_decoded_byte_stream = attempt_to_decipher(hex_crib_string, cipher)
        look_up(attempted_decoded_byte_stream)


if __name__ == "__main__":
    """needs to be done only once"""
    xor_cipher_list = xor_ciphers(ciphers)
    """ start the whole process """
    try_with(" have ")

0 个答案:

没有答案