如何将ASCII字节写入二进制文件?
我在做一个关于MD5碰撞的作业,但不太确定怎么在Python里写原始字节。我试了一下,结果得到的只是一个包含ASCII字符的.bin文件。以下是我的代码:
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()
示例输入: d1 31 dd 02 c5 e6 ee c4 69 3d 9a 06 98 af f9 5c 2f ca b5
我之前有一个链接指向我的输入文件,但好像被管理员删掉了。这个文件每一行都是用ASCII写的十六进制字节。
编辑:解决了!感谢Circumflex。
我有两个不同的文本文件,每个文件里有128个ASCII字节。我把它们转换成二进制格式,然后用struck.pack写入,成功得到了一个MD5碰撞。
2 个回答
>>> import binascii
>>> binary = binascii.unhexlify("d131dd02c5")
>>> binary
'\xd11\xdd\x02\xc5'
binascii.unhexlify()
是在 binascii.c
中定义的。下面是一个用 Python 实现的“接近 C 语言”的版本:
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())
如果没有 binascii.unhexlify()
、bytearray.fromhex()
、str.decode('hex')
或类似的功能,你可以这样写:
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)
如果你想把数据写成原始字节,可以使用 struct
类型的 pack()
方法。
你可以把 MD5 值写成两个长整型数字,但需要把它分成两个 8 字节的部分来写。
http://docs.python.org/library/struct.html
编辑:
举个例子:
import struct
bytes = "6F"
byteAsInt = int(bytes, 16)
packedString = struct.pack('B', byteAsInt)
如果我理解没错,你是想把一些包含十六进制字符串的文本提取出来,转换成二进制格式,然后输出?如果是这样的话,这段代码应该能满足你的需求。
它基本上是把原始的十六进制字符串转换成一个整数,然后把它以二进制形式(作为字节)打包成一个字符串。
你可以对输入字符串中的每个字节进行类似这样的循环处理。