#--------------------------
# CP460 (Fall 2019)
# Final Exam
# Do not edit this file
#--------------------------

import final
import utilities
import mod
import SDES
import matrix
import math
import random
import string

#----------------------------------------------------
# Honor Pledge
#---------------------------------------------------
def honor_pledge():
    final.honor_pledge()
    return

#----------------------------------------------------
# Test Q1: mathCipher
#---------------------------------------------------
def test_q1():
    print("-------------------------------------------")
    print("Testing Q1: MathCipher")
    print()

    alphabet = utilities.get_lower()

    print('Testing validity of keys:')
    keys = [['ab',[1,1,1]],('',[1,1,1]),('a',[1,1,1]),(123,[1,1,1]),
            ('ab',(1,1,1)),('ab',[1,1]),('ab',[1,'1',1]),(alphabet,[6,7,11]),
            (alphabet,[11,13,19]),(alphabet,[11,7,13])]
    for key in keys:
        print(key, ' = ', final.isValidKey_mathCipher(key))
    print()
    
    print('Testing Encryption/Decryption:')
    baseStr = alphabet
    k = [5,9,11]
    plaintext = 'MATH CIPHER'
    key = (baseStr,k)
    print('key = ',key)
    print('plaintext =  ',plaintext)
    ciphertext = final.e_mathCipher(plaintext,key)
    print('ciphertext=  ',ciphertext)
    plaintext2 = final.d_mathCipher(ciphertext,key)
    print('plaintext2=  ',plaintext2)
    print()

    baseStr = alphabet + ' ?!'
    k = [45,5,16]
    plaintext = 'Is mission accomplished?'
    key = (baseStr,k)
    print('key = ',key)
    print('plaintext =  ',plaintext)
    ciphertext = final.e_mathCipher(plaintext,key)
    print('ciphertext=  ',ciphertext)
    plaintext2 = final.d_mathCipher(ciphertext,key)
    print('plaintext2=  ',plaintext2)
    print()

    baseStr = alphabet + ' ?!#'
    k = [5,5,5]
    plaintext = ''
    key = (baseStr,k)
    print('key = ',key)
    print('plaintext =  ',plaintext)
    ciphertext = final.e_mathCipher(plaintext,key)
    print()
    plaintext2 = final.d_mathCipher(ciphertext,key)
    print()
    print()

    k = [421,421,421]
    baseStr = alphabet + '?!'
    key = (baseStr,k)
    plaintext = 'The quick brown fox jumps over the lazy dog'
    print('key = ',key)
    print('plaintext =  ',plaintext)
    ciphertext = final.e_mathCipher(plaintext,key)
    print('ciphertext=  ',ciphertext)
    plaintext2 = final.d_mathCipher(ciphertext,key)
    print('plaintext2=  ',plaintext2)
    print()

    k = [10,3,9]
    baseStr = alphabet + '#?!'
    key = (baseStr,k)
    print('key = ',key)
    print('plaintext =  ',plaintext)
    ciphertext = final.e_mathCipher(plaintext,key)
    print('ciphertext=  ',ciphertext)
    plaintext2 = final.d_mathCipher(ciphertext,key)
    print('plaintext2=  ',plaintext2)
    print()
    
    k = [0,1,1]
    plaintext = 'This is Q1 of CP460 Final Exam'
    key = (baseStr,k)
    print('key = ',key)
    print('plaintext =  ',plaintext)
    ciphertext = final.e_mathCipher(plaintext,key)
    print()
    plaintext2 = final.d_mathCipher(plaintext,key)
    print()
    print()

    print('Testing analyze_mathCipher:')
    base = 'ab'
    print('Analyze: ',base,'= ',final.analyze_mathCipher(base))
    base = 'abc'
    print('Analyze: ',base,'= ',final.analyze_mathCipher(base))
    base = 'abcd'
    print('Analyze: ',base,'= ',final.analyze_mathCipher(base))
    base = 'abcde'
    print('Analyze: ',base,'= ',final.analyze_mathCipher(base))
    base = 'abcdefg'
    print('Analyze: ',base,'= ',final.analyze_mathCipher(base))
    base = utilities.get_lower()
    print('Analyze: ',base,'= ',final.analyze_mathCipher(base))
    base = base + '!#?'
    print('Analyze: ',base,'= ',final.analyze_mathCipher(base))
    print()

    print('Testing stats_mathCipher:')
    final.stats_mathCipher()
    print()

    print('Testing cryptanalysis:')
    plaintext = 'There are two kinds of cryptography in this world: cryptography that will stop your kid sister '
    plaintext+= 'from reading your files, and cryptography that will stop major governments from reading your files.'
    baseString = utilities.get_baseString()[:26]
    key = (baseString,[3,9,11])
    ciphertext = final.e_mathCipher(plaintext,key)
    plaintext,key = final.cryptanalysis_mathCipher(ciphertext)
    if plaintext != '':
        print('Key = ',key)
        print('plaintext = ',plaintext)
    print()
    
    ciphertext = 'Uxcnoicostplqpcampcaptaugec ktptcxolcamutcdiptauog,cnoicyurrcxughctozpcmugat'
    print('ciphertext: ',ciphertext)
    plaintext,key = final.cryptanalysis_mathCipher(ciphertext)
    if plaintext != '':
        print('Key = ',key)
        print('plaintext = ',plaintext)
    print()

    print("-------------------------------------------")

    return

#----------------------------------------------------
# Test Q2: Myszkowski Cryptanalysis
#---------------------------------------------------
def test_q2():
    print("-------------------------------------------")
    print("Testing Q2: Myskowski Cryptanalysis")
    print()

    print('Scenario 1:')
    
    ciphertext = 'Bd ims av ascenifc ale.Thsear ocasinsa oo larerwoldno mssqatehe itivu e ecso gden u ti.'
    print('ciphertext = ',ciphertext)
    print('Starting Cryptanalysis:')
    plaintext,key = final.cryptanalysis1_myszkowski(ciphertext)
    if plaintext != '':
        print('Key = ',key)
        print('plaintext = ',plaintext)
    print()

    ciphertext = 'omnoeemti nv o  g; nexre nreergN aout f xprienatonca eerprvemeriht asigl epeimntca pov m won.'
    print('ciphertext = ',ciphertext)
    print('Starting Cryptanalysis:')
    plaintext,key = final.cryptanalysis1_myszkowski(ciphertext)
    if plaintext != '':
        print('Key = ',key)
        print('plaintext = ',plaintext)
    print()

    final.q2_description1()
    print()

    print('Scenario 2:')

    ciphertext = 'cinc desno kowit dbttoimgiatonseeo tn se  ani'
    print('ciphertext = ',ciphertext)
    print('Starting Cryptanalysis:')
    plaintext,key = final.cryptanalysis2_myszkowski(ciphertext,3)
    if plaintext != '':
        print('Key = ',key)
        print('plaintext = ',plaintext)
    print()

    ciphertext = 'e  ifa ornaonl tf cyo, psdesaic p eaiolb n inoa sc rosal oomcessn.eneuodstinn '
    print('ciphertext = ',ciphertext)
    print('Starting Cryptanalysis:')
    plaintext,key = final.cryptanalysis2_myszkowski(ciphertext,13)
    if plaintext != '':
        print('Key = ',key)
        print('plaintext = ',plaintext)
    print()

    ciphertext = 'cuq ndohqot u asodchiean t cqqat uiq iyclqTsh'
    print('ciphertext = ',ciphertext)
    print('Starting Cryptanalysis:')
    plaintext,key = final.cryptanalysis2_myszkowski(ciphertext,15)
    if plaintext != '':
        print('Key = ',key)
        print('plaintext = ',plaintext)
    print()

    final.q2_description2()
    print()

    print('Scenario 3:')

    ciphertext = 'irtTi:Dont atemchtmeo asngequsioqF  osuini tsp w    len'
    print('ciphertext = ',ciphertext)
    print('Starting Cryptanalysis:')
    plaintext,key = final.cryptanalysis3_myszkowski(ciphertext)
    if plaintext != '':
        print('Key = ',key)
        print('plaintext = ',plaintext)
    print()

    ciphertext = 'Sondip:avenou brks d sep ursqqe   gealhqcTHehaneoq'
    print('ciphertext = ',ciphertext)
    print('Starting Cryptanalysis:')
    plaintext,key = final.cryptanalysis3_myszkowski(ciphertext)
    if plaintext != '':
        print('Key = ',key)
        print('plaintext = ',plaintext)
    print()

    ciphertext = 'iitwtauoiqTrd p: artithhe sy estns rstqqhTS  eqifq'
    print('ciphertext = ',ciphertext)
    print('Starting Cryptanalysis:')
    plaintext,key = final.cryptanalysis3_myszkowski(ciphertext)
    if plaintext != '':
        print('Key = ',key)
        print('plaintext = ',plaintext)
    print()
    
    print("-------------------------------------------")
    print()
    return

#----------------------------------------------------
# Test Q3: SDES Modes
#---------------------------------------------------
def test_q3():
    print("-------------------------------------------")
    print("Testing Q3: SDES modes")
    print()

    print('Case 0:')
    plaintext = 'CP460 Final Exam'
    key = ''
    print('\te_SDES({},{}) = '.format(plaintext,key),end= '')
    ciphertext = final.e_SDES(plaintext,key,'CTR')
    print()
    print('\td_SDES({},{}) = '.format('Cfpzch3mN4f0',key),end = '')
    final.d_SDES('Cfpzch3mN4f0',key,'CTR')
    print()
    key = '111000111'
    print('\te_SDES({},{}) = '.format(plaintext,key),end= '')
    ciphertext = final.e_SDES(plaintext,key,'CBC')
    print()
    print('\td_SDES({},{}) = '.format(ciphertext,key),end = '')
    final.d_SDES('',key,'ECB')
    print()
    print()

    modes = ['ECB','CBC','OFB']

    for mode in modes:
        outFile = open('SDES_config.txt','w')
        outFile.close()
        
        print('Testing mode {}:'.format(mode))

        print('case {}:'.format(modes.index(mode)+1))
        SDES.config_SDES('rounds','2')
        SDES.config_SDES('key_size','9')
        SDES.config_SDES('block_size','12')
        SDES.config_SDES('encoding_type','B6')
        configList = SDES.get_SDES_config()
        print('Configuration:',configList)
        if mode != 'ECB':
            print('IV = ',SDES.get_IV())

        plaintext = 'xRxR'
        key = '111000111'
        ciphertext = final.e_SDES(plaintext,key,mode)
        print('\te_SDES({},{}) = {}'.format(plaintext,key,ciphertext))
        plaintext2 = final.d_SDES(ciphertext,key,mode)
        print('\td_SDES({},{}) = {}'.format(ciphertext,key,plaintext2))
        print()

        print('Case 2:')
        SDES.config_SDES('p','103')
        SDES.config_SDES('q','199')
        configList = SDES.get_SDES_config()
        print('Configuration:',configList)
        if mode != 'ECB':
            print('IV = ',SDES.get_IV())
        plaintext = 'DES is a legacy Cipher'
        key = '111000111'
        ciphertext = final.e_SDES(plaintext,key,mode)
        print('\te_SDES({},{}) = {}'.format(plaintext,key,ciphertext))
        plaintext2 = final.d_SDES(ciphertext,key,mode)
        print('\td_SDES({},{}) = {}'.format(ciphertext,key,plaintext2))
        print()
       
        print('Case 3:')
        SDES.config_SDES('rounds','5')
        SDES.config_SDES('key_size','15')
        SDES.config_SDES('block_size','24')
        configList = SDES.get_SDES_config()
        print('Configuration:',configList)
        print()
        if mode != 'ECB':
            print('IV = ',SDES.get_IV())
        plaintext = 'speed car'
        key = '111000111001010'
        ciphertext = final.e_SDES(plaintext,key,mode)
        print('\te_SDES({},{}) = {}'.format(plaintext,key,ciphertext))
        plaintext2 = final.d_SDES(ciphertext,key,mode)
        print('\td_SDES({},{}) = {}'.format(ciphertext,key,plaintext2))
        print()
        
        print('Case 4:')
        plaintext = 'AAAAAA'
        key = ''
        ciphertext = final.e_SDES(plaintext,key,mode)
        print('\te_SDES({},{}) = {}'.format(plaintext,key,ciphertext))
        plaintext2 = final.d_SDES(ciphertext,key,mode)
        print('\td_SDES({},{}) = {}'.format(ciphertext,key,plaintext2))
        print()
    
    print("-------------------------------------------")
    print()
    return

#----------------------------------------------------
# Test Q4: DoubleX Cipher
#---------------------------------------------------
def test_q4():
    print("-------------------------------------------")
    print("Testing Q4: DoubleX Cipher")
    print()
    
    print('Case 1:')
    ciphertext = utilities.file_to_text('q4A_ciphertext.txt')
    plaintext,key = final.q4A(ciphertext)
    print('key1 = ',key[0])
    print('key2 = ',key[1])
    print('plaintext[500:574]',plaintext[500:574])
    print()

    print('Case 2:')
    ciphertext = utilities.file_to_text('q4B_ciphertext.txt')
    plaintext,key = final.q4B(ciphertext)
    print('key1 = ',key[0])
    print('key2 = ',key[1])
    print('plaintext[500:576]',plaintext[500:576])
    print()

    print('Case 3:')
    ciphertext = utilities.file_to_text('q4C_ciphertext.txt')
    plaintext,key = final.q4C(ciphertext)
    print('key1 = ',key[0])
    print('key2 = ',key[1])
    print('plaintext[499:576]',plaintext[499:576])
    print()

    print("-------------------------------------------")
    return

#----------------------------------------------------
# Test Q5: Public X
#---------------------------------------------------
def test_q5():
    print("-------------------------------------------")
    print("Testing Q5: Public X")
    print()
    print('Key Information:')
    key = final.get_RSAKey()
    print('name = ',key[0])
    print('p = ',key[1])
    print('q = ',key[2])
    print('m = ',key[3])
    print('n = ',key[4])
    print('e = ',key[5])
    print('d = ',key[6])
    print()

    print('Testing LRM exponentiation:')
    b = 66
    e = 13
    m = 20
    print('({}**{}) mod {} = {}'.format(b,e,m,final.LRM(b,e,m)))
    b = 5
    e = 117
    m = 19
    print('({}**{}) mod {} = {}'.format(b,e,m,final.LRM(b,e,m)))
    b = 4
    e = 60
    m = 69
    print('({}**{}) mod {} = {}'.format(b,e,m,final.LRM(b,e,m)))
    b = 1234567890
    e = 151515151515151515
    m = 190
    print('({}**{}) mod {} = {}'.format(b,e,m,final.LRM(b,e,m)))
    print()

    print('Testing mod96 Encoding/decoding:')
    x = 'a'
    print('encode_mod96({}) = {}'.format(x,final.encode_mod96(x)))
    x = 'A'
    print('encode_mod96({}) = {}'.format(x,final.encode_mod96(x)))
    x = 'aB'
    print('encode_mod96({}) = {}'.format(x,final.encode_mod96(x)))
    x = 'bb'
    print('encode_mod96({}) = {}'.format(x,final.encode_mod96(x)))
    x = 'ABC DE'
    print('encode_mod96({}) = {}'.format(x,final.encode_mod96(x)))
    print()

    y = 0
    block_size = 4
    print('decode_mod96({},{}) = {}'.format(y,block_size,final.decode_mod96(y,block_size)))
    y = 26
    block_size = 3
    print('decode_mod96({},{}) = {}'.format(y,block_size,final.decode_mod96(y,block_size)))
    y = 27
    block_size = 6
    print('decode_mod96({},{}) = {}'.format(y,block_size,final.decode_mod96(y,block_size)))
    y = 97
    print('decode_mod96({},{}) = {}'.format(y,block_size,final.decode_mod96(y,block_size)))
    y = 214315391742
    block_size = 8
    print('decode_mod96({},{}) = {}'.format(y,block_size,final.decode_mod96(y,block_size)))
    print()
    
    print('Testing Encryption/Decryption:')
    print()
    print("""Case 1: Use instructor's public key:""")
    print()
    plaintext = "Your theory is crazy, but it's not crazy enough to be true"
    m = 535093796775623
    e = 32452999
    key = (m,e) # this is the instructor's public key
    ciphertext = final.e_RSA(plaintext,key)
    print('Encryption using instructor public key:')
    print('plaintext: ',plaintext)
    print('key: ',key)
    print('ciphertext: ',ciphertext)
    print()
    print('Decryption using instructor public key:')
    ciphertext = """e!WL;i^Vf*-QQFk\dpE(xLNwgW^6TM\Xa9lFss-fa6#k`ZD(dV|0u~bEa;XR\Z'Ea|#vB<fZcXS7\_F_ek,Y5U`sb_gi1RkvaF7);1]2gJ7).kfX"""
    plaintext2 = final.d_RSA(ciphertext,key)
    print('ciphtertext: ', ciphertext)
    print('key = ',key)
    print('plaintext: ',plaintext2)
    print()
    
    print("""Case 2: Use your  public/private key:""")
    print()
    plaintext = "Your theory is crazy, but it's not crazy enough to be true"
    name,p,q,m,n,e,d = final.get_RSAKey()
    key = (m,e) # this is your public key
    ciphertext = final.e_RSA(plaintext,key)
    print('Encryption using your public key:')
    print('plaintext: ',plaintext)
    print('key: ',key)
    print('ciphertext: ',ciphertext)
    print()
    print('Decryption using your private key:')
    key = (m,d) # this is your private key
    plaintext2 = final.d_RSA(ciphertext,key)
    print('ciphtertext: ', ciphertext)
    print('key = ',key)
    print('plaintext: ',plaintext2)
    print()

    print('Testing signature verification:')
    print()
    print('Message 1:')
    ciphertext = """h6}~I:7:hKwX:grYdCTDu*v\dL6BI|0tbU#s&n@2a?F1^S+:iwNn}OM6iMbZ8c) bS-WE1V&eJ{_VA*)bk>HzElUaRX%8LzDd/>PyHC9g6&^OTsBhUOc'{cWdLZT"rU}gC_Y Gs#cm"*tCkahjv?vMw`a;4LA{2o"""
    print(ciphertext)
    name,message = final.verify_RSA(ciphertext)
    print('Message Author: ',name)
    print('Message: ',message)
    print()

    print('Message 2:')
    ciphertext = """hhh'j`Z|d(v?Sj-3gvj3X6=idV^+2NV5h)p9mrmbf|6XS`@(be0/xd#kgO4>}ll.d"(K-7c.gae`[6[2i]yBjd][eBly'wA#ihw;<IAKh""zv~U*jtMz?.erea-],g:Pc;^*\]O#gkTdLMm_db7y$)U+gM=^xHG="""
    print(ciphertext)
    name,message = final.verify_RSA(ciphertext)
    print('Message Author: ',name)
    print('Message: ',message)
    print()
    print("-------------------------------------------")
    return
