def encrypt_vertical(message, key, n=1, filler='X'): # example message: AABBCCDDEE # example permutation: 2, 1, 3 # n = 2 key = get_permutation(key) if type(key) == tuple else key_permutation(key) result = [] column_size = math.ceil(len(message) / (n * len(key))) #1. break into 2-grams and add padding as necessary ngrams_list = break_into_ngrams_with_remainders(message, n) # add padding to the last ngram if it has been truncated -- if filler is not the empty string if filler != '': while len(ngrams_list[len(ngrams_list) - 1]) < n: ngrams_list[len(ngrams_list) - 1] += filler #2. make a list of columns #[['AA' 'DD'] ['BB' 'EE'] ['CC']] columns_list = [] for i in range(len(key)): columns_list.append(ngrams_list[i::len(key)]) # add padding blocks to the columns that have been truncated #(in this case, add 'XX' to the 'CC' column) for column in columns_list: if len(column) < column_size: column.append(n * filler) #3. rearrange the columns in the list for j in range(len(key)): col = columns_list[key[j] - 1] result.append(''.join(col)) return ''.join(result)
def encrypt_horizontal(message, key, n=1, filler='X'): #example message: AABBCCDDEEFF #example permutation: 2, 1, 3 #n = 2 key = get_permutation(key) if type(key) == tuple else key_permutation(key) result = [] #represents the final message #1. break into 2-grams and add padding as necessary ngrams_list = break_into_ngrams_with_remainders(message, n) #add padding to the last ngram if it has been truncated -- if there is filler if filler != '': while len(ngrams_list[len(ngrams_list) - 1]) < n: ngrams_list[len(ngrams_list) - 1] += filler #2. make a list of horizontal parts ([['AA' 'BB' 'CC'] ['DD' 'EE' 'FF']]) parts_to_tranpose_list = [] index = 0 while index < len(ngrams_list): li = [] for j in range(len(key)): try: #if index is OK, append normally li.append(ngrams_list[index]) except IndexError: #otherwise append a filler block li.append(filler * n) index += 1 parts_to_tranpose_list.append(li) #3. transpose each part for part in parts_to_tranpose_list: for i in range(len(key)): result.append(part[key[i] - 1]) return ''.join(result)
def nfid_encode(c, period, n): m = int(period * n) c_list = break_into_ngrams_with_remainders(c, m) result = [] for i in range(len(c_list)): result.append(encrypt(key=n, message=c_list[i])) return ''.join(result)
def decrypt_horizontal(message, key, n=1): #same as encrypting with the inverse permutation -- except if there are remainders key = get_permutation(key) if type(key) == tuple else key_permutation(key) inv_perm = invert(key) column_size = math.ceil(len(message) / (n * len(key))) are_remainders = len(message) / (n * len( key)) != column_size #check to see if there even are remainders #if there are no remainders, it is a simple calculation if not are_remainders: return encrypt_horizontal(message, inv_perm, n) #otherwise... grid_size = column_size * len(key) num_of_remainders = grid_size - math.ceil(len(message) / n) letters_per_row = n * len(key) truncated = ''.join(break_into_ngrams(message, letters_per_row)) #this part of the message can be decrypted simply using the encryption algorithm & the inverse of the key non_remainder_decrypted = encrypt_horizontal(truncated, inv_perm, n) #but more needs to be done to get the remainder in the right order... non_truncated = break_into_ngrams_with_remainders(message, letters_per_row) remainder_portion = non_truncated[len(non_truncated) - 1] #if remainder is a single-cell remainder just append to the end of the message if len(remainder_portion) <= n: return non_remainder_decrypted + ''.join(remainder_portion) #otherwise... do the complicated rearrangement process else: reconstructed_rem_rows_list = [] i = 0 j = 0 while i < len(key): addend = 0 if key[i] == len(key) - num_of_remainders: block_remainder = (n - len(message) % n) % n addend = n - block_remainder elif key[i] in range(len(key) - num_of_remainders): addend = n reconstructed_rem_rows_list.append(remainder_portion[j:j + addend]) j += addend i += 1 #put the rows in the remainder list in the right order ordered_rem_rows = [] for i in range(len(inv_perm)): ordered_rem_rows.append(reconstructed_rem_rows_list[inv_perm[i] - 1]) #return the truncated decryption + the remainder decryption return non_remainder_decrypted + ''.join(ordered_rem_rows)
def encrypt(message, key, splitter=''): ngrams = break_into_ngrams_with_remainders(message, key) are_remainders = int(len(message) / key) != len(message) / key if not are_remainders: stop = len(ngrams) extra = '' else: stop = len(ngrams) - 1 extra = reverse(ngrams[len(ngrams) - 1]) result = [reverse(ngrams[i]) for i in range(stop)] return ''.join(result) + splitter + extra
def get_grid(msg, key): return break_into_ngrams_with_remainders(msg, key)