Calculating MD5 of Hex in Python - python

I always fail with the decrypting of a RC4 encrypted object. My key has to be the MD5-Hash of this hex string:
00 00 00 01 3e 2a 5b 71 00 00 03 a0
What i tried was to convert that hex string to ascii and calculate afterwards the MD5 hash of it, but it seems like my key is always wrong. I think there is a problem because some of the hex values are control characters, but how is then the correct way to calculate the MD5 of this hex string ? What i thought of was something like this:
from Crypto.Cipher import ARC4
from Crypto.Hash import MD5
def hexToAscii(hex_string):
return ''.join([chr(int(''.join(c), 16)) for c in zip(hex_string[0::2],hex_string[1::2])])
def main():
hex_string = '000000013e2a5b71000003a0'
# Key for Decryption
myKey = MD5.new(hexToAscii(hex_string)).hexdigest()
print 'hexToAscii(hex_string): %s' % hexToAscii(hex_string)
#open('myfile','wb').write(ARC4.new(hexToAscii(myKey)).decrypt(hexToAscii(CIPHER_TEXT)))
if __name__ == '__main__':
main()

The main function prints hexToAscii(hex_string) instead of myKey.
BTW, you'd better to use binascii.unhexlify instead of hexToAscii. And you can use hashlib module to calculate md5.
>>> import hashlib
>>> import binascii
>>> hex_string = '000000013e2a5b71000003a0'
>>> hashlib.md5(binascii.unhexlify(hex_string)).hexdigest()
'6afebf522c531575e96d6814be816c7c'

Use hashlib and binascii from Python standard lib, no conversion to ASCII involved:
import binascii
import hashlib
base = binascii.unhexlify("000000013e2a5b71000003a0")
key = hashlib.md5(base).digest()

Related

Wrong CMAC generation from Pycryptodome

As per the Example given in the documentation of PyCryptodome
>>> from Crypto.Hash import CMAC
>>> from Crypto.Cipher import AES
>>> secret = b'Sixteen byte key'
>>> cobj = CMAC.new(secret, ciphermod=AES)
>>> cobj.update(b'Hello')
>>> print cobj.hexdigest()
it generates the AES CMAC but when I try the test vector from RFC4493, I get the wrong CMAC.
for example, the test vectors from RFC4493 are:
K 2b7e1516 28aed2a6 abf71588 09cf4f3c
M 6bc1bee2 2e409f96 e93d7e11 7393172a
AES-CMAC 070a16b4 6b4d4144 f79bdd9d d04a287c
But when I tried the same key and message
>>> from Crypto.Hash import CMAC
>>> from Crypto.Cipher import AES
>>> secret = b'2b7e151628aed2a6abf7158809cf4f3c'
>>> cobj = CMAC.new(secret, ciphermod=AES)
>>> cobj.update(b'6bc1bee2 2e409f96 e93d7e11 7393172a')
>>> print cobj.hexdigest()
I got the following output
a3f10a99bd83f4dee4392d65ed9f76c1
The problem in your code is that your are not treating the message or key 2b7e1516 28aed2a6 abf71588 09cf4f3c as a hex number which it is in this case but you are treating it as bytes where each character is stored in it's ASCII representation rather than being stored as the actual value of hex character so f is stored as binary 0100 0110 rather than as binary 1111. While the RFC deal with input as the numbers encoded as HEX characters, so use this code:
from Crypto.Hash import CMAC
from Crypto.Cipher import AES
secret = "2b7e151628aed2a6abf7158809cf4f3c"
msg = "6bc1bee22e409f96e93d7e117393172a"
cobj = CMAC.new(bytes.fromhex(secret), ciphermod=AES)
cobj.update(bytes.fromhex(msg))
res = cobj.hexdigest()
print(res)
which will print correct result of
070a16b46b4d4144f79bdd9dd04a287c
Hope this solve your problem.

How to join hex values

I am reading four bytes from file
I would like to join them
g = f.read(60)
f.seek (60)
k60 =f.read(1)
print('byte60',k60)
k61 =f.read(1)
print('byte61',k61)
k62 =f.read(1)
print('byte62',k62)
k63 =f.read(1)
print('byte63',k63)
print(k63,k62,k61,k60)
print (b''.join([k63,k62,k61,k60]))
Result is:
b'\x00\x00\x00\x80'
I would like to receive:
00000080
You to convert a byte string to its hex representation, you can use the hexlify() method from the binascii module:
>>> from binascii import hexlify
>>> ...
>>> raw = b''.join([k63,k62,k61,k60])
>>> print(hexlify(raw))
b'00000080'
>>> print(hexlify(raw).decode('ascii') # if you want to convert it to a string
00000080
The same could be accomplished by using codecs.encode(raw, 'hex').

How do I force recv() in Socket to NOT convert my hex values into ASCII if it can (python)

I am using python 3.4 socket interface of python-can. I am having a problem, when I receive the data via recv() or recvfrom() it converts some of the hex data in the message to ASCII if it can for example '63' becomes a 'c'. I do not want this, I want the raw hex data.
Here is a snippet part of the code:
def dissect_can_frame(frame):
can_id, can_dlc, data = struct.unpack(can_frame_fmt, frame)
global dataS
dataS = data[:can_dlc]
return (can_id, can_dlc, data[:can_dlc])
s = socket.socket(socket.AF_CAN,socket.SOCK_RAW,socket.CAN_RAW)
print(s)
s.bind((can_interface,))
#s.bind((sys.argv[1],)) #used for 'can0' as argument at initial execution
print(socket.AF_CAN,",",socket.SOCK_RAW,",",socket.CAN_RAW)
#while True:
cf, addr = s.recvfrom(4096)
print(cf,',',addr)
I get "b'\x18c\xd8\xd6\x1f\x01 \x18'" as the output section of the data instead of "18 63 D8 D6 1F 01 20 18". Do not care about the formatting but notice how '63' has become 'c' and '20' has inserted a space. Can I stop it doing this?
Is it common for socket to convert the data rather than producing the raw data?
Thank you for any help.
That's just how the data looks when it comes out of recv. If you want to convert it into a hex-looking string, then you can use format on each character:
>>> s = b'\x18c\xd8\xd6\x1f\x01 \x18'
>>> " ".join(["{:02X}".format(ord(c)) for c in s])
'18 63 D8 D6 1F 01 20 18'
Of course, this is an inconvenient format for actually doing any kind of analysis on the data. But it looks nice for display purposes.
Alternatively, there's hexlify, but that doesn't space out the values for you:
>>> import binascii
>>> binascii.hexlify(s)
'1863d8d61f012018'

PyCrypto AES encryption not working as expected

I am creating a Python function to perform counter mode encryption using the PyCrypto module. I am aware of the builtin, but want to implement it myself.
I'm trying Test Vector #1 from RFC 3686, and have the correct Counter Block and the correct Key in ASCII form. But when I encrypt the Counter Block using the Key, I don't get the expected Key Stream.
The relevant parts of my code:
cipher = AES.new(key)
ctr_block = iv + nonce + ctr
key_stream = base64.b64decode(cipher.encrypt(ctr_block))
I can provide more code if needed, but I'm not sure how because ctr_block and key have many question mark characters when I print them.
Why am I not getting the expected answer? It seems like everything should go right. Perhaps I made some mistake with the encoding of the string.
Edit
Self-contained code:
from Crypto.Cipher import AES
import base64
def hex_to_str(hex_str):
return str(bytearray([int(n, 16) for n in hex_str.split()]))
key = hex_to_str("AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E")
iv = hex_to_str("00 00 00 00 00 00 00 00")
nonce = hex_to_str("00 00 00 30")
ctr = hex_to_str("00 00 00 01")
cipher = AES.new(key)
ctr_block = iv + nonce + ctr
key_stream = base64.b64decode(cipher.encrypt(ctr_block))
print "".join([hex(ord(char)) for char in key_stream])
# 0xd90xda0x72
First, the correct CTR block order is nonce + iv + ctr. Second, that base64.b64decode call is wrong: cipher.encrypt produces a decoded string. After these two fixes your code prints 0xb70x600x330x280xdb0xc20x930x1b0x410xe0x160xc80x60x7e0x620xdf which seems to be a correct key stream.
First, use byte strings:
In [14]: keystring = "AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E"
In [15]: keystring.replace(' ', '').decode('hex')
Out[15]: '\xaehR\xf8\x12\x10g\xccK\xf7\xa5vUw\xf3\x9e'
Second, you shouldn't use base64.

How to write a file of ASCII bytes to a binary file as actual bytes?

Trying to do an MD5 collision homework problem and I'm not sure how to write raw bytes in Python. I gave it a shot but just ended up with a .bin file with ASCII in it. Here's my code:
fileWriteObject1 = open("md5One.bin", 'wb')
fileWriteObject2 = open("md5Two.bin", 'wb')
fileReadObject1 = open('bytes1.txt', 'r')
fileReadObject2 = open('bytes2.txt', 'r')
bytes1Contents = fileReadObject1.readlines()
bytes2Contents = fileReadObject2.readlines()
fileReadObject1.close()
fileReadObject2.close()
for bytes in bytes1Contents:
toWrite = r"\x" + bytes
fileWriteObject1.write(toWrite.strip())
for bytes in bytes2Contents:
toWrite = r"\x" + bytes
fileWriteObject2.write((toWrite.strip())
fileWriteObject1.close()
fileWriteObject2.close()
sample input:
d1
31
dd
02
c5
e6
ee
c4
69
3d
9a
06
98
af
f9
5c
2f
ca
b5
I had a link to my input file but it seems a mod removed it. It's a file with a hex byte written in ASCII on each line.
EDIT: SOLVED! Thanks to Circumflex.
I had two different text files each with 128 bytes of ASCII. I converted them to binary and wrote them using struck.pack and got a MD5 collision.
If you want to write them as raw bytes, you can use the pack() method of the struct type.
You could write the MD5 out as 2 long long ints, but you'd have to write it in 2 8 byte sections
http://docs.python.org/library/struct.html
Edit:
An example:
import struct
bytes = "6F"
byteAsInt = int(bytes, 16)
packedString = struct.pack('B', byteAsInt)
If I've got this right, you're trying to pull in some text with hex strings written, convert them to binary format and output them? If that is the case, that code should do what you want.
It basically converts the raw hex string to an int, then packs it in binary form (as a byte) into a string.
You could loop over something like this for each byte in the input string
>>> import binascii
>>> binary = binascii.unhexlify("d131dd02c5")
>>> binary
'\xd11\xdd\x02\xc5'
binascii.unhexlify() is defined in binascii.c. Here's a "close to C" implementation in Python:
def binascii_unhexlify(ascii_string_with_hex):
arglen = len(ascii_string_with_hex)
if arglen % 2 != 0:
raise TypeError("Odd-length string")
retval = bytearray(arglen//2)
for j, i in enumerate(xrange(0, arglen, 2)):
top = to_int(ascii_string_with_hex[i])
bot = to_int(ascii_string_with_hex[i+1])
if top == -1 or bot == -1:
raise TypeError("Non-hexadecimal digit found")
retval[j] = (top << 4) + bot
return bytes(retval)
def to_int(c):
assert len(c) == 1
return "0123456789abcdef".find(c.lower())
If there were no binascii.unhexlify() or bytearray.fromhex() or str.decode('hex') or similar you could write it as follows:
def unhexlify(s, table={"%02x" % i: chr(i) for i in range(0x100)}):
if len(s) % 2 != 0:
raise TypeError("Odd-length string")
try:
return ''.join(table[top+bot] for top, bot in zip(*[iter(s.lower())]*2))
except KeyError, e:
raise TypeError("Non-hexadecimal digit found: %s" % e)

Categories

Resources