RyanAllarey

Encryption / Decryption

Oct 19th, 2019
634
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.65 KB | None | 0 0
  1. """
  2. # Crypto Corgi Company
  3. Build some simple functions for encrypting, decrypting, and hashing text
  4. for cryptography purposes.
  5. Date: Fall 2019
  6. Course: CISC108
  7. School: University of Delaware
  8.  
  9. # When You Are Done
  10. When you pass all tests, remember to clean and document your code.
  11. But we will be reviewing your documentation and code quality!
  12. Yes, you have to unit test all your functions.
  13. """
  14.  
  15. from cisc108 import assert_equal
  16.  
  17. def convert_text(message:str) -> [int]:
  18.     '''
  19.    Consumes a 'message' and produces a list of integers where each character
  20.    gets converted to an int using the ASCII table.
  21.    
  22.    Args:
  23.        message (str): The string of text, it can be any message as long as
  24.            it is a valid string.
  25.    
  26.    Returns:
  27.        list[int]: the list of ints after the each value in the string was
  28.            converted to an int.
  29.    '''
  30.     new_list = []
  31.     for a_character in message:
  32.         new_list.append(ord(a_character))
  33.     return new_list
  34.  
  35. assert_equal(convert_text("A!"),[65,33])
  36. assert_equal(convert_text("CGM"),[67,71,77])
  37. assert_equal(convert_text("{!"),[123,33])
  38.  
  39. def shift_list(list_of_nums:[int],shift: int) -> [int]:
  40.     '''
  41.    Consumes a list of integers and a shift value. The list is shifted forward by
  42.    'shift' amount. For example, shifting the string "Apple" by 1 would create
  43.    "eAppl".
  44.    
  45.    Args:
  46.        list_of_nums (list[int]): The list of integers
  47.        shift (int): The amount the list is shifted forward.
  48.        
  49.    Returns:
  50.        list[int]: the list of ints after the each value in the list was shifted by
  51.            'shift' amount.
  52.    '''
  53.     for x in range(shift):
  54.         list_of_nums = [list_of_nums[-1]] + list_of_nums[:-1]
  55.     return list_of_nums
  56.    
  57. assert_equal(shift_list([1,2,3,4,5], 1),[5,1,2,3,4])
  58. assert_equal(shift_list([1,2,3,4,5], 3),[3,4,5,1,2])
  59. assert_equal(shift_list([1,2,3,4,5], 4),[2,3,4,5,1])
  60.  
  61. def rotate_list(list_of_nums:[int], rotate:int) -> [int]:
  62.     '''
  63.    Consumes a list of integers and a rotate value. The list is rotated by 'rotate'
  64.    amount using a rotation formula.
  65.    
  66.    Args:
  67.        list_of_nums (list[int]): The list of integers.
  68.        rotate (int): The amount the list is being rotated by.
  69.        
  70.    Returns:
  71.        list[int]: the list of ints after the each value in the list was rotated by
  72.            'rotate' amount.
  73.    '''
  74.     new_list = []
  75.     for a_number in list_of_nums:
  76.         new_list.append((a_number + rotate - 32) % 94 + 32)
  77.     return new_list
  78.  
  79. assert_equal(rotate_list([1,2,3,4,5],2),[97,98,99,100,101])
  80. assert_equal(rotate_list([110],50),[66])
  81. assert_equal(rotate_list([67],12),[79])
  82. assert_equal(rotate_list([0],10),[104])
  83.  
  84. def insert_tilde(list_of_nums:[int]) -> [int]:
  85.     '''
  86.    Consumes a list of integers. After every integer value that is less than 48, the
  87.    ASCII value of "~" which is 126 will be appended.
  88.    
  89.    Args:
  90.        list_of_nums (list[int]): A list of integers.    
  91.        
  92.    Returns:
  93.        list[int]: A new list of integers with the value 126 inserted after every
  94.            value in the list that is less than 48.
  95.    '''
  96.     new_list = []
  97.     for a_number in list_of_nums:
  98.         if a_number < 48:
  99.             new_list.append(a_number)
  100.             new_list.append(126)
  101.         else:
  102.             new_list.append(a_number)
  103.     return new_list
  104.  
  105. assert_equal(insert_tilde([125,48,23,123,4,5]),[125,48,23,126,123,4,126,5,126])
  106. assert_equal(insert_tilde([1,2,3,4,5]),[1,126,2,126,3,126,4,126,5,126])
  107.  
  108. def convert_to_str(list_of_nums:[int]) -> str:
  109.     '''
  110.    Consumes a list of integers and produces a string where each
  111.    value gets converted to a character using the ASCII table.
  112.    
  113.    Args:
  114.        list_of_nums (list[int]): A list of integers
  115.        
  116.    Returns:
  117.        str: The string produced after each value in the list was converted
  118.            back to a character.
  119.    '''
  120.     new_str = ""
  121.     for a_number in list_of_nums:
  122.         new_str = new_str + chr(a_number)
  123.     return new_str
  124.  
  125. assert_equal(convert_to_str([49,50,51,52,53]),"12345")
  126. assert_equal(convert_to_str([123]),"{")
  127.  
  128. def encrypt_text(message: str, shift: int, rotation: int) -> str:
  129.     '''
  130.    Consumes a string (plaintext message) and two integers (shift, and rotation),
  131.    and produces a new string that is encrypted.
  132.    
  133.    Args:
  134.        message (str): A plaintext message.
  135.        shift (int): The amount that the list will be shifted.
  136.        rotation (int): The amount that the list will be rotated.
  137.        
  138.    Returns:
  139.        str: The new string that is encrypted.  
  140.    '''
  141.     shifted_list = shift_list(convert_text(message),shift)
  142.     encrypted_text = convert_to_str(insert_tilde(rotate_list(shifted_list,rotation)))
  143.     return encrypted_text
  144.  
  145. assert_equal(encrypt_text("abcdefg",3,2),"ghicdef")
  146. assert_equal(encrypt_text("Hello world!",3,10),'vn+~Rovvy*~#~y|')
  147.  
  148. def remove_tilda(list_of_nums:[int]) -> [int]:
  149.     '''
  150.    Consumes a list of integers. For every value of 126 in the list, it
  151.    will be removed.
  152.    
  153.    Args:
  154.        list_of_nums (list[int]): A list of integers.    
  155.        
  156.    Returns:
  157.        list[int]: A new list of integers without any occurences of the value
  158.            126.
  159.    '''
  160.     new_list = []
  161.     for a_num in list_of_nums:
  162.         if a_num != 126:
  163.             new_list.append(a_num)
  164.     return new_list
  165.  
  166. assert_equal(remove_tilda([1234,123,5,12,3,126,6,3,126]),[1234,123,5,12,3,6,3])
  167. assert_equal(remove_tilda([126,126,126,126,126,126,1,2,6]),[1,2,6])
  168.  
  169. def rotate_negative(list_of_nums:[int],rotate:int) -> [int]:
  170.     '''
  171.    Consumes a list of integers and a rotate value. The list is rotated by (-'rotate')
  172.    amount using a rotation formula.
  173.    
  174.    Args:
  175.        list_of_nums (list[int]): The list of integers.
  176.        rotate (int): The negative amount the list is being rotated by.
  177.        
  178.    Returns:
  179.        list[int]: the list of ints after the each value in the list was rotated by
  180.            (-'rotate') amount.
  181.    '''
  182.     new_list = []
  183.     for a_number in list_of_nums:
  184.         new_list.append((a_number + (-rotate) - 32) % 94 + 32)
  185.     return new_list
  186.  
  187. assert_equal(rotate_negative([1,2,3,4,5],2),[93, 94, 95, 96, 97])
  188. assert_equal(rotate_negative([123],10),[113])
  189. assert_equal(rotate_negative([0],10),[84])
  190.  
  191. def shift_negative(list_of_nums:[int],shift: int) -> [int]:
  192.     '''
  193.    Consumes a list of integers and a shift value. The list is shifted forward by
  194.    (-'shift') amount. For example, shifting the string "Apple" by -1 would create
  195.    "ppleA".
  196.    
  197.    Args:
  198.        list_of_nums (list[int]): The list of integers
  199.        shift (int): The amount the list is shifted backwards.
  200.        
  201.    Returns:
  202.        list[int]: The list of ints after the each value in the list was shifted
  203.            backwards by 'shift' amount.
  204.    '''
  205.     for x in range(shift):
  206.         list_of_nums = list_of_nums[1:] + [list_of_nums[0]]
  207.     return list_of_nums
  208.  
  209. assert_equal(shift_negative([1,2,3,4,5],2),[3,4,5,1,2])
  210. assert_equal(shift_negative([0,10,-1,-6],6),[-1, -6, 0, 10])
  211.  
  212. def decrypt_text(encrypted_message: str, shift: int, rotation: int) -> str:
  213.     '''
  214.    Consumes a string (encrypted message) and two integers (shift, and rotation),
  215.    and produces a new string that is decrypted.
  216.    
  217.    Args:
  218.        encrypted_message (str): A message that has already been encrypted.
  219.        shift (int): The amount the listed will be shifted backwards.
  220.        rotate (int): The amount the list will be negatively rotated.
  221.        
  222.    Returns:
  223.        str: The new string that has been decrypted.
  224.    '''
  225.     rotated_list = rotate_negative(remove_tilda(convert_text(encrypted_message)),rotation)
  226.     decrypted_text = convert_to_str(shift_negative(rotated_list,shift))
  227.     return decrypted_text
  228.  
  229. assert_equal(decrypt_text('vn+~Rovvy*~#~y|',3,10),'Hello world!')
  230. assert_equal(decrypt_text('ghicdef',3,2),'abcdefg')
  231. assert_equal(decrypt_text('B',1,1),'A')
  232.  
  233. def hash_convert(list_of_nums:[int], base: int) -> [int]:
  234.     '''
  235.    Consumes a list of numbers that will be changed using the following formula:
  236.    new value = (index + base) ** (old value).
  237.    
  238.    Args:
  239.        list_of_nums (list[int]): A list of integers.
  240.        base (int): A value that will be used in the formula to tranform the list.
  241.        
  242.    Returns:
  243.        list[int]: The new list after each value has been transformed.
  244.    '''
  245.     new_list = []
  246.     index = 0
  247.     for a_number in list_of_nums:
  248.         new_list.append((index + base)**a_number)
  249.         index = index + 1
  250.     return new_list
  251.  
  252. assert_equal(hash_convert([1,2,3,4,5],3),[3, 16, 125, 1296, 16807])
  253. assert_equal(hash_convert([0],100),[1])
  254. assert_equal(hash_convert([100],10),[10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000])
  255.  
  256. def sum_list(list_of_nums:[int]) -> int:
  257.     '''
  258.    Consumes a list of integers and sums the list of integers.
  259.    
  260.    Args:
  261.        list_of_nums (list[int]): A list of integers.
  262.    
  263.    Returns:
  264.        int: The sum value of all the values in the list.
  265.    '''
  266.     sum = 0
  267.     for a_number in list_of_nums:
  268.         sum += a_number
  269.     return sum
  270.  
  271. assert_equal(sum_list([1,2,3,4,5]),15)
  272. assert_equal(sum_list([0]),0)
  273. assert_equal(sum_list([-1,-2,-3,-4,-5]),-15)
  274.  
  275. def limit_hash_size(total_sum: int, hash_size: int) -> int:
  276.     '''
  277.    Consumes a total sum and a hash size and uses the modulo operator (%)
  278.    to limit the total value to the hash size.
  279.    
  280.    Args:
  281.        total_sum (int): A total value.
  282.        hash_size (int): A value that the total value will be limited by.
  283.        
  284.    Returns:
  285.        int: The value that the total value is limited by because of the hash size.
  286.    '''
  287.     return total_sum % hash_size
  288.  
  289. assert_equal(limit_hash_size(15,4),3)
  290. assert_equal(limit_hash_size(0,100),0)
  291. assert_equal(limit_hash_size(100,5),0)
  292.  
  293. def hash_text(text: str, base: int, hash_size: int) -> int:
  294.     '''
  295.    Consumes a string (any text) and two integers (base and hash_size), and produces an
  296.    integer that attempts to uniquely represent the text.
  297.    
  298.    Args:
  299.        text (str): Any valid string message.
  300.        base (int): A value that will be used in a formula to tranform the list.
  301.        hash_size (int): A value that the total value will be limited by.
  302.        
  303.    Returns:
  304.        int: an integer that uniquely represents the original text.
  305.    '''
  306.     converted_list = hash_convert(convert_text(text),base)
  307.     return int(limit_hash_size(sum_list(converted_list),hash_size))
  308.  
  309. assert_equal(hash_text('abcdefg',3,1000000000),62589600)
  310.  
  311. def main():
  312.     """
  313.    Main function that calls all the other functions and provides
  314.    an crypto experience
  315.    """
  316.     action = input("What would you like to do? ")
  317.     shift = 3
  318.     rotate = 10
  319.     base = 3
  320.     hash_size = 1000000000
  321.     if action == "encrypt":
  322.         message = input("Enter a message. ")
  323.         encrypted_message = encrypt_text(message,int(shift), int(rotate))
  324.         hashed_text = hash_text(encrypted_message, base, hash_size)
  325.         print("You're encrypted message is " + encrypted_message)
  326.         print("You're hashed text is " + str(hashed_text))
  327.     elif action == "decrypt":
  328.         message = input("Enter your encrypted message. ")
  329.         decrypted_message = decrypt_text(message, int(shift), int(rotate))
  330.         expected_hash = input("Enter your expected hash. ")
  331.         actual_hash = hash_text(decrypted_message, base, hash_size)
  332.         if actual_hash == int(expected_hash):
  333.             print(decrypted_message)
  334.         else:
  335.             print("Error Error Error")
  336.     else:
  337.         print("There is an error. Goodbye.")
  338.        
  339.     # ...
  340.  
  341.  
  342. # The following lines of code are used to call the main function.
  343. # Professional Python programmers always guard their main function call with
  344. #   this IF statement, to make it easier for other users to call their code.
  345. # For now, just leave this code alone, but recognize that it is how you are
  346. #   calling your main function.
  347. if __name__ == '__main__':
  348.     main()
  349.    
  350. """
  351. #Extra Credit Questions
  352.  
  353. 1. Define the term "Security through Obscurity" and explain why it is not a good idea,
  354. in the context of Ada's Crypto Corgi Company.
  355.  
  356. 2. Define and explain the difference between integrity, authentication, and confidentiality.
  357. Given these terms, what is the important difference between sending the hash values and the
  358. encrypted message?
  359.  
  360. 3. Look up the term "Hash Collision". Find two strings that hash together using Ada's hashing
  361. algorithm for the base 31 and hash_size 10**9.
  362.  
  363. 4. Decrypt the following text. Note that each line is using a different set of integers for the shift
  364. and rotation.
  365. """
Add Comment
Please, Sign In to add comment