Using Python
Lecturer: 夜猫、土豆、丰嘉
steganos 代表 hidden or covered (隱藏) 的意思。
graph 代表 to write (書寫) 的意思。
一般完整的隱寫系統包含幾個要件:
依現行能用於隱藏訊息的載體,大致可分為五種型式:
就核心概念來說,兩者的目標一致:
保護訊息不讓第三方知曉
兩者使用完全不同的機制來達到目的
STEGANOGRAPHY | CRYPTOGRAPHY | |
---|---|---|
定義 | 隱藏訊息在存在的通訊中 | 轉換訊息為無法理解的型式 |
密文可視性 | Never | Always |
密文資料結構 | 不會更動 | 會更動 |
金鑰 | Optional | Necessary |
每張圖像是由 pixels (像素) 所組成,為影像顯示的基本單位。
每個 pixels (像素),儲存的是由 RGB 三原色組成的顏色值。亦即 Red, Green, Blue 組成每張圖像的每一個 pixel (像素)。
LSB Insertion
總共16777216 種顏色
人類能夠辨識的顏色平均大約1000萬種顏色
更改每個像素LSB的變化以人眼無法辨別
先確認使用者要用何種功能(隱寫or解密)
先確認使用者要用何種功能(隱寫or解密)
先確認使用者要用何種功能(隱寫or解密)
def str2bin(message):
message_bytes = bytes(message, 'ascii')
return "".join(["{:08b}".format(x) for x in message_bytes])
def bin2str(binary):
binary_split = []
count = 0
temp = ""
for i in range(len(binary)):
count += 1
temp += binary[i]
if count == 8:
binary_split.append(temp)
count = 0
temp = ""
return "".join([chr(int(b, 2)) for b in binary_split])
def encode(num, digit):
'''
1. change num to binary.
2. add digit to last digit of num binary.
3. change num binary back to decimal, and return it.
'''
bin_num = bin(num)
bin_num = bin_num[:-1] + digit
return int(bin_num, 2)
def decode(num):
return bin(num)[-1]
def hide(filename, message):
img = Image.open(filename)
binary = str2bin(message) + "1111111111111110"
if img.mode == 'RGBA':
datas = img.getdata()
newData = []
count = 0
message_end = False
for data in datas:
if not message_end:
newpix = []
for num in data :
if count < len(binary):
newpix.append(encode(num, binary[count]))
count += 1
else:
newpix.append(num)
message_end = True
newData.append(tuple(newpix))
else:
break
img.putdata(newData)
img.save(filename, "PNG")
return "Completed!"
else:
return "Incorrect Image Mode, couldn't hide :("
def hide(filename, message):
img = Image.open(filename)
binary = str2bin(message) + "1111111111111110"
if img.mode == 'RGBA':
datas = img.getdata()
newData = []
count = 0
message_end = False
for data in datas:
if not message_end:
newpix = []
for num in data :
if count < len(binary):
newpix.append(encode(num, binary[count]))
count += 1
else:
newpix.append(num)
message_end = True
newData.append(tuple(newpix))
else:
break
img.putdata(newData)
img.save(filename, "PNG")
return "Completed!"
else:
return "Incorrect Image Mode, couldn't hide :("
def retr(filename):
img = Image.open(filename)
binary = ""
if img.mode == 'RGBA':
datas = img.getdata()
for data in datas:
for num in data:
binary += decode(num)
if binary[-16:] == "1111111111111110":
print("Seccuss!")
return bin2str(binary[:-16])
return bin2str(binary)
return "Incorrect Image Mode, couldn't retrieve :("
def main():
parser = optparse.OptionParser('python lsbsteg.py ' + '-e/-d <target file>')
parser.add_option('-e', dest = 'hide', type='string', help='target pic path to hide text')
parser.add_option('-d', dest = 'retr', type='string', help='target pic path to retrieve text')
(options, args) = parser.parse_args()
if options.hide != None:
text = input("Enter a message to hide: ")
print(hide(options.hide, text))
elif options.retr != None:
print(retr(options.retr))
else:
print(parser.usage)
quit()
if __name__ == '__main__':
main()
from PIL import Image
from stegano import lsb
import optparse
parser = optparse.OptionParser('usage %prog ' + '-e/-d <target file>')
parser.add_option('-e', dest = 'hide', type='string', help='target pic path to hide text')
parser.add_option('-d', dest = 'retr', type='string', help='target pic path to retrieve text')
(options, args) = parser.parse_args()
if options.hide != None:
text = input("Enter a message to hide: ")
image = Image.open(options.hide)
image_stego = lsb.hide(image, text)
image_stego.save(options.hide)
print("Success")
elif options.retr != None:
message = lsb.reveal(options.retr)
print("Complete")
print(message)
else:
print(parser.usage)
quit()
parser = optparse.OptionParser('usage %prog ' + '-e/-d <target file>')
parser.add_option('-e', dest = 'hide', type='string', help='target pic path to hide text')
parser.add_option('-d', dest = 'retr', type='string', help='target pic path to retrieve text')
(options, args) = parser.parse_args()
if options.hide != None:
text = input("Enter a message to hide: ")
print(hide(options.hide, text))
elif options.retr != None:
print(retr(options.retr))
else:
print(parser.usage)
quit()
parser = optparse.OptionParser('usage %prog ' + '-e/-d <target file>')
parser.add_option('-e', dest = 'hide', type='string', help='target pic path to hide text')
parser.add_option('-d', dest = 'retr', type='string', help='target pic path to retrieve text')
(options, args) = parser.parse_args()
if options.hide != None:
text = input("Enter a message to hide: ")
elif options.retr != None:
else:
print(parser.usage)
quit()