{{announcement.body}}
{{announcement.title}}

# Alphanumeric Shifting Made Easy With Python

DZone 's Guide to

# Alphanumeric Shifting Made Easy With Python

### Thanks to a couple of built-in functions, this dev was able to use Python to easily solve an otherwise rather complex puzzle. Read on to see how!

· Web Dev Zone ·
Free Resource

Comment (0)

Save
{{ articles.views | formatCount}} Views

During my first CTF(Capture the Flag) competition I noticed that some challenges required a character shifting in order to discover the real value of a string. I spent a few minutes on those challenges trying to figure out a pattern that could be applied to “unmask” the given content.

### Challenge 1

After gathering information about the given IP address, a file was found with the following content:

``rxms{DqhqdeqpRxms}``

It looks completely random, but given the fact that the flags had a pattern of: “flag{some-hash-here}”, we could try a character shifting:

``````rxms{DqhqdeqpRxms}
synt
tzou
uapv
vbqw
wcrx
xdsy
yetz
zfua
agvb
bhwc
cixd
djye
ekzf
flag{...} <- real content``````

We had to jump 12 positions in the alphabet to get the real content of the string.

### Challenge 2

In order to connect to a service we had to solve a pass-phrase code:

``AQW UJCNN PQV RCUU``

At first glance, the pass-phrase code looks like a Caesar’s Cipher. Solving this challenge also required character shifting, but this time, backward:

``````AQW UJCNN PQV RCUU
ZPV TIBMM OPU QBTT
YOU SHALL NOT PASS <- backward content``````

### Python to the Rescue

Python has the built-in functions ord() and chr() that can help us to accomplish this task:

``````class Alphanumeric(object):

ALPHABET_LENGTH = 26

def __init__(self, nrange=None):
self.current_letter = 'z'
self.current_number = 0
self.nrange = nrange

def forward_letter(self, letter, positions):
if letter.islower():
unicode_point = ord('a')
else:
unicode_point = ord('A')

start = ord(letter) - unicode_point
offset = ((start + positions) % self.ALPHABET_LENGTH) + unicode_point
self.current_letter = chr(offset)
return self.current_letter

def backward_letter(self, letter, positions):
if letter.islower():
unicode_point = ord('a')
else:
unicode_point = ord('A')

start = ord(letter) - unicode_point
offset = ((start - positions) % self.ALPHABET_LENGTH) + unicode_point
self.current_letter = chr(offset)
return self.current_letter

def next_letter(self):
return self.forward_letter(self.current_letter, 1)

def previous_letter(self):
return self.backward_letter(self.current_letter, 1)

def forward_number(self, number, positions):
if not self.nrange:
self.current_number = number + positions
return self.current_number

index = self.nrange.index(number)
start = index + positions
offset = (start % len(self.nrange))
self.current_number = self.nrange[offset]
return self.current_number

def backward_number(self, number, positions):
if not self.nrange:
return number - positions

index = self.nrange.index(number)
start = index - positions
offset = (start % len(self.nrange))
self.current_number = self.nrange[offset]
return self.current_number

def next_number(self):
return self.forward_number(self.current_number, 1)

def previous_number(self):
return self.backward_number(self.current_number, 1)

def forward_alphanumeric(self, alpha, positions, ignore_numbers=False, ignore_letters=False):
result = ""
for char in alpha:
if char.isdigit() and not ignore_numbers:
char = str(self.forward_number(int(char), positions))

if char.isalpha() and not ignore_letters:
char = self.forward_letter(char, positions)

result += char

return result

def backward_alphanumeric(self, alpha, positions, ignore_numbers=False, ignore_letters=False):
result = ""
for char in alpha:
if char.isdigit() and not ignore_numbers:
char = str(self.backward_number(int(char), positions))

if char.isalpha() and not ignore_letters:
char = self.backward_letter(char, positions)

result += char

return result``````

Using the Alphanumeric class:

``````alpha = Alphanumeric()
print alpha.forward_alphanumeric('abc123', 1)
print alpha.backward_alphanumeric('abc123', 1)

// prints: bcd234
// prints: zab012``````

Note that you can define a range of numbers to perform a “cyclic loop” when shifting numbers:

``````alpha = Alphanumeric([1, 2, 3, 4 , 5])
print alpha.forward_alphanumeric('123', 6)

// prints: 234``````

### A CLI Tool to the Rescue

Thinking about the next CTF’s challenges I wrote a small CLI tool called shift that makes it easier to shift alphanumeric characters.

``````echo "Dqhqdeqp Oazfqzf" | python shift.py -p 12 --backwards
// prints: "Reversed Content"

python shift.py abc123 -p 5
// prints: "fgh678"``````

You can see the documentation and the source code as well on GitHub.

Topics:
python ,web dev ,python functions

Comment (0)

Save
{{ articles.views | formatCount}} Views

Opinions expressed by DZone contributors are their own.