Skip to content

Instantly share code, notes, and snippets.

@srli
Created June 26, 2018 03:35
Show Gist options
  • Save srli/fd1c67cba10cd95091d992152fc80d04 to your computer and use it in GitHub Desktop.
Save srli/fd1c67cba10cd95091d992152fc80d04 to your computer and use it in GitHub Desktop.
Sample encoding and decoding caesar cipher generator
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