예제 #1
0
def forge_sha1_mac(original_message, mac, append):
    A, B, C, D = struct.unpack('<IIII', mac)
    for prefix_length in range(1, 20):
        print(f'PREFIX LENGTH: {prefix_length}')
        to_pad = b'a' * prefix_length + original_message
        padded = get_md4_padding(to_pad)

        md4 = MD4(append, len(padded) + len(append), A, B, C, D)
        new_mac = md4.digest()

        new_plaintext = padded[prefix_length:] + append
        if authenticate(new_plaintext, new_mac):
            return new_plaintext, new_mac
    return b'', b''
예제 #2
0
def appendMessage(original, tag, extra):
    #assume secret is between 0 and 64 bytes in length
    for i in range(0, 65):
        oldpadding = generateMD4Padding(len(original)+i);
        newdata = extra;
        a = int.from_bytes(tag[0:4], byteorder='little');
        b = int.from_bytes(tag[4:8], byteorder='little');
        c = int.from_bytes(tag[8:12], byteorder='little');
        d = int.from_bytes(tag[12:16], byteorder='little');
        newtag = MD4(A=a, B=b, C=c, D=d, numbytes=i+len(original + oldpadding)).update(newdata).digest()
        if (checkDumbHashAuth(original + oldpadding + extra, newtag)):
            print(original + oldpadding + extra)
            return newtag
    print("Failure");
예제 #3
0
def hash_extend_attack(old_message, old_tag, new_message):
    # try key length
    for i in range(17):
        old_pad = gen_md4_padding(len(old_message) + i)

        new_data = new_message
        a = struct.unpack("<I", (old_tag[0:4]))[0]
        b = struct.unpack("<I", (old_tag[4:8]))[0]
        c = struct.unpack("<I", (old_tag[8:12]))[0]
        d = struct.unpack("<I", (old_tag[12:16]))[0]
        new_tag = MD4(A=a,
                      B=b,
                      C=c,
                      D=d,
                      numbytes=i +
                      len(old_message + old_pad)).update(new_data).digest()
        if check(old_message + old_pad + new_message, new_tag):
            print("congratz!")
            return new_tag
    print("failed")
예제 #4
0
def challenge55():
    md = MD4()
    # these are the two messages (given in a Wang's paper) that have the 
    # same hash (written in little endian)
    #h = "4d7a9c8356cb927ab9d5a57857a7a5eede748a3cdcc366b3b683a0203b2a5d9fc69d71b3f9e99198d79f805ea63bb2e845dd8e3197e31fe52794bf08b9e8c3e9"
    #h = "4d7a9c83d6cb927a29d5a57857a7a5eede748a3cdcc366b3b683a0203b2a5d9fc69d71b3f9e99198d79f805ea63bb2e845dc8e3197e31fe52794bf08b9e8c3e9"
    #m = h.decode("hex")

    # convert to big endian before packing into string:
    # (split into 8 4-bytes blocks and then invert the order of bytes in each block)
    #b = struct.unpack("<16I", m)
    #m = struct.pack(">16I", *b)
    
    print "Wang's paper reports that 4 to 64 randomly selected messages are needed to find a collision;"
    print "with this implementation a few thousands randomly selected messages are needed (it takes some minutes)"
    print "to find a collision - could be because not all multi-step modifications have been applied"
    print ""
    
    charset = string.letters + string.digits + "%/+=" 
    for i in range(10000):
        m = ''.join(random.choice(charset) for x in range(64)) 
        #m = "PyxsBFALuSQW0AsCRKx7wXvRRyKIOIMg1v3hN+dlguuqGnKP1Y=BYo/gR1JHp86="
        #m = "AaUjDhPG6n6acvWmRecqqQ5IDlI0+Klkw9oe6rzDQ=b1/7rtQB2rE=VrxEC2aRhK"
        
        # fails in i = 35 (even all conditions are met, the steps 32 and 33 might fail)
        #m = "wJKsvK3V1Ypyi7U5I=Wqbe2VJRne29l/Q9LADne=YJg65DBrwTuPj7WP=oLK6q/W"
        #m = "l13YLL0oC/rnykdK%i5q%5abUwLNvleCPv6hspmmDPoSG4kX0W9SI2qlsYpJZBb6"
        #m = "M/LxOqd9KpzNY4G%bh9dT%kTGLrpk9wCU4hi+4/K3n=9yufGrqqCD8ULG9rcBh91"
        #m = "+JiumjNHGtbVX886=0qnZSZYx/uX%MHUO8q0Aq0NWa%Zi8nQ=hwrh+5X5udJyNhy"
        
        #h = "4b67208753178a6617a95fb685448610209732e8abe97a8c5bc7d9a615136f314d475b027ff19f881befb76080eb382e169f30e1b6e9347edd17890badbfeae3"
        #m = h.decode("hex")
        #b = struct.unpack("<16I", m)
        #m = struct.pack(">16I", *b)
        
        #ok = md.modify_message(m)
        #print ok
        
        #md = MD4()
        #md.add(m)
        #d = md.finish()
        #hash1 = d.encode("hex")
        
        #h1 = "4b672087d3178a6687a95fb685448610209732e8abe97a8c5bc7d9a615136f314d475b027ff19f881befb76080eb382e169e30e1b6e9347edd17890badbfeae3"
        #m1 = h1.decode("hex")
        #b1 = struct.unpack("<16I", m1)
        #m1 = struct.pack(">16I", *b1)
        
        #md = MD4()
        #md.add(m1)
        #d = md.finish()
        #hash2 = d.encode("hex")
        
        #print hash1
        #print hash2
        
        # collisions are constructed for example for:
        #m = "hMJI75MIPD2ib4SjeJKrMiOrjWD59/CdhM8mUuWC81Fd1nQXrnaQs44P060kCbAh"
        #m = "4MuGCKvYPnlmdnhAab1JF=J4l7/YSMw30WJvY4izj%fgwXuTgADMLptYTBn9Gdww"

        #m = "\xff" * 8 * 8
        #ms = struct.unpack("<16I", m) # m_0, m_1, ..., m_15
        # m_0 - "1234", m_1 - "5678", m_3 - "1234", m_4 - "5678" ...
    
        # modify message to be of the format for which we can construct collision
        ok = md.modify_message(m)
        if not ok:
            continue
        x_mod = md.X_mod[:16]
        # x_mod has been constructed using little endian, so consider this when packing into string:         
        
        l1 = map(lambda x : struct.pack("<I", x), x_mod)
        m_mod = "".join(l1)
    
        md = MD4()
        md.add(m_mod)
        d = md.finish()
        hash1 = d.encode("hex")
    
        # construct collision:
        success = md.construct_collision(m_mod)
        if success == False: # it could be None
            continue
        x_coll = md.X_mod[:16]
        # x_mod has been constructed using little endian, so consider this when packing into string:
    
        l1 = map(lambda x : struct.pack("<I", x), x_coll)
        x_coll = "".join(l1)

        md1 = MD4()
        md1.add(x_coll)
        d = md1.finish()
        hash2 = d.encode("hex")
        for i in range(25, 38):
            break
            print "======"
            # i = 35 ... b_9
            # i = 36 ... a_10
            # i = 37 ... d_10
            t = md._calculate_h_until_break(md.X[:16], i)
            if i == 35:
                print "---"
                print t
            t1 = md._calculate_h_until_break(md.X_mod[:16], i)
            if t != t1:
                print i
                print t
                print t1
                da, db, dd = None, None, None
                if i == 35:
                    db = t1[1] - t[1]
                    print db
                if i == 36:
                    da = t1[0] - t[0]
                    print da
                if i == 37:
                    dd = t1[3] - t[3]
                    print dd
        
        print hash1
        print hash2
        if hash1 == hash2:
            print "Hash collision!"
            print "The following two messages have the same hash:" 
            print m_mod
            print x_coll
            break
        else:
            print "Not OK"
예제 #5
0
def secret_prefix_mac(message, key):
    md4 = MD4(key + message)
    return md4.digest()
예제 #6
0
 def sign(self, msg):
     md4 = MD4()
     digest = md4.update(key+msg).digest()
     return digest
예제 #7
0
    length = sha._message_byte_length # wrong!
    sha2 = Sha1Hash(d, length)
    print 'sha2._h', sha2._h
    assert sha2._h == sha._h

# The reason we need to use the exact padding bytes is because the registers we
# are going to inject contain the hash state after hashing key || message || padding.
# So the final 
if __name__ == '__main__':
    #test2()
    #exit()

    key = 'yellow submarine'
    mac = MD4Mac(key)
    msg = "comment1=cooking%20MCs;userdata=foo;comment2=%20like%20a%20pound%20of%20bacon"
    output_mac = mac.sign(msg)

    evil = ';admin=true'
    # my_mac is the sha1 hash of key || msg || glue_padding || evil
    # we need to try all the possible key lengths to figure out which amount of
    # glue padding is in there.

    for i in range(32):
        pad = MD4.get_padding(len(msg) + i)
        mymd4 = MD4(digest=output_mac, length=i + len(msg) + len(pad))
        mymd4.update(evil)
        my_mac = mymd4.digest()
        full_msg = msg + pad + evil
        if mac.validate(full_msg, my_mac):
            print 'Forged message', my_mac.encode('hex'), 'key length = ', i
예제 #8
0
def hash_md4(data):
    #return hashlib.new('md4', data)
    md4 = MD4()
    md4.update(data)
    return md4
예제 #9
0
def md4(data):
    return MD4().update(data).digest()
예제 #10
0
def get_hash(orig):
    md4 = MD4()
    md4.update(KEY + orig)
    return md4.dgst()
예제 #11
0
from md4 import MD4, get_pad

def get_hash(orig):
    md4 = MD4()
    md4.update(KEY + orig)
    return md4.dgst()


def get_hash_check(orig):
    md4 = MD4()
    md4.update(KEY + orig)
    return md4.dgst()


KEY = b'YELLOW SUBMARINE'
message = b'comment1=cooking%20MCs;userdata=foo;comment2=%20like%20a%20pound%20of%20bacon'
faked = b';admin=true'
mess = struct.unpack('<4I', get_hash(message))

for i in range(10000):
    padding = b'A' * i
    new_key = get_pad(padding + message) + faked
    length = len(new_key) * 8
    fake_mess = new_key[i:]
    md4hash = MD4(mess)
    md4hash.update(faked, length)
    fake_mac = md4hash.dgst()
    test = get_hash_check(fake_mess)
    if test == fake_mac:
        print(fake_mess)
예제 #12
0
def dumbMD4HashAuth(key, message):
    return MD4().update(key + message).digest()