I recently discovered the cryptopals crypto challenges by nccgroup. I’ll be recording my solutions here.

set1

import sys
from Crypto.Cipher import AES

def tobits(s):
result = []
for c in s:
bits = bin(ord(c))[2:]
bits = '00000000'[len(bits):] + bits
result.extend([int(b) for b in bits])
return result

# ----------------------------------

def hexTo64(hex):
return HEX.decode('hex').encode('base64')

def fixedXOR(buf1, buf2):
x = buf1.decode('hex')
y = buf2.decode('hex')
return "".join(chr(ord(a) ^ ord(b)) for a, b in zip(x, y))

#challenge2string1 = '1c0111001f010100061a024b53535009181c'
#challenge2string2 = '686974207468652062756c6c277320657965'
#print fixedXOR(hex1, hex2).encode('hex')

def singleByteXOR(input, key):
output = ""
for i in input:
output += chr(ord(i) ^ ord(key))
return output

# challenge2 end

frequency = {
' ': 20,
'e': 12.02,
't': 9.10,
'a': 8.12,
'o': 7.68,
'i': 7.31,
'n': 6.95,
's': 6.28,
'r': 6.02,
'h': 5.92,
'd': 4.32,
'l': 3.98,
'u': 2.88,
'c': 2.71,
'm': 2.61,
'f': 2.30,
'y': 2.11,
'w': 2.09,
'g': 2.03,
'p': 1.82,
'b': 1.49,
'v': 1.11,
'k': 0.69,
'x': 0.17,
'q': 0.11,
'j': 0.10,
'z': 0.07
}

class Result:
def **init**(self, score, key, result):
self.score = score
self.key = key
self.result = result

    def __eq__(self, other):
    	return self.result == other.result

    def __lt__(self, other):
    	return self.score < other.score

    def printObject(self):
    	print('Key: ' + self.key + " Score: " + str(self.score) + " Phrase: " + str(self.result) + "\n")

    def __iter__(self):
    	return self

def frequencyInEnglish(char):
return frequency.get(char.lower(), 0)

def smartSingleByteXOR(input):
arr = []
options='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 +-:;'
for key in options:
score = 0
result = singleByteXOR(input, key)
for char in result:
if True: # ((ord(char) in range(97,122)) or (ord(char) in range(64i,90) or (ord(char) == 32))):
score += frequencyInEnglish(char)
arr.append(Result(int(100\*(float(score)/float(len(result)))), key, result)) # Return sorted list
arr.sort()
return arr

challengeThreeString='1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736'.decode('hex')
#for ans in smartSingleByteXOR(challengeThreeString):

# ans.printObject()

#print smartSingleByteXOR(challengeThreeString)[-1].printObject()

# challenge 3 end

def detectSingleCharacterXOR(largeFile):
bestCandidates = []
lines = []
with open(largeFile) as f:
lines = f.readlines()
lines = map(lambda x: x.decode('hex'), map(lambda x: x.split('\n')[0], lines))

# print lines

    for l in lines:
    	bestCandidates.append(smartSingleByteXOR(l)[-1])

    bestCandidates.sort()
    return bestCandidates

# for ans in detectSingleCharacterXOR('4.txt'):

# ans.printObject()

# challenge 4 end

# challenge 5 start

c5input = '''Burning 'em, if you ain't quick and nimble
I go crazy when I hear a cymbal'''

c5output = '0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f'

def repeatedXOR(inputText, key):
output = ""
modValue = len(key)
for i in range(0,len(inputText)):
output += chr(ord(inputText[i]) ^ ord(key[i % modValue]))

    return output

#print repeatedXOR(c5input, 'ICE').encode('hex')
#print repeatedXOR(c5output.decode('hex'), 'ICE')

# challenge 5 done

# challenge 6 start

c6example1 = 'this is a test'
c6example2 = 'wokka wokka!!!'

def editDistance(str1, str2):
total = 0
b1 = tobits(str1)
b2 = tobits(str2)
for a,b in zip(b1, b2):
if a != b:
total += 1
return total

# print editDistance(c6example1, c6example2)

def theThreeMostLikelyKeySizes(input):
distances = []
for KEYSIZE in range(2,40):
first = input[ : KEYSIZE]
second = input[KEYSIZE : KEYSIZE * 2]
third = input[KEYSIZE * 2 : KEYSIZE * 3]
fourth = input[KEYSIZE * 3 : KEYSIZE * 4]
normalized = float(editDistance(first, second) + editDistance(second, third) + editDistance(third,fourth)) / (KEYSIZE \* 3)
distances.append((KEYSIZE, normalized))
return map(lambda x: x[0], sorted(distances, key=lambda tup:tup[1])[:3])

fileSix = ''
with open('6.txt', 'r') as myfile:
fileSix=myfile.read().replace('\n', '').decode('base64')

#print theThreeMostLikelyKeySizes(fileSix)

alphabetTestInput = 'abcdefghijklmnopqrstuvwxyz'

def breakIntoBlocksOfSizeN(theFile, n):
output = []
for i in range(0, len(theFile)+1, n):
#print "from: " + str(i) + " to: " + str(i+n-1) + "\n"
output.append(theFile[i:i+n])
return output

#testBrokenBlocks = breakIntoBlocksOfSizeN(fileSix, 29)
#print testBrokenBlocks

def transposeBlocks(blocks, n): # Create array of empty strings, one for each tranposed string
output = [''] \* n # Start sifting bits from each block into correct string
for b in blocks:
for whichBucket in range(0,len(b)):
#print "len is: " + str(len(b))
output[whichBucket] += b[whichBucket]
return output

#print transposeBlocks(testBrokenBlocks, 29)

def breakRepeatKeyXOR(input, keySizes):
finalArr=[]
for KEYSIZE in keySizes:
finalString = ""
transposed = transposeBlocks(breakIntoBlocksOfSizeN(input, KEYSIZE), KEYSIZE)
for t in transposed:
finalString += smartSingleByteXOR(t)[-1].key
finalArr.append(finalString)

    return finalArr

#keys = breakRepeatKeyXOR(fileSix,theThreeMostLikelyKeySizes(fileSix))
#print keys
#print repeatedXOR(fileSix, keys[2])

# END 6

# START 7

with open('7.txt', 'r') as myfile:
fileSeven=myfile.read().replace('\n', '').decode('base64')

sevenKey = b'YELLOW SUBMARINE'
aesKey = AES.new(sevenKey, AES.MODE_ECB)
#print aesKey.decrypt(fileSeven)

# END 7

# START 8

fileEightArray = []
with open('8.txt', 'r') as myfile:
fileEight=myfile.read()
fileEight = fileEight.split('\n')
fileEightArray = map(lambda x: x.decode('hex'), fileEight)

#print fileEightArray

## Detect whether ANY blocks of 16 bytes

def howManyUniqueBlocks(arr):
frequencies = []
for item in arr:
frequency = {}
splitByBytes = [item[i:i+16] for i in range(0, len(item), 16)]
for bytes in splitByBytes:
if bytes in frequency:
frequency[bytes] += 1
print item.encode('hex') # FOR THIS CHALLENGE, the only # sequence of bytes > 1 is the answer!!
else:
frequency[bytes] = 1 # Could do further analysis here, but we print the answer above.

#data = ['\x00\x00\x00\x00\x00\x00', '\x00\x00\x00\x00\x00\x00']
howManyUniqueBlocks(fileEightArray)

# d880619740a8a19b7840a8a31c810a3d08649af70dc06f4fd5d2d69c744cd283e2dd0

# 52f6b641dbf9d11b0348542bb5708649af70dc06f4fd5d2d69c744cd2839475c9dfdbc1d46

# 597949d9c7e82bf5a08649af70dc06f4fd5d2d69c744cd28397a93eab8d6aecd56648915478

# 9a6b0308649af70dc06f4fd5d2d69c744cd283d403180c98c8f6db1f2a3f9c4040deb0ab51b29

# 933f2c123c58386b06fba186a

## set 1 end

to be continued....

```