def HMAC(key, message, hashFunction): keyLen = len(key) if hashFunction == "SHA1": hash = hash_sha1 blockSize = 64 outputSize = 20 elif hashFunction == "MD4": hash = hash_md4 blockSize = 64 outputSize = 16 elif not hashFunction == "MD4" and not hashFunction == "SHA1": raise Exception("Hash Function not supported") if keyLen > blockSize: key = hash(key).decode("hex") if (keyLen < blockSize): key = key + "00".decode("hex")*(blockSize-keyLen) o_key_pad = fixedXOR(key.encode('hex'), ("5c" * blockSize)).decode("hex") i_key_pad = fixedXOR(key.encode("hex"), ("36" * blockSize)).decode("hex") return hash(o_key_pad + hash(i_key_pad + message).decode("hex"))
def findBlockByPadding(padLen, randomBlock, cipherBlock, IV, blockSize=16): foundBlock = '' paddedRandomHits = randomBlock[(-1) * (padLen * 2):] maskForHits = (hex(padLen)[2:].zfill(2)) * (len(paddedRandomHits) / 2) foundBlock = fixedXOR(paddedRandomHits, maskForHits) for k in range(blockSize - padLen): maskOne = (hex(0)[2:].zfill(2)) * (blockSize - padLen) + ( hex(padLen)[2:].zfill(2)) * (padLen) maskTwo = (hex(0)[2:].zfill(2)) * (blockSize - padLen) + ( hex(padLen + 1)[2:].zfill(2)) * (padLen) padLen += 1 randomBlock = fixedXOR(randomBlock, maskOne) randomBlock = fixedXOR(randomBlock, maskTwo) for j in range(256): randomBlock = randomBlock[:(blockSize - padLen) * 2] + hex( j)[2:].zfill(2) + randomBlock[2 * (blockSize - padLen + 1):] if paddingOracle(randomBlock + cipherBlock, IV): foundBlock = fixedXOR( hex(j)[2:].zfill(2), hex(padLen)[2:].zfill(2)) + foundBlock break return foundBlock
def decrypt(self, cipherText): blocks = [ cipherText[i:i + AES.block_size] for i in range(0, len(cipherText), AES.block_size) ] message = b"" message += fixedXOR(self.ecb.decrypt(blocks[0]), self.iv) for i in range(1, len(blocks)): tmp = self.ecb.decrypt(blocks[i]) message += fixedXOR(blocks[i - 1], tmp) return pkcs7Strip(message, AES.block_size)
def crackCBC(blockSize=16): randomBlock = os.urandom(blockSize).encode("hex") cipherText, IV = encryptionOracle() cipherLen = len(cipherText) crackedText = '' foundBlock = '' previousBlock = IV for i in range(0, cipherLen, blockSize * 2): cipherBlock = cipherText[i:i + (blockSize * 2)] for j in range(256): newRandomBlock = randomBlock[:-2] + hex(j)[2:].zfill(2) if paddingOracle(newRandomBlock + cipherBlock, IV): padLen = findPaddingLength(newRandomBlock, cipherBlock, IV) foundBlock = findBlockByPadding(padLen, newRandomBlock, cipherBlock, IV) crackedText += fixedXOR(foundBlock, previousBlock).decode("hex") previousBlock = cipherBlock else: pass print crackedText
def encodeRepeatingXOR(key, message): keyIterator = 0 result = b'' for byte in message: result += fixedXOR.fixedXOR(bytes([byte]), bytes([key[keyIterator]])) keyIterator = (keyIterator + 1) % len(key) return result
def crackSingleXOR(cipherText, retUnit=True, retScore=False): cipherLen = len(cipherText) bruteKey = '' finalKey = '' score = 0.00 maxScore = 0.00 for i in range(256): bruteKey = '' while len(bruteKey) != cipherLen: bruteKey += hex(i)[2:].zfill(2).rstrip("L") score = scoreText(fixedXOR(bruteKey, cipherText).decode("hex")) if (score > maxScore): maxScore = score finalKey = bruteKey if retUnit and (not retScore): return finalKey[:2] elif (not retUnit) and retScore: return maxScore elif retUnit and retScore: return finalKey[:2], maxScore else: return finalKey
def makeAdmin(): blockSize = findBlockSize() inputText = "Z" * blockSize adminText = ";admin=true;f=k;" attaxText = fixedXOR(adminText.encode("hex"), inputText.encode("hex")) cipherText = encryptionOracle(inputText * 2) cipherLen = len(cipherText) for i in range(cipherLen / (blockSize * 2) - 2): maskText = blockSize * i * 2 * "0" + attaxText + ( cipherLen - (blockSize * 2) - (blockSize * i * 2)) * "0" forgedText = fixedXOR(maskText, cipherText) if checkAdminOracle(forgedText): print "Hacked Through AES CBC mode" break
def getScoreFromBruteForceXOR(inData): maxScore = 0 res = "" for x in range(0, 256): xorToTry = str(x) * len(inData) transformedData = fixedXOR(inData, xorToTry).decode("hex") if score(transformedData) > maxScore: maxScore = score(transformedData) res = transformedData return maxScore
def decrypt(key, cipher): if len(key) > 16: raise Exception("key greater than 16 bits") keyStream = '' cipherLen = len(cipher) seed = int(key,2) mt = MT19937(seed) for i in range(cipherLen/8 + 1): keyStream += hex(mt.temper())[2:].zfill(8).rstrip('L') keyLen = len(keyStream) diffBytes = (keyLen - cipherLen) if diffBytes > 0: tempKeyStream = keyStream[:(-1)*diffBytes] return fixedXOR(tempKeyStream, cipher) else: return fixedXOR(keyStream, cipher)
def encrypt(key, message): if len(key) > 16: raise Exception("key greater than 16 bits") keyStream = '' message = message.encode("hex") msgLen = len(message) seed = int(key,2) mt = MT19937(seed) for i in range(msgLen/8 + 3): keyStream += hex(mt.temper())[2:].zfill(8).rstrip('L') keyLen = len(keyStream) diffBytes = (keyLen - msgLen) if diffBytes > 0: tempKeyStream = keyStream[:(-1)*diffBytes] return fixedXOR(tempKeyStream, message) else: return fixedXOR(keyStream, message)
def hammingDistance(hexString1, hexString2): XORed = fixedXOR(hexString1, hexString2) XORed = bin(int(XORed, 16))[2:] count = 0.00 for bit in XORed: if bit == '1': count += 1 return count
def encrypt(self, message): message = pkcs7Pad(message, AES.block_size) blocks = [ message[i:i + AES.block_size] for i in range(0, len(message), AES.block_size) ] cipherText = b"" prevCipher = self.iv for block in blocks: block = fixedXOR(block, prevCipher) prevCipher = self.ecb.encrypt(block) cipherText += prevCipher return cipherText
def repeatKeyXOR(key, text): keyLen = len(key) textLen = len(text) repeatKey = '' i = 0 while (textLen - (i * keyLen)) >= keyLen: repeatKey += key i += 1 if textLen % keyLen != 0: repeatKey += key[:(textLen % keyLen)] return fixedXOR(repeatKey, text)
def breakSingleByteXOR(cipherText): maxScore = 0 plainText = "" key = 0 for i in range(256): likelyKey = i likelyText = fixedXOR.fixedXOR( cipherText, b''.join( [ bytes([likelyKey]) ] * len(cipherText) ) ) score = scoreText(likelyText) if maxScore < score: plainText = likelyText maxScore = score key = chr(likelyKey) # print(f"Cipher Text: {cipherText}\nPlain Text: {plainText}\n") return [plainText, key]
def singleByteXOR(a): length = len(a) letters = [x for x in string.ascii_letters] freq_of_letters = [] for key in letters: # or can reuse the old pgm, much cleaner :) # encode the key and expand it to the length # of the string new_key2 = key.encode('hex') * length c = fixedXOR(a, new_key2)\ .decode('hex') freq_of_letters.append(calculateFrequency(c, new_key2)) # find the decoded string that is most similar to english max_match = max(freq_of_letters) return letters[freq_of_letters.index(max_match)]
def AESCBCencrypt(key, hexString, IV): hexLen = len(hexString) blockSize = 32 previousMsg = IV cipherText = '' if (hexLen % blockSize) != 0: hexString = padMsg(hexString, hexLen + (blockSize - (hexLen % blockSize)), True) hexLen = len(hexString) for i in range(0, hexLen, blockSize): previousMsg = AESencrypt( key, fixedXOR(hexString[i:i + blockSize], previousMsg)) cipherText += previousMsg return cipherText
def AESCTRdecrypt(key, hexString, nonce, blockSize=16): hexLen = len(hexString) blockSize *= 2 ctr = 0 keyStream = '' for i in range(0, int(math.ceil(hexLen / (blockSize * 1.0)))): hex_ctr = big2little(hex(ctr)[2:].zfill(16).rstrip("L")) hex_nonce = big2little(hex(nonce)[2:].zfill(16).rstrip("L")) ctr += 1 keyStream += AESencrypt(key, hex_nonce + hex_ctr) keyLen = len(keyStream) diffBytes = keyLen % hexLen if diffBytes > 0: keyStream = keyStream[:(-1) * diffBytes] return fixedXOR(keyStream, hexString)
def AESCBCdecrypt(key, hexString, IV): hexLen = len(hexString) blockSize = 32 previousMsg = IV plainText = '' hexLen = len(hexString) if hexLen % blockSize != 0: raise Exception("16(n) byte cipher text required- " + str(hexLen)) else: for i in range(0, hexLen, blockSize): plainText += fixedXOR(AESdecrypt(key, hexString[i:i + blockSize]), previousMsg) previousMsg = hexString[i:i + blockSize] plainText = isValidPadding(plainText.decode("hex")) return plainText.encode("hex")
def crackSingleXOR(cipherText, retUnit=True, retScore=False): cipherLen = len(cipherText) bruteKey = '' finalKey = '' score = 0.00 maxScore = 0.00 for i in range(256): bruteKey = '' while len(bruteKey) != cipherLen: bruteKey += hex(i)[2:].zfill(2).rstrip("L") score = scoreText(fixedXOR(bruteKey, cipherText).decode("hex")) if (score > maxScore): maxScore = score finalKey = bruteKey if retUnit and (not retScore): return finalKey[:2] elif (not retUnit) and retScore: return maxScore elif retUnit and retScore: return finalKey[:2], maxScore else: return finalKey if __name__ == "__main__": Key = crackSingleXOR(sys.argv[1], False) print fixedXOR(Key, sys.argv[1]).decode("hex")
def hammingDistance(bytes1, bytes2): xorSum = fixedXOR.fixedXOR(bytes1, bytes2) xorSumBin = bin(int(binascii.hexlify(xorSum), 16))[2:] distance = len([bit for bit in xorSumBin if bit == '1']) return distance
safeMessage = 'comment1=cooking%20MCs;userdata=' + \ safeMessage + ';comment2=%20like%20a%20pound%20of%20bacon' encrypted = aes.encrypt(safeMessage.encode()) return encrypted def decryptCheck(cipherText, aes): message = aes.decrypt(cipherText) print(f'\nDecrypted message:\n{message}') if message.find(b';admin=true;') > -1: print('ADMIN ACCESS GRANTED') else: print('ADMIN ACCESS DENIED') if __name__ == "__main__": aes = AES_CBC() cipherText = encrypt('A' * 32, aes) print(f'\nOriginal Ciphertext:\n{cipherText}') # Begin attack xorText = fixedXOR(b'A' * 12, b';admin=true;') modifiedCipherText = cipherText[:32] + fixedXOR( cipherText[32:48], b'z %,(/|534$z' + b'\x00' * 4) + cipherText[48:] # End attack print(f'\nModified Ciphertext:\n{modifiedCipherText}') decryptCheck(modifiedCipherText, aes)
from fixedXOR import fixedXOR from binascii import hexlify, unhexlify test_input_a = '1c0111001f010100061a024b53535009181c' test_input_b = '686974207468652062756c6c277320657965' expected_output = '746865206b696420646f6e277420706c6179' if __name__ == '__main__': status = '[*] testing fixed XOR...{0}' test_output = hexlify( fixedXOR(unhexlify(test_input_a), unhexlify(test_input_b))) if test_output == expected_output: status = status.format('OK') else: status = status.format('FAIL.\n\tgot: {0}\n\texpected{1}'.format( test_output, expected_output)) print(status)
def test_fixedXOR(self): intputData = "1c0111001f010100061a024b53535009181c" xorData = "686974207468652062756c6c277320657965" output = "746865206b696420646f6e277420706c6179" self.assertEqual(output, fixedXOR(intputData, xorData))
from crackSingleXOR import crackSingleXOR from fixedXOR import fixedXOR if __name__ == "__main__": score = 0.00 maxScore = 0.00 detectedLine = '' with open('./Tests/4.txt', 'r') as testFile: for line in testFile: score = crackSingleXOR(line.strip(),False,True) if(score > maxScore): maxScore = score detectedLine = fixedXOR(crackSingleXOR(line.strip(),False),line.strip()).decode("hex") print detectedLine, maxScore
if __name__ == "__main__": encryptedStrings = readFileandEncrypt("./Tests/20.txt") maxLen = 0.0 key = '' for encryption in encryptedStrings: if (len(encryption) > maxLen): maxLen = len(encryption) repeatStrings = moldMatrix(encryptedStrings, maxLen / 2) for eachString in repeatStrings: if len(eachString) > 0: key += crackSingleXOR(eachString) else: key += hex(0)[2:].zfill(2) keyLen = 0 diffBytes = 0 tempKeyStream = '' for encryption in encryptedStrings: keyLen = len(key) eLen = len(encryption) diffBytes = (keyLen - eLen) if diffBytes > 0: tempKeyStream = key[:(-1) * diffBytes] print fixedXOR(tempKeyStream, encryption).decode("hex") else: print fixedXOR( tempKeyStream, encryption[:len(tempKeyStream)]).decode( "hex" ) + " - Trimmed Cipher due to unavailability of enough data"