如果要修改字節的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