Python和隐写术

不久前,在我举行了一次针对学生的黑客马拉松试点。 任务主题与信息安全有关,包括数据加密。



TASK-10是最丰富多彩的任务之一: 隐写术
我们给出一个定义。
考虑到这种转移(存储)事实的机密性, 隐写术是一种传输或存储信息的方式。
换句话说,如果密码术隐藏了信息本身,那么隐秘术则隐藏了其传播的事实。



不幸的是,我和团队没有时间按时完成这项任务,因此我决定在活动结束后完成它。

当时最明显的解决方案似乎是:

  1. 将密文转换为位集。
  2. 对图像执行相同的操作。
  3. 将文本放置在图像上的任意位置,并将其另存为图片。

这里有一些代码将文本转换为位集,反之亦然。

def text_to_binary(event): return [int(format(ord(elem),'b')) for elem in event] def binary_to_text(event): return [chr(int(str(elem),2)) for elem in event] 

但是,在告诉我经验丰富的同事我的想法之后,我被派去教材料。
您需要首先开始一个事实,即如果不是bmp,则不能直接编辑图像文件的字节。

{%-随机编码器%}
在阅读了一些有关颜色模型的知识之后,我决定放弃将图像分解为1和0的方法,转而对RGB调色板中的像素本身进行修改。 对于这些操作,我选择了Pillow库,这是一篇很好的文章。

因此,我们有一个图像。 图像有像素。 像素由原色形成-红色,绿色和蓝色。

每种颜色都使用0到255之间的数字进行编码。



而且,我们还有已编码的ASCII字符。

让我们尝试加密此图片中的一些文本。

图片:




一点文字:
C可以使您轻松射击自己的脚; C ++使它变得更难,但是当您这样做时,它会炸掉您的整个腿
连接必要的库。

 from PIL import Image, ImageDraw from random import randint 

然后,我们声明该函数并将所有对我们有用的对象放入其中。

 def stega_encrypt(): keys = [] img = Image.open(input("path to image: ")) draw = ImageDraw.Draw(img) width = img.size[0] height = img.size[1] pix = img.load() f = open('keys.txt','w') 

更有趣。 最重要的任务是提出一种加密消息的方法。 我提出了这种方法

  1. 取一个字符,将其转换为ASCII数字
  2. 创建具有随机坐标的元组
  3. 我们从坐标处的一个像素收集绿色和蓝色阴影
  4. 将红色调替换为ASCII字符号

 for elem in ([ord(elem) for elem in input("text here: ")]): key = (randint(1,width-10),randint(1,height-10)) g, b = pix[key][1:3] draw.point(key, (elem,g , b)) f.write(str(key)+'\n') 

我们保存密钥和图像。

 print('keys were written to the keys.txt file') img.save("newimage.png", "PNG") f.close() 

代号

我们尝试执行脚本。

结果,我们得到了相同的图像,但是是png格式,并且像素有所变化。



现在,仍然需要以某种方式解密所有内容。

我们正在编写用于解密的脚本!

我们连接所需的一切。

 from PIL import Image from re import findall 

我们声明一个用于解密的函数以及几个对象。

 def stega_decrypt(): a = [] keys = [] img = Image.open(input("path to image: ")) pix = img.load() f = open(input('path to keys: '),'r') y = str([line.strip() for line in f]) 

基本解密算法:

 for i in range(len(findall(r'\((\d+)\,',y))): keys.append((int(findall(r'\((\d+)\,',y)[i]),int(findall(r'\,\s(\d+)\)',y)[i]))) for key in keys: a.append(pix[tuple(key)][0]) return ''.join([chr(elem) for elem in a]) 

需要这些正则表达式才能从文本文件中读取元组。

最后的操作是在屏幕上显示加密的消息。

 print("you message: ", stega_decrypt()) 

代号

现在尝试获取我们的消息。



根据证明,一切正常!

主要缺点是:在加密大量字符的情况下,图像中坏点的可见性。 但是,此缺陷可以通过高分辨率完美纠正。

参考文献:

Source: https://habr.com/ru/post/zh-CN413803/


All Articles