Rot 13 SimpleExplanation

How to use ROT13 in Python? Simply Explained

ROT13 is a simple encryption method. It shifts each character of the clear text string 13 positions forward in the alphabet.

This Python one-liner does ROT13 encryption for you:

cleartxt = "berlin"
abc = "abcdefghijklmnopqrstuvwxyz"
secret = "".join([abc[(abc.find(c)+13)%26] for c in cleartxt])
print(secret)
# oreyva

Note: cleartxt is the string we want to encode and must not contain spaces, numbers or upper case letters.

Don’t worry if this seems confusing. We’ll explain it all in detail below!

To encode strings containing spaces and upper case letters, use the built-in codecs library.

As an alternative, you can also use the following Python library call — that does ROT13 encryption for you:

import codecs
codecs.encode(phrase, 'rot_13')

(Reading time — 12 minutes, or watch the video!)

ROT13 Video Tutorial

If you already learned something from this tutorial, why not joining my free Python training program? I call it the Finxter Email Computer Science Academy—and it’s just that: a free, easy-to-use email academy that teaches you Python in small daily doses for beginners and pros alike!

Learn Python and join the Free Finxter Email Computer Science Academy. It’s fun!

But before we move on, I’m excited to present you my brand-new Python book Python One-Liners (Amazon Link).

If you like one-liners, you’ll LOVE the book. It’ll teach you everything there is to know about a single line of Python code. But it’s also an introduction to computer science, data science, machine learning, and algorithms. The universe in a single line of Python!

The book is released in 2020 with the world-class programming book publisher NoStarch Press (San Francisco).

Now, let’s answer an important technical question:

What is ROT13?

The ROT13 algorithm is a simple encryption algorithm. It is used on many forums (e.g. Reddit) to prevent spoilers – or to hide the details of a conversation from newbies.

ROT13 is so simple that it provides almost no security. But if you understand it, you’ll finally be able to decipher those insider conversations on Reddit.

The algorithm can be explained in one sentence. ROT13 = Rotate the string to be encrypted by 13 positions (modulo 26) in the alphabet of 26 characters.

abcdefghijklm
nopqrstuvwxyz

If you want to encrypt a string, shift each character forwards by 13 positions in the alphabet. If you move past the last character “z”, you start over at the first position in the alphabet “a”.

What Are ROT13 Implementations in Python?

First, I’ll give you an easy-to-understand implementation of the ROT13 algorithm. Then, I’ll provide you with a Python one-liner. Finally, I’ll give you the library call for ROT13 encryption. Use the version you prefer.

So check out this ROT13 algorithm without using libraries. Read the code carefully, because I will ask you a question about it in a moment.

def rot13(phrase):
   abc = "abcdefghijklmnopqrstuvwxyz"
   out_phrase = ""

   for char in phrase:
       out_phrase += abc[(abc.find(char)+13)%26]
   return out_phrase


phrase = "xthexrussiansxarexcoming"

print(rot13(phrase))
# kgurkehffvnafknerkpbzvat

print(rot13(rot13(phrase)))
# What's the output?

The last print statement showcases a nice property of the algorithm. But which one?

The solution is the output "thexrussiansxarexcoming". This is because rot13 is its own inverse function (shifting by 13+13 positions brings you back to the original character in the alphabet).

An advanced coder will always prefer the shortest and cleanest way of writing Pythonic code. So, let’s rewrite the ROT13 algorithm as a Python one-liner.

abc = "abcdefghijklmnopqrstuvwxyz"


def rt13(x):
   return "".join([abc[(abc.find(c) + 13) % 26] for c in x])


print(rt13(rt13(phrase)))

We create a list of encrypted characters via a list comprehension. If you need a refresher on list comprehension, check out our comprehensive blog tutorial.

We then join this list together with the empty string to get the final result. In the list comprehension, each character, c, from the original string, x, is encrypted separately. For each c, we find its position in the alphabet with abc.find(c). Then we add 13 to this position. So 'z' returns index 25 and 25 + 13 = 38. But there is no 38th letter. Thus we use the modulo operator (% 26) to make sure our values are in the range 0 – 25 (Python indexes start at 0).

To encrypt character ‘z’, the algorithm shifts its index 25 by 13 index positions to the right. It takes the result modulo 26 to get the final index of the encrypted character. This prevents overshooting by restarting the shift operation at index 0. It results in the following shift sequence: 25 > 0 > 1 > … > 12.

Alternative solution: one of my “Coffee Break Python” email subscribers, Thomas, came up with an alternative solution that is fast and easy to read.

def rot13(phrase):
    key = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    val = "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM"
    transform = dict(zip(key, val))
    return ''.join(transform.get(char, char) for char in phrase)

The idea is to “hardcode” the mapping between keys and values. This is quite “tedious” programming work. But it’s a perfectly valid solution to the ROT13 algorithm (and it works for uppercase letters, spaces, numbers and symbols too!).

Note that it does not encode non-letter characters. It simply returns them:

>>> rot13('Hello World!!')
'Uryyb Jbeyq!!' 

Is There a Library for ROT13 in Python?

Yes! It’s a built-in library called codecs. Using the ROT13 algorithm with the library is simple. Just import the library and call the encode function.

Here is an example:

import codecs

phrase = "The Russians are coming!"

# Apply twice to get back original string
print(codecs.encode(codecs.encode(phrase, 'rot_13'), 'rot_13'))
# The Russians are coming!

print(codecs.encode('hello', 'rot_13'))
# uryyb

The encode function from the codecs library takes up to three parameters. The first parameter is the string object to encode. The second parameter is the encoding scheme (default: ‘utf-8’). The third parameter allows you to customize error handling. In most cases, you can skip the last parameter and use the default error handling.

What Are the Applications of the ROT13 Algorithm?

The ROT13 algorithm is easy to decrypt. An attacker can easily crack your code by running a probabilistic analysis on the distribution of the letters in your encrypted text. You should never rely on this algorithm to encrypt your messages!

So, what are the applications of the ROT13 algorithm?

  •    Obscure potentially offensive jokes in online forums.
  •    Obscure the result of puzzles in online forums.
  •    Obscure possible spoilers for movies or books.
  •    Make fun of existing (weak) encryption algorithms: “56-bit DES is stronger than ROT13”
  •    Obscure email addresses on websites against not very sophisticated email bots (the 99%).
  •    Use it as a game to find phrases that make sense in both forms, encrypted or decrypted. Examples: (png, cat), (be, or).
  •    ROT13 is a special case of the popular Caesar cipher. ROT13 serves as an educational tool to explain it. (Example)

In summary, ROT13 is more a fun encryption method that has been a popular running gag in internet culture.

As a user on StackExchange describes it:

“So a lot of things that did mild obfuscation used ROT13, because it was commonly available, and so it’s been backported into a number of more modern languages. It’s just a weird quirk.”

How is CAPITALIZATION Handled?

The encode function of the codecs library handles capitalization for you. If you apply ROT13 to an uppercase letter, it will remain uppercase after the encoding. If you apply ROT13 to a lowercase letter, it will remain lowercase.

Here is an example:

import codecs

print(codecs.encode('Hello', 'rot_13'))
# Uryyb

How is ROT13 Related to the Caesar Cipher?

The Caesar cipher is the generalization of the ROT13 algorithm. 

“It is a type of substitution cipher in which each letter in the plaintext is replaced by a letter some fixed number of positions down the alphabet.”

Wikipedia

As you can see, ROT13 does nothing but fix the “number of positions down the alphabet” to +13.

Why do we shift the original text, called ‘cleartext’ or ‘plaintext’, by 13 positions and not another number? It ensures that applying the encryption twice returns the original cleartext. Hence, you do not have to define two separate methods for encryption and decryption – one method to rule them all!

This is not the case if you use any other number. If you shift the cleartext by 5 positions, ROT5, and apply it twice, you get ROT10 encryption (5+5=10).

Online Tool for ROT13 Encryption and Decryption

To encrypt your own cleartext, simply replace the string value of the variable ‘clear_text’ with your personal string.

Click to visit the interactive tool to obfuscate your own texts with ROT13.

What Are the Alternatives to ROT13?

Most alternatives are stronger than ROT13. Here are a few of them:

  • Triple DES
  • RSA
  • Blowfish
  • Twofish
  • AES

If you want to dive deeper into these alternatives, check out this article that briefly describes their ideas.

What Are Examples of ROT13?

Here are examples from various sources on the web. I‘ve chosen ones where the ROT13 encryption produces some kind of English word.

  • aha ↔ nun
  • ant ↔ nag
  • balk ↔ onyx
  • bar ↔ one
  • barf ↔ ones
  • be ↔ or
  • bin ↔ ova
  • ebbs ↔ roof
  • envy ↔ rail
  • er ↔ re
  • errs ↔ reef
  • flap ↔ sync
  • fur ↔ she
  • gel ↔ try
  • gnat ↔ tang
  • irk ↔ vex
  • clerk ↔ pyrex
  • purely ↔ cheryl
  • PNG ↔ cat
  • SHA ↔ fun
  • furby ↔ sheol
  • terra ↔ green
  • what ↔ Jung
  • URL ↔ hey
  • purpura ↔ Chechen
  • shone ↔ FUBAR
  • Ares ↔ Nerf
  • abjurer ↔ nowhere

Write a ROT13 Encoder Decoder in Python

Since we’re programmers we want to automate everything. I don’t want to open Python every time I see something encoded in ROT13 and have to write a function. It would be great if we could apply ROT13 encryption/decryption from the command line!

Let’s create a script, rot13.py, to run whenever we find some text in ROT13. We want the final command to look like this

$ python rot13.py 'text to encode/decode'

So we need to 

  1. Create the script rot13.py
  2. Pass command line arguments to our script

Thankfully, the built-in sys module lets us access command line arguments. The object sys.argv is a list containing all arguments passed to the script.

# sys_file.py
import sys

print(f'sys.argv is: {sys.argv}')

for arg_index in range(len(sys.argv)):
    print(f'Argument #{arg_index} is: {sys.argv[arg_index]}')

Let’s run this from the command line and pass it some arguments

# Pass 3 arguments to sys_file.py
$ python sys_file.py hello goodbye come_back
sys.argv is: ['some_file.py', 'hello', 'goodbye', 'come_back!']
Argument #0 is: some_file.py
Argument #1 is: hello
Argument #2 is: goodbye
Argument #3 is: come_back

The first element of sys.argv is always the name of the script. The other elements are the arguments you passed in the order you passed them. When you access these in your Python script, it is the same as indexing starting from 1. You access the first argument with sys.argv[1].

Note: arguments are separated by spaces. Thus come_back is one argument and come back is two.

Let’s apply this to the ROT13 functions we wrote earlier.

# rot13.py
import sys
from codecs import encode 

# Store 1st argument as a variable
my_text = sys.argv[1]

# Print out encoded version to the screen
print(encode(my_text, 'rot_13'))

We will only pass one argument to this script: a string we want to encode. We store this as a variable my_text and pass it to the encode function from the codecs module.

Save rot13.py in your Home directory. Now whenever you find some text in ROT13, you just need to open a terminal window and can decode it within seconds. Type the following into your terminal window now!

$ python rot13.py 'Lbh ner nznmvat!'

Where to Go From Here?

ROT13 is a simple encryption method. it shifts each character of a string, x, 13 positions forwards in the alphabet.

It offers no encryption, only obfuscation. However, it is a great way to obscure messages in online forums and private communications. ROT13 is a special variant of Caesar’s cipher where the function is its own inverse.

'a' >> (shift by 13 positions) >> 'n' >> (shift by 13 positions) >> 'a'

Do you want to improve your Python skills to the point where every software company would love to hire you because you belong to the top coders? Check out the Coffee Break Python book series! It’s a fun way of accelerating your Python coding skills in a very engaging manner. (And we just reached LeanPub bestseller status in the category Python!)