Skip to content

Commit

Permalink
Creation of ECBPlaintextAttack
Browse files Browse the repository at this point in the history
  • Loading branch information
doyler committed Aug 12, 2016
1 parent 127c9a9 commit 53c03bf
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 0 deletions.
4 changes: 4 additions & 0 deletions ECBPlaintextAttack/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# ECB Plaintext Attack
A sample AES-ECB server and client for demonstrating a chosen plaintext attack.

For more information, see the following blog post - https://www.doyler.net/security-not-included/ecb-chosen-plaintext-attack
78 changes: 78 additions & 0 deletions ECBPlaintextAttack/ecbAttack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/python

import math
import socket
import sys

def chunkstring(string, length):
return (string[0+i:length+i] for i in range(0, len(string), length))

def roundup(x, base=10):
return int(math.ceil(x / (base + 0.0))) * base

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server_address = ('localhost', 10000)
s.connect(server_address)

try:
found = False
secret = ""

secretLen = 0
#prependChars = "ENCRYPT:"
prependChars = ""

message = "A"
s.sendall(message)
data = s.recv(2048)
output = list(chunkstring(data, 32))
initialLen = len(output)

curLen = 0

while (curLen <= initialLen):
message += "A"
s.sendall(message)
data = s.recv(2048)
output = list(chunkstring(data, 32))
curLen = len(output)

extra = len(message) - 1

secretLen = ((curLen - 1) * 16) - extra - len(prependChars)

print "SECRETLEN: " + str(secretLen)

while not found:
initialBlock = "A" * (16 - len(prependChars))
fullLen = roundup(secretLen, 16)
prepend = "B" * (fullLen - len(secret) - 1)
message1 = initialBlock + prepend

s.sendall(message1)
data = s.recv(8192)
initialReturn = list(chunkstring(data, 32))
#print "INITIAL: " + str(initialReturn)

for i in range(33, 127):
message2 = message1 + secret + chr(i)
s.sendall(message2)
data = s.recv(8192)
oracle = list(chunkstring(data, 32))
#print "ORACLE: " + str(oracle)
compareBlock = (len(message2) / 16)
#print "COMPARE = " + str(compareBlock)
if oracle[compareBlock] == initialReturn[compareBlock]:
secret += chr(i)
#print "LENGTH: " + str(len(secret))
#print "SECRET: " + secret
#print "INITIAL: " + str(initialReturn)
#print "ORACLE: " + str(oracle)
if len(secret) == secretLen:
found = True
print secret
break

finally:
s.close()
80 changes: 80 additions & 0 deletions ECBPlaintextAttack/ecbServer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/python

from Crypto.Cipher import AES
import socket
import sys
import random
import string

blockSize = 16
encKey = "ENCRYPTIONKEY123"
#secret = "mys3cretP@ssword!"
before = ""
#before = "ENCRYPT:"
chars = string.ascii_letters + string.digits + string.punctuation
secret = ''.join(random.choice(chars) for _ in range(random.randint(1,1000)))

def pad(input):
if (len(input) % blockSize == 0):
return input
else:
extra = blockSize - (len(input) % blockSize)
output = input + "\x00" * extra
return output

def unpad(input):
return input.rstrip("\x00")

def encrypt(input):
if (input is None) or (len(input) == 0):
print "Input text cannot be null or empty"

input += secret
input = pad(before + input)
cipher = AES.AESCipher(encKey, AES.MODE_ECB)
cipherText = cipher.encrypt(input)
return cipherText.encode("hex")

def decrypt(input):
if (input is None) or (len(input) == 0):
print "Input text cannot be null or empty"

encrypted = input.decode("hex")
cipher = AES.AESCipher(encKey, AES.MODE_ECB)
plainText = unpad(cipher.decrypt(encrypted))
return plainText

def main():
print "SECRET LENGTH: " + str(len(secret))
print "SECRET = " + secret

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

server_address = ('localhost', 10000)
print "\nStarting up on %s port %s" % server_address
s.bind(server_address)

s.listen(1)

while True:
connection, client_address = s.accept()

try:
while True:
data = connection.recv(2048)
if data:
#print "DATA: " + data
input = data.rstrip()
print "INPUT: " + input
print "HEX: " + input.encode("hex")
encrypted = encrypt(input)
print "ENCRYPTED: " + encrypted
connection.send(encrypted)
else:
break
finally:
connection.close()

if __name__ == "__main__":
main()

0 comments on commit 53c03bf

Please sign in to comment.