Caesar Cipher Decrypt/Encrypt Python Script
If you’re unsure of the shift value the following script will find that for you. If you already know it’s a ROT 13, simply run the following Bash one liner:
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
#! /bin/python3 | |
import argparse,enchant | |
def check_range(value): | |
value = int(value) | |
if value >= 26 or value <= 0: | |
msg = "Shift value must be in the range 1 - 25." | |
raise argparse.ArgumentTypeError(msg) | |
return value | |
def main(): | |
parser = argparse.ArgumentParser(description=""" | |
Entering text surrounded by quotation marks by itself will attempt to decrypt and find | |
the shift in the supplied encrypted text. | |
""") | |
group = parser.add_mutually_exclusive_group() | |
group.add_argument(dest='encrypted_text', type=str, nargs='?', help="Encrypted text without flag") | |
group.add_argument('-d', dest='decrypt', type=str, nargs='?', help="Decrypt the supplied text") | |
group.add_argument('-e', dest='encrypt', type=str, nargs='?', help="Encrypt the supplied text") | |
parser.add_argument('-s', dest='shift', nargs='?', type=check_range, help=""" | |
The number of characters to shift. Value must be between 1 and 25 | |
""") | |
args = parser.parse_args() | |
if args.encrypt: | |
if args.shift: | |
shift = args.shift | |
else: | |
shift = 13 | |
print(encrypt(args.encrypt, shift)) | |
elif args.decrypt: | |
if(args.shift): | |
print(decrypt(args.decrypt,args.shift)) | |
else: | |
find_shift(args.decrypt) | |
elif args.shift and args.encrypted_text: | |
print(decrypt(args.encrypted_text,args.shift)) | |
elif args.encrypted_text: | |
find_shift(args.encrypted_text) | |
def shift_char(c, shift): | |
if ord('a') <= ord(c) <= ord('z'): | |
shift_c = chr(((ord(c) + shift - ord('a')) % 26) + ord('a')) | |
else: | |
shift_c = chr(((ord(c) + shift - ord('A')) % 26) + ord('A')) | |
return shift_c | |
def find_shift(encrypted_text, start=1, end=27): | |
shift_list = [] | |
for i in range(start,end): | |
decrypted = decrypt(encrypted_text, i) | |
shift_list.append(decrypted) | |
print("position: %d \t %s"%(i,decrypted)) | |
eng_dictionary = enchant.Dict("en_US") | |
match = "" | |
for i,shift_str in enumerate(shift_list): | |
#check for min of three real words to consider it a match | |
hits = 0 | |
for word in shift_str.split(" "): | |
if(eng_dictionary.check(word) == True): | |
if(hits == 3): | |
match = shift_str | |
break | |
else: | |
hits += 1 | |
if(len(match)): | |
print("\n\nMatch at shift position %d: %s"%(i+1,match)) | |
break | |
if(not len(match)): | |
print("\n\nNo match found.") | |
return(shift_list) | |
def decrypt(encrypted_text, shift_int): | |
new_string = '' | |
for char in encrypted_text: | |
if char.isalpha(): | |
new_string += shift_char(char, shift_int) | |
else: | |
new_string += char | |
return new_string | |
def encrypt(unencrypted_text, shift_int): | |
new_string = '' | |
for char in unencrypted_text: | |
if (not char.isalpha()): | |
new_string += char | |
else: | |
char_pos = ord(char) | |
if ord('a') < char_pos <= ord('z'): | |
shift_c = char_pos - shift_int | |
if shift_c < ord('a'): | |
shift_c = ord('z') - (ord('a') - shift_c - 1) | |
else: | |
shift_c = char_pos - shift_int | |
if shift_c < ord('A'): | |
shift_c = ord('Z') - (ord('A') - shift_c - 1) | |
new_string += chr(shift_c) | |
return new_string | |
if __name__ == "__main__": | |
main() |