Violent Python: XOR Encryption

What You Need

A Kali Linux machine, real or virtual. You could also use OS X, or Windows with Python installed.

Purpose

Encrypt and decrypt files using XOR in Python.

Understanding XOR

Exclusive OR (XOR) is a fundamental mathematical operation used in many encryption algorithms.

XOR operates on one bit at a time, with these results:

0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0
For our purposes, we'll use the Python ^ operator, which acts on a whole byte at a time.

Characters are ASCII-encoded, like this:

A is 01000001
B is 01000010
C is 01000011
...
A whole table of ASCII values is here:

http://www.asciitable.com/

Consider A^B:

A is 01000001
B is 01000010
A^B= 00000011
That is character 3, an unprintable end-of-text mark.

However, A^s is printable:

A is 01000001
s is 01110011
A^s= 00110010
The result is the hexadecimal value 0x32, or the numeral 2.

XOR in Python

In Kali Linux, in a Terminal window, execute this command:
nano xor1
In nano, enter the code shown below:
#!/usr/bin/python

import sys

if len(sys.argv) != 4:
  print "Usage: ./xor1 infile outfile k"
  print "k is a one-character XOR key"
  print "For hexadecimal keys, use $'\\x01'"
  exit()

f = open(str(sys.argv[1]), "rb")
g = open(str(sys.argv[2]), "a")
k = ord(sys.argv[3])

try:
    byte = f.read(1)
    while byte != "":
        xbyte = ord(byte) ^ k
        g.write(chr(xbyte))
        byte = f.read(1)
finally:
    f.close()

g.close()

Save the file with Ctrl+X, Y, Enter.

Troubleshooting

If you are using Windows, it's difficult to enter a non-ASCII key, and it also adds carriage return characters after line feeds when writing, so use this code instead:
#!/usr/bin/python

import sys

if len(sys.argv) != 4:
  print "Usage: ./xor1 infile outfile keynum"
  print "k is a number in base 10"
  exit()

f = open(str(sys.argv[1]), "rb")
g = open(str(sys.argv[2]), "ab")
k = int(sys.argv[3])

out = ""
try:
    byte = f.read(1)
    while byte != "":
        xbyte = ord(byte) ^ k
        out += chr(xbyte)
        byte = f.read(1)
finally:
    f.close()

g.write(out)
g.close()
Next, we need to make the file executable.

In a Terminal window, execute this command:

chmod a+x xor1

Encrypting a Single Character

In a Terminal window, execute this command:
./xor1
You see the help message, explaining how to use the program, as shown below.

To create a file named plain1 with the letter A in it, execute these commands :

echo -n A > plain1

cat plain1
The "echo -n" command created a file named plain1 which contains a single letter A, without a carriage return at the end of the file.

The "cat plain1" command printed out the file, which appeared as a single A at the start of the next line, as shown below:

To encode the plain1 file with a key of s, execute these commands:

./xor1 plain1 cipher1 s

cat cipher1
The result is 2, as shown below:

Encrypting a Text File

In Kali Linux, in a Terminal window, execute this command:
nano plain2
In nano, enter the code shown below, replacing "YOUR NAME" with your own name:
Normal English text; written by YOUR NAME

Save the file with Ctrl+X, Y, Enter. To encrypt the file using a key of x, execute these commands:

./xor1 plain2 cipher2 x

cat cipher2
The result is strange unreadable characters, as shown below:

Decrypting a Text File

To decrypt a file, simply repeat the XOR operation with the same key. It will reverse itself.

Execute these commands:

./xor1 cipher2 plain2r x

cat plain2r
The file is restored to readable text, as shown below:


Challenge 1: Decrypting a Text File Without the Key (10)

This one is pretty simple: the key is a capital letter, from A to Z.

To get the ciphertext, execute this command:

curl https://samsclass.info/124/proj14/xorchal1-cipher > xorchal1-cipher
Windows users: right-click on this link and "Save As":

https://samsclass.info/124/proj14/xorchal1-cipher

Decrypt the file to find the message. Then use the form below to get your name onto the Winners Page.

Your Name:
Message:

Challenge 2: Decrypting a Text File Without the Key (10 pts. extra credit)

The key is a single byte from \x00 to \xff.

To get the ciphertext, execute this command:

curl https://samsclass.info/124/proj14/xorchal2-cipher > xorchal2-cipher
Windows users: right-click on this link and "Save As":

https://samsclass.info/124/proj14/xorchal2-cipher

Decrypt the file to find the message. Then use the form below to get your name onto the Winners Page.

Your Name:
Message:

Challenge 3: Decrypting an Image File Without the Key (10 pts. extra credit)

The key is a single byte from \x00 to \xff.

To get the ciphertext, execute this command:

curl https://samsclass.info/124/proj14/xorchal3-cipher > xorchal3-cipher
Windows users: right-click on this link and "Save As":

https://samsclass.info/124/proj14/xorchal3-cipher

This is an image file. When decrypted, it starts with a PNG file header, as shown below:

Notice that the first 4 bytes are 89, 50, 4E, 47; the 2nd through 4th byte spell out PNG in ASCII.

Decrypt the file. When you get it, change its filename extension to PNG and open it in an image viewer or Web browser.

Read the message written inside the image. Use the form below to get your name onto the Winners Page.

Your Name:
Message:

Challenge 4: Decrypting an Image File Without the Key (10 pts. extra credit)

The key is two bytes from \x0000 to \xffff.

To get the ciphertext, execute this command:

curl https://samsclass.info/124/proj14/xorchal4-cipher > xorchal4-cipher
Windows users: right-click on this link and "Save As":

https://samsclass.info/124/proj14/xorchal4-cipher

This is an image file. When decrypted, it starts with a JPEG file header, as shown below:

Notice that the first 2 bytes are FFD8, and some later bytes contain the ASCII characters JFIF.

Decrypt the file. When you get it, change its filename extension to JPG and open it in an image viewer or Web browser.

Use the form below to get your name onto the Winners Page.

Your Name:
Key Bytes in decimal:    


6-2-18: Windows version added
6-19-18 "A^s" typo fixed 6-19-18
Updated to Arial and HTTPS 10-20-18