Saturday, February 16, 2019

ROT Cipher in Python

Recently I was messing around with some stuff and kept needing a Caesar Cipher deciphered and kept using some not-so-good online ones. So what better thing to do than make one myself. Why even stop at a Caesar Cipher and just make an adjustable ROT tool. So rather than copying one that probably works better and has a nicer design, I made my own.

#!/usr/bin/python3
#
# Made by: Matthew DeSantis
#          www.anarchy46.net

import sys
import os

# Upper case limits
CAP_MIN = ord( 'A' )
CAP_MAX = ord( 'Z' )
# Lower case limits
LOW_MIN = ord( 'a' )
LOW_MAX = ord( 'z' )

# Rotate the characters
def rotate ( offset, c ):
    o = ord( c )
    # Uppercase
    if o >= CAP_MIN and o <= CAP_MAX:
        o = o + offset
        # Loop back to beginning
        if o > CAP_MAX:
            o = o - CAP_MAX + CAP_MIN - 1

        # Loop back to end for backwards
        elif o < CAP_MIN:
            o = CAP_MAX - CAP_MIN + o + 1

    # Lowercase
    elif o >= LOW_MIN and o <= LOW_MAX:
        o = o + offset
        # Loop back to beginning
        if o > LOW_MAX:
            o = o - LOW_MAX + LOW_MIN - 1

        # Loop back to the end
        elif o < LOW_MIN:
            o = LOW_MAX - LOW_MIN + o + 1

    return chr( o )

# Cycle through the string
def cipher ( offset, text ):
    output=''
    for t in text:
        output += rotate( offset, t )
    return output

if __name__ == '__main__':
    try:
        # Max rotation offset
        max_off = CAP_MAX - CAP_MIN + 1
        offset = int( sys.argv[1] )
        # Get the offset from max (like if 27 is in and max is 25, you get 2)
        # Then set positive or negative
        offset = offset and (abs( offset ) - abs( max_off * int( offset / max_off ) )) * (offset / abs( offset )) or offset

        # Text is passed via args
        if len( sys.argv ) > 2:
            text = " ".join( sys.argv[2:] )
            eol = os.linesep

        # Or text is passed via pipe (./rot.py 13 < example.txt)
        elif not sys.stdin.isatty():
            text = "".join( sys.stdin.readlines() )
            eol = ''

        # No text!
        else:
            raise Exception( "Missing text!" )
        print( cipher( int( offset ), text ), end=eol )

    # Not a valid number or the like.
    except ValueError:
        print( "Invalid type." )
        exit( 1 )

    # Catch anything else because oops.
    except Exception as err:
        print( err )
        exit( 1 )


So saving this as rot.py, I can use it for stuff in the terminal:

./rot.py 13 This is a secret message

Or I can use it to decrypt a file:

./rot.py -13 < secret.txt

I tried to make it as flexible as possible. Decryption can be done by using a negative, or you could cipher it negatively, whatever makes you happy. My math for doing the offset is a bit of evil. The idea is to rotate no more than once around while preserving which way around it goes. There are most certainly better ways to do it, but I was feeling "artistic."

No comments:

Post a Comment

Tag Cloud

.NET (2) A+ (5) ad ds (1) addon (4) Android (4) anonymous functions (1) application (9) arduino (1) artificial intelligence (1) backup (1) bash (6) camera (2) certifications (3) comptia (5) css (2) customize (11) encryption (3) error (13) exploit (5) ftp (1) funny (4) gadget (4) games (3) GUI (5) hardware (16) haskell (6) help (14) HTML (3) imaging (2) irc (1) it (1) java (2) javascript (13) jobs (1) Linux (19) lua (1) Mac (4) malware (1) math (6) msp (1) network (13) perl (2) php (3) plugin (2) powershell (8) privacy (2) programming (24) python (10) radio (2) regex (3) repair (2) security (16) sound (2) speakers (2) ssh (1) story (5) Techs from the Crypt (5) telnet (1) tools (13) troubleshooting (11) tutorial (9) Ubuntu (4) Unix (2) virtualization (2) web design (6) Windows (16) world of warcraft (1) wow (1) wx (1)