Skip to content

Commit b5a3b09

Browse files
committed
added simple commandline tool to perform caeser cipher en/decoding. I usually use it in CTFs
1 parent a04df11 commit b5a3b09

File tree

1 file changed

+75
-0
lines changed

1 file changed

+75
-0
lines changed

caeser_cipher/caeser.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
from __future__ import print_function
2+
import os
3+
import string
4+
import argparse
5+
6+
try:
7+
maketrans = string.maketrans # python2
8+
except AttributeError:
9+
maketrans = str.maketrans # python3
10+
11+
12+
def caeser_cipher(string_: str, offset: int, decode: bool, file_: string) -> None:
13+
""" Caeser Cipher implementation, reads file or string. Also decodes.
14+
15+
Default implementation is ROT13 encoding.
16+
17+
To decode, specify the same offset you used to encode and your ciphertext / file.
18+
19+
:param string_: string to encode / decode
20+
:param offset: # of chars to rotate by
21+
:param decode: decode instead of encode
22+
:param file_: file to read in then encode/decode
23+
"""
24+
if file_ and os.path.exists(file_):
25+
with open(file_, 'r') as f:
26+
string_ = f.read()
27+
28+
if decode:
29+
offset *= -1
30+
31+
lower_offset_alphabet = string.ascii_lowercase[offset:] + string.ascii_lowercase[:offset]
32+
lower_translation_table = maketrans(string.ascii_lowercase, lower_offset_alphabet)
33+
34+
upper_offset_alphabet = string.ascii_uppercase[offset:] + string.ascii_uppercase[:offset]
35+
upper_translation_table = maketrans(string.ascii_uppercase, upper_offset_alphabet)
36+
37+
lower_converted = string_.translate(lower_translation_table)
38+
final_converted = lower_converted.translate(upper_translation_table)
39+
40+
if file_:
41+
extension = 'dec' if decode else 'enc'
42+
with open("{}.{}".format(file_, extension), 'w') as f:
43+
print(final_converted, file=f)
44+
else:
45+
print(final_converted)
46+
47+
48+
def check_offset_range(value: int) -> int:
49+
""" Validates that value is in the allowable range.
50+
51+
:param value: integer to validate
52+
:return: valid integer
53+
:raises: argparse.ArgumentTypeError
54+
"""
55+
value = int(value)
56+
if value < -25 or value > 25:
57+
raise argparse.ArgumentTypeError("{} is an invalid offset".format(value))
58+
return value
59+
60+
61+
if __name__ == '__main__':
62+
parser = argparse.ArgumentParser(description="Simple Caeser Cipher [En,De]coder")
63+
64+
parser.add_argument('-d', '--decode', action='store_true', dest='decode',
65+
help='decode ciphertext (offset should equal what was used to encode)', default=False)
66+
parser.add_argument('-o', '--offset', dest='offset', default=13, type=check_offset_range,
67+
help='number of characters to shift')
68+
69+
group = parser.add_mutually_exclusive_group(required=True)
70+
group.add_argument('-f', '--file', dest='file', help='file to encode', default=None)
71+
group.add_argument('-s', '--string', dest='string', help='string to encode', default=None)
72+
73+
args = parser.parse_args()
74+
75+
caeser_cipher(args.string, args.offset, args.decode, args.file)

0 commit comments

Comments
 (0)