#foo=bar&baz=qux&zap=zazzle
def parse2dict(s):
    d={}
    s=s.split("&")
    for item in s:
        t=item.split("=")
        d[t[0]]=t[1]
    return d

uid=1
#6,X,5,10 - 3 blocks
def profile_for(key,email):
    global uid
    email=email.strip("&=")
    email=email.replace("&","")
    email=email.replace("=","")
    s="email="+str(email)+"&uid="+str(uid)+"&role=user"
    n=16
    line =s
    #print [line[i:i+n] for i in range(0, len(line), n)]
    news=pad(s,16)
    out=encryptECBAES(key,news)
    #uid+=1
    return out

def create_profile(key,ct):
    out=decryptECBAES(key,ct)
    out=unpad(out)
    #print(out)
    #print ':'.join(x.encode('hex') for x in out)
    d=parse2dict(out)
    return d

from blockcrypto import *
globalkey=randomkey(16)

ct=profile_for(globalkey,"foo@bar&role=admin&crap=.com")

print create_profile(globalkey,ct)

"""
Explanation: http://www.reddit.com/r/crypto/comments/2wuztm/some_questions_regarding_matasano_challenge_13/
End of explanation
"""


print newECBorCBCoracle(globalkey,16,profile_for)

### Need to modify padding oracle
## First of all find where we are - how much input to we have to give to keep +1 blocks (16 chars) the same (from no input)?
## Then insert this number + (16-n) bytes to do the padding attack - can only decrypt part after our input
import numpy as np

def wherearewe(blackbox, key):
    #return offset to block
    pastblocks=np.zeros(16)
    blocksnoinput = splitblocks(blackbox(key,""), 16)
    blocksonebyte=splitblocks(blackbox(key,"A"), 16)
    #numsameorig=np.sum(np.array(blocksnoinput)==np.array(blocksonebyte))
    numsameorig=len(set(blocksnoinput).intersection(set(blocksonebyte)))
    for b in xrange(1,18):
        blocks = splitblocks(blackbox(key,"A"*b), 16)
        #numsame=np.sum(np.array(blocksnoinput)==np.array(blocks))
        numsame=len(set(blocks).intersection(set(pastblocks)))
        if numsame>numsameorig:
            return ((b-1)%16, np.max(np.where(np.array(blocks[:len(pastblocks)])==np.array(pastblocks)) ))
        pastblocks=blocks
    return None

(offset,ourblock) =wherearewe(profile_for,globalkey) #expect 10
print offset, ourblock
###So we want to start with 35As, then reduce

### TODO - We need to set the starting block correctly - want to extract from second block not first to begin with
def newcreatedict(blackbox, key,blocksize,curblock=0,byte=1,knownletters=[], offset=0):
    d={}
    z=(curblock*blocksize)
    #print z, z+blocksize, byte
    #print ascii2hex(blackbox(key,("A"*((blocksize-1)+offset))+"&"))
    #print ':'.join(x.encode('hex') for x in blackbox(key,("A"*((blocksize-2)+offset))+"=u")[16:32])
    for a in xrange(0,128):
        #print ("A"*((blocksize-byte)))+"".join(knownletters)+chr(a)
        d[blackbox(key,("A"*((blocksize-byte)+offset))+"".join(knownletters)+chr(a))[z:z+blocksize]]=chr(a)
    #print ("A"*((blocksize-byte)))+"".join(knownletters)+chr(a)
    return d

# TODO CANNOT GET FIRST BYTE ?!?

def newpadoracle(blackbox,blocksize,totalbytes,key, offset=0, ourblock=0):
    outs=[]
    knownletters=[]
    for b in xrange((ourblock+1),(totalbytes/blocksize)+1):
        o=""
        for byte in xrange(1,blocksize+1):
            #print b,byte,offset,blocksize,((blocksize-byte)+offset)
            #print b*blocksize, (b+1)*blocksize
            #print blackbox(key, "A"*((blocksize-1)+offset))
            print ':'.join(x.encode('hex') for x in blackbox(key, "A"*((blocksize-2)+offset)+"=")[16:32])

            onebyteshort=blackbox(key, "A"*((blocksize-byte)+offset))
            d=newcreatedict(blackbox,key,blocksize,curblock=b,byte=byte,knownletters=knownletters, offset=offset)
            #print d
            #print d
            try: #TODO: Hack for last byte
                knownletters.append(d[onebyteshort[b*blocksize:(b+1)*blocksize]])
                o+=d[onebyteshort[b*blocksize:(b+1)*blocksize]]
                print o
            except Exception as e:
                #print e
                pass
           # print o, b
        outs.append(o)
       #print outs,b
    return "".join(outs)

#print (len(profile_for(globalkey,"")) - (16-offset))
#print len(profile_for(globalkey,""))
#print newpadoracle(profile_for,16,16, globalkey,offset, ourblock)


### TODO: We are removing & and = when we encode email, so we cannot use these in padding attack
### but &u succeeds, but we must guess that it is & - how do we know?
### Strip only removes from the end
### - change to do quoting

hiddenlength= len(profile_for(globalkey,""))
print hiddenlength

out=padoracle(profile_for,16,hiddenlength,globalkey)
print unpad(out)

"""
Explanation: Assume blocksize is 16-byes (128-bit) - discovering this is possible but a pain in the ass.
End of explanation
"""


ct1=profile_for(globalkey,"AAA@AA.COMadmin"+("\x0B"*11))

ct2=profile_for(globalkey,"AAAAAAAA@A.COM")

    ct3=ct2
print len(ct3)
ct4=ct2[:32]+ct1[16:32]
print len(ct4)
print create_profile(globalkey,ct4)

"""
Explanation: Assuming we know plaintext form
End of explanation
"""


