Пример #1
0
def main():

    msg = input("Enter a message: ")
    # IMPORTANT PRECONDITION: ENTIRE MESSAGE SHOULD BE UPPERCASE
    msg = ''.join(msg.split())  #case matters! only spaces are removed
    n = int(input("n = "))
    custom_alphabet = input("Custom alphabet <y/n>?: ")

    # input validation
    while not custom_alphabet.upper() in 'YN':
        custom_alphabet = input("Custom alphabet <y/n>?: ")

    alphabet = ''.join(get_distinct_ngrams(input("Enter an alphabet: "), n=1)) \
        if custom_alphabet.upper() == 'Y' else DEFAULT_ALPHABET

    mode = input("Mode <encrypt/decrypt>?: ")

    #input validation
    while not (mode.upper() == 'ENCRYPT' or mode.upper() == 'DECRYPT'):
        mode = input("<encrypt/decrypt>?: ")

    print()  #padding

    print(encrypt(msg, n, alphabet)) if mode.upper() == 'ENCRYPT' \
        else print(decrypt(msg, n, alphabet))
Пример #2
0
def generate_expected(msg, n=1, alphabet=''):

    expected = dict()
    #this is the alphabet by default (if no alphabet is provided)
    if alphabet == '':
        alphabet = ''.join(get_distinct_ngrams(msg, 1))

    expected_value = 1 / pow(len(alphabet), n)
    all_ngrams = generate_all_possible_ngrams(n, alphabet)
    for ngram in all_ngrams:
        expected[ngram] = expected_value

    return expected
Пример #3
0
def ngrams_to_letters(msg, n, alphabet = DEFAULT_ALPHABET):
    ngram_list = []
    possible_ngrams = ngramFrequencyAnalysis.get_distinct_ngrams(msg, n)
    for index in range(0, len(msg), n):
        ngram_list.append(msg[index: index + n])

    result = []
    for ngram in ngram_list:
        if len(ngram) != n:
            break
        i = possible_ngrams.index(ngram)
        result.append(alphabet[i])

    return ''.join(result)
Пример #4
0
def main():

    message = input("Enter a message: ")

    message = ''.join(message.split())
    n = int(input("n = "))
    custom_alphabet = input("Custom alphabet <y/n>?: ")

    #input validation
    while not custom_alphabet.upper() in 'YN':
        custom_alphabet = input("Custom alphabet <y/n>?: ")

    alphabet = ''.join(ngramFrequencyAnalysis.get_distinct_ngrams(input("Enter an alphabet: "), n=1))  \
    if custom_alphabet.upper() == 'Y' else DEFAULT_ALPHABET

    print() #padding

    print(ngrams_to_letters(message, n, alphabet))
Пример #5
0
def main():

    message = input('Enter a message: ')
    display_msg = """
E)   compare to standard English frequencies
U)   compare to uniform English distribution
N)   compare n-grams to random distribution

"""
    test_type = input(display_msg)
    #input validation
    validate_input(test_type, 'EUN')
    #check test type and print appropriate test
    if test_type.upper() == 'E':
        print_all_ngram_chi_squared_test_results(message,
                                                 alphabet=ENGLISH_ALPHABET,
                                                 compare_to_english=True)
    elif test_type.upper() == 'U':
        print_all_ngram_chi_squared_test_results(message,
                                                 alphabet=ENGLISH_ALPHABET)
    else:
        custom_alphabet = input(
            "Custom alphabet? (contains characters not present in the message) <y/n>: "
        )
        validate_input(custom_alphabet, 'YN')
        if custom_alphabet.upper() == 'Y':
            #in case the user accidentally types multiple characters in the alphabet, be ready...
            alphabet = ''.join(
                get_distinct_ngrams(input("Enter the alphabet:"), n=1))
        else:
            alphabet = ''  #this is the input passed for the default value of the alphabet

        lower = int(input("Lower bound: n = "))
        upper = int(input("Upper bound: n = "))
        print_all_ngram_chi_squared_test_results(message,
                                                 lower_bound=lower,
                                                 upper_bound=upper)
Пример #6
0
def main(ciphertext: str):

    try:
        parts = ast.literal_eval(ciphertext)
        #extract data from a saved list (if that is the input)
        ciphertext, bold_letters, non_bold_letters, replaced_characters = parts[
            0], parts[1], parts[2], parts[3]
    except (SyntaxError, ValueError):
        #otherwise if the input is not a list, assume that input is a normal ciphertext
        bold_letters = []
        non_bold_letters = get_distinct_ngrams(ciphertext, n=1)
        replaced_characters = []
    print()
    print_with_bolds(ciphertext)
    print()
    while True:
        character = input(
            "Enter a character to replace,'/UNDO' to undo a character replacement, '/FREQ' to view frequencies,\
'/RESET' to undo all character replacements, or '/Q' to save & quit: ")

        if character == '/Q':
            print()  #padding
            print("Your current message: ", end='')
            print_with_bolds(ciphertext)
            print()  #more padding
            save_list = str([
                ciphertext, bold_letters, non_bold_letters, replaced_characters
            ])
            print("Enter this next time to resume <copied to clipboard>: " +
                  save_list)
            pyperclip.copy(save_list)
            sys.exit(0)

        elif character.upper() == '/FREQ':
            print()
            print_special_frequency_analysis(''.join(ciphertext.split()),
                                             bold_letters, non_bold_letters,
                                             replaced_characters)
            print_with_bolds(ciphertext)
            print()
            continue

        elif character.upper() == '/RESET':
            print()
            ciphertext = reset_message(ciphertext)
            bold_letters.clear()
            non_bold_letters = get_distinct_ngrams(ciphertext, n=1)
            replaced_characters.clear()
            print_with_bolds(ciphertext)
            print()
            continue

        elif character in non_bold_letters:
            new_character = input("Enter replacement character: ")
            #intermediate ciphertext to indicate which letters are bold
            ciphertext = special_replace(ciphertext, character,
                                         new_character + BOLD_CHAR + character)
            #add an entry to replaced characters
            replaced_characters.append((character, new_character))
            #character has been bolded now -- remove from non-bolded
            non_bold_letters.remove(character)
            bold_letters.append(new_character)
            print()
            print_with_bolds(ciphertext)
            print()  #one extra line of padding

        elif character.upper() == '/UNDO':
            character_to_revert = input("Enter bolded character to revert: ")
            if character_to_revert in bold_letters:
                possible_reverts = [
                ]  #a list of possible bold mappings to revert
                for i in range(len(replaced_characters)):
                    if replaced_characters[i][1] == character_to_revert:
                        possible_reverts.append(replaced_characters[i][0])

                if len(possible_reverts) == 1:
                    reverted_character = possible_reverts[0]

                else:
                    print(
                        "The bolded character %s has been used to replace: " %
                        character_to_revert,
                        end='')
                    print(*possible_reverts)
                    reverted_character = input(
                        "Which of those characters would you like to see nonbolded? "
                    )
                    #input validation
                    while reverted_character not in possible_reverts:
                        reverted_character = input(
                            "Please enter one of the characters listed above: "
                        )

                # finally, do the replacement
                ciphertext = ciphertext.replace(
                    character_to_revert + BOLD_CHAR + reverted_character,
                    reverted_character)
                #update bold & non-bold letters lists
                bold_letters.remove(character_to_revert)
                non_bold_letters.append(reverted_character)
                #delete entry from replaced_characters
                replaced_characters.remove(
                    (reverted_character, character_to_revert))

                print()  #padding
                print_with_bolds(ciphertext)
                print()  #padding

            else:
                print(
                    "Invalid input -- character entered is not among bolded letters"
                )
                print()
                print_with_bolds(ciphertext)
                print()
                continue

        else:
            print(
                "Invalid input -- character entered is not among nonbolded letters"
            )
            print()
            print_with_bolds(ciphertext)
            print()
            continue
Пример #7
0
def print_nth_column_frequencies(message, key, n):
    nth_column = get_nth_column(message, key, n)
    print_special_frequency_analysis(nth_column, default_input='Y') if not BOLD_CHAR in nth_column else \
    print_special_frequency_analysis(nth_column, bold_letters=get_distinct_ngrams(message, n=1), default_input='Y')
Пример #8
0
def outer_hill_climb(message, alphabet=DEFAULT_ALPHABET, initial_key=None):

    #important note: pseucocode describes a 1-based index coordinate system
    #so need to standardize by subtracting one from the indexes in all the swaps

    global best_key
    global best_initial_key

    distinct_symbols = ''.join(get_distinct_ngrams(message, n=1))
    n = len(distinct_symbols)
    D_C = get_observed_bigram_frequency_matrix(message,
                                               alphabet=distinct_symbols)
    message_length = len(message)
    m_values = get_initial_frequency_distribution(n, alphabet)

    if not initial_key:
        m_values = get_initial_frequency_distribution(n, alphabet)
        best_score = random_initial_key(m_values, D_C, message_length,
                                        alphabet)
    else:
        best_initial_key = initial_key
        m_values = get_initial_frequency_distribution_from_key(
            initial_key, alphabet)
        initial_decryption = decode_homophonic(message, distinct_symbols,
                                               initial_key)
        best_score = get_bigram_score(
            get_observed_bigram_frequency_matrix(initial_decryption, alphabet),
            get_expected_bigram_frequency_matrix(message_length, alphabet))
    best_key = best_initial_key

    for i in range(1, len(alphabet)):
        for j in range(1, len(alphabet) - i + 1):

            if m_values[j - 1] != 0:
                m_prime_values = outer_swap(m_values, j + i - 1, j - 1)
            else:
                continue  #cannot swap the values if the second value is equal to zero (no negative numbers)

            score = random_initial_key(m_prime_values, D_C, message_length,
                                       alphabet)

            if score < best_score:
                m_values = m_prime_values
                best_score = score
                best_key = best_initial_key
            else:
                if m_values[j - 1] != 0:
                    m_prime_values = outer_swap(m_values, j + i - 1, j - 1)
                else:
                    continue

                score = random_initial_key(m_prime_values, D_C, message_length,
                                           alphabet)
                if score < best_score:
                    m_values = m_prime_values
                    best_score = score
                    best_key = best_initial_key

        print('$', end='')

    return distinct_symbols, best_key
Пример #9
0

if __name__ == '__main__':
    #note: case sensitive! message should be ALL UPPERCASE
    print(
        "WARNING: this program is case-sensitive. The default alphabet is the capital alphabet A-Z."
    )
    msg = input("Enter a message: ")

    custom_def_alphabet = input("Custom (default) alphabet <y/n>?: ")

    # input validation
    while not custom_def_alphabet.upper() in 'YN':
        custom_def_alphabet = input("Custom alphabet <y/n>?: ")

    custom_def_alphabet = ''.join(get_distinct_ngrams(input("Enter a custom (default) alphabet: "), n=1)) \
        if custom_def_alphabet.upper() == 'Y' else ALPHABET

    mode = input("Encrypt/Decrypt <e/d>?: ")

    # more input validation
    while not mode.upper() in 'ED':
        key = input("Please enter a valid mode:")
    if mode.upper() == 'E':
        r = input("Encrypt with a randomly generated alphabet <y/n>?: ")
        while not r.upper() in 'YN':
            key = input("Please enter 'y' or 'n':")
        if r.upper() == 'Y':
            random_alph = generate_random_alphabet(custom_def_alphabet)
            print(encrypt(msg, random_alph, custom_def_alphabet))
            print("Alphabet Used: " + random_alph)