如果要修改字节的LSB,将值表达为二进制字符串没有意义。实际上,你会做沿东西线(在伪代码):
byte = '\x6h'
binary = convert_to_bits(byte) # some way of getting 1s and 0s in a string
binary = binary[:7] + my_bit_string
byte = convert_to_byte(binary)
有更直接,更有效的方式来修改一个位值,这就是与bitwise operators。例如,假设我们要将01001001(十进制73)更改为01001000.我们想要创建一个位掩码11111110,它的十进制值是254,而AND
它与我们的值。
>>> value = 73 & 254
>>> value
72
>>> '{0:08b}'.format(value)
'01001000'
当你嵌入位字节中,LSB可能改变也可能不会。有很多方法可以解决这个问题,但最直接的做法是将lsb清零,然后用OR
(如果您还想嵌入多个位,则功能非常全面)将其覆盖。
byte = (byte & 254) | my_bit
你也可以零出LSB用right shift
,随后left shift
,但这需要2个操作,而不是一个。
byte = ((byte >> 1) << 1) | my_bit
或者你可以检查LSB和你的位是否是不同的,并用XOR
翻转。但是,这种方法使用分支,效率最低。
if (byte & 1) != my_bit:
byte = byte^1
# no need to do anything if they are the same
所以,你需要做的就是将您的字节整数数组。你可以使用[ord(byte) for byte in frame]
,但有更高效的内置方式。随着bytearray()
和bytes()
:
>>> frame = '\x0f\x02\x0e\x02\xf7\x00\xf7\x00T\xffT\xff'
>>> frame_bytes = bytearray(frame)
>>> frame_bytes[0]
15
>>> frame_bytes[0] = 14 # modify
>>> bytes(frame_bytes) # convert back to bytes
'\x0e\x02\x0e\x02\xf7\x00\xf7\x00T\xffT\xff'
与array.array()
(这似乎是几十万字节的一小一丁点儿慢):
>>> import array
>>> frame = '\x0f\x02\x0e\x02\xf7\x00\xf7\x00T\xffT\xff'
>>> frame_bytes = array.array('B', frame)
>>> frame_bytes[0]
15
>>> frame_bytes[0] = 14 # modify
>>> frame_bytes.tostring() # convert back to bytes; in Python 3 use `tobytes()`
'\x0e\x02\x0e\x02\xf7\x00\xf7\x00T\xffT\xff'
嵌入和提取的例子。
frame = '\x0f\x02\x0e\x02\xf7\xf7T\xffT\xff'
bits = [0, 0, 1, 1, 0]
# Embedding
frame_bytes = bytearray(frame)
for i, bit in enumerate(bits):
frame_bytes[i] = (frame_bytes[i] & 254) | bit
frame_modified = bytes(frame_bytes)
# Extraction
frame_bytes = bytearray(frame_modified)
extracted = [frame_bytes[i] & 1 for i in range(5)]
assert bits == extracted
如果你的秘密是一个字符串或字节序列,它很容易convert them to a list of 1s and 0s。
最后,请确保您不要修改任何标题数据,因为这可能会导致文件无法读取。
乱码字符可能是字节,它们只是以这种方式打印。什么让你觉得他们不是?你有没有尝试'打印(类型(框架))'? – rofls
子过程ffmpeg? – alphanumeric
@rofls - 类型是str。如何以1和0打印这些字节? – aditya