Reputation: 1503
I have files encrypted by the code below using a 1 byte key and XOR encryption.
blocksize=256
while (args.secretkey.tell() < blocksize):
generates once?
sys.stdout.write('.')
args.secretkey.write(os.urandom(1))
counter=0
args.secretkey.seek(0)
keydata = args.secretkey.read(blocksize)
while 1:
byte = args.infile.read(1)
if not byte:
break
args.outfile.write(chr(ord(keydata[counter % len(keydata)]) ^ ord(byte)))
counter+=1
How do I find the correct key to decrypt the files? Must I go through 256 combinations to get the correct key?
Upvotes: 0
Views: 1853
Reputation: 50218
To reverse the encryption, you need the 256 byte random key. But if you've lost it, xor encryption is so weak that if you know something about some of your encrypted files, you can reverse-engineer it with a bit of patience.
For exposition, let's assume that you have several files that you know to contain English text; the same principles apply to many other types of content, though. Ideally, you need a few hundred blocks of predictable text.
First, note that the same "secret" byte is used to encode every 256'th byte; so you can collect a good bunch of bytes, from different text files, that were xor'ed with the same key byte (e.g., byte 0 of your key).
You can now count the frequencies of the encoded bytes and match them against a frequency table for English text.
Let's say the most frequent byte is 0xAB
; well, in English text the most frequent byte is space (0x20
); it's almost twice as frequent as the next most common byte (e
), so it's hard to go wrong if you're looking at text files. So, just solve the little equation 0x20 ^ x = 0xAB
. Congrats, you've recovered one byte from your lost key. Repeat another 255 times.
If somehow you compute a byte wrong, don't worry; once you have the entire key, errors in the decoded text will be obvious and you'll be able to go back and fix the corresponding key byte.
Upvotes: 1
Reputation: 9390
Here you have the decoding program (the encoding is a xor against the random generated data, so the decoding is to do the same xor):
#!/usr/bin/python
import os
import sys
import argparse
blocksize=256
parser = argparse.ArgumentParser(description="Custom encryption algorithm because a friend said that's the way to do it. Anyway, it's called 'Only This Program' since I'm pretty sure that only this program can securely decrypt the files as long as you don't give out your secret.dat file created when you encrypt something.")
parser.add_argument('--infile', metavar='i', nargs='?', type=argparse.FileType('r'), help='input file, defaults to standard in', default=sys.stdin)
parser.add_argument('--outfile', metavar='o', nargs='?', type=argparse.FileType('wb'), help='output file, defaults to standard out', default=sys.stdout)
parser.add_argument('--secretkey', metavar='s', nargs='?', type=argparse.FileType('r'), help='input file, defaults to secretkey.dat', default='secretkey.dat')
args = parser.parse_args()
counter=0
args.secretkey.seek(0)
keydata = args.secretkey.read(blocksize)
while 1:
byte = args.infile.read(1)
if not byte:
break
args.outfile.write(chr(ord(keydata[counter % len(keydata)]) ^ ord(byte)))
counter+=1
sys.stderr.write('\nSecret keyfile: %s\nInput file: %s\nOutput file: %s\nTotal bytes: %d \n' % (args.secretkey.name, args.infile.name, args.outfile.name, counter))
Upvotes: 1