Created
June 26, 2018 03:35
-
-
Save srli/fd1c67cba10cd95091d992152fc80d04 to your computer and use it in GitHub Desktop.
Sample encoding and decoding caesar cipher generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import string | |
import random | |
from collections import Counter | |
""" | |
An easy implementation of the Caesar cipher | |
Written by Sophie Li, 2018 | |
http://blog.justsophie.com/caesar-cipher-generator/ | |
""" | |
def encode_string(input_string): | |
# Generate seed for shift | |
seed = random.randint(0, len(string.ascii_lowercase)) | |
# Create cipher dictionary by shifting alphabet over by "seed" places | |
alphabet = list(string.ascii_lowercase) | |
alphabet_shifted = alphabet[seed:] + alphabet[:seed] | |
cipher_dict = dict(zip(alphabet, alphabet_shifted)) | |
# Remove punctuation, spacing, and capitalization of input string | |
clean_text = input_string.translate(None, string.punctuation).replace(" ", "").lower() | |
# Encode string, adding a space every 4 letters for readability | |
cipher_text = "" | |
for ind, letter in enumerate(clean_text): | |
cipher_text += cipher_dict[letter] | |
if (ind+1)%4 == 0: | |
cipher_text += " " | |
return cipher_text | |
""" | |
There are a few ways to decode strings, but for this quick example, a | |
frequency analysis can be a good starting point-- especially if your message is | |
long. If the message is too short, there won't be enough data to do a good analysis. | |
""" | |
def cipher_freq_analysis(cipher_string): | |
# Calculate histogram of cipher text | |
cipher_hist = Counter(cipher_string.replace(" ", "")) | |
# Find alphabet positions of 4 most common letters | |
e_position = string.ascii_lowercase.index('e') | |
a_position = string.ascii_lowercase.index('a') | |
o_position = string.ascii_lowercase.index('o') | |
i_position = string.ascii_lowercase.index('i') | |
possible_seeds = [] | |
for ind in range(1, 3): | |
common_letter = cipher_hist.most_common(ind)[0][0] | |
# Check distance between the cipher histogram and common letters | |
e_distance = string.ascii_lowercase.index(common_letter) - e_position | |
a_distance = string.ascii_lowercase.index(common_letter) - a_position | |
o_distance = string.ascii_lowercase.index(common_letter) - o_position | |
i_distance = string.ascii_lowercase.index(common_letter) - i_position | |
# Add these distances as possible seeds | |
possible_seeds += [e_distance, a_distance, o_distance, i_distance] | |
return possible_seeds | |
def decode_string_by_seed(cipher_string, seed): | |
# Create cipher dictionary by shifting alphabet over by "seed" places | |
alphabet = list(string.ascii_lowercase) | |
alphabet_shifted = alphabet[seed:] + alphabet[:seed] | |
decode_dict = dict(zip(alphabet_shifted, alphabet)) | |
decode_dict[" "] = " " | |
# Encode string, adding a space every 4 letters for readability | |
decoded_text = "" | |
for ind, letter in enumerate(cipher_string): | |
decoded_text += decode_dict[letter] | |
print decoded_text | |
def decode_string(cipher_string): | |
possible_seeds = cipher_freq_analysis(cipher_string) | |
print "------" | |
print "Decoding string by possible seeds. CTRL+C to exit at any time" | |
for seed in possible_seeds: | |
print "------\n " | |
decode_string_by_seed(cipher_string, seed) | |
raw_input("") | |
if __name__ == '__main__': | |
raw_string = "Hi there, this is a sample string to be encoded. It's pretty normal looking." | |
cipher_string = encode_string(raw_string) | |
print "Ecoded string: ", cipher_string | |
decode_string(cipher_string) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment