原文地址:利用Python、OpenCV对图像加密解密 | QuantumCloud蕴藏一个有趣、不难且实用的理论知识https://myblog.quantumcloud.top/2021/05/16/c6b0f12c5d9c/
基本原理:逻辑异或运算
关于Python就不用过多介绍了,就是一门编程语言;而OpenCV的话,则是一个基于BSD许可发行的跨平台计算机视觉和机器学习的(部分开源)软件库,目前已经支持许多语言,比如C、C++、Python、Java和MATLAB等。
这里选择其中一种语言——Python,来演示整个操作流程,其他语言大致步骤一样,不再作过多赘述。
首先,咱们来看一道基本的(二进制)计算题,以帮助大家理解后续的东西:
【在看题之前,如果不知道异或运算的规则,可以先看一下这张真值表】
(逻辑异或运算真值表)
数字A = 1011 0011
数字B = 0100 1110
那么,A xor B = ? (注:这里我用xor代表“逻辑异或”运算符)
根据上面的真值表,不难得出最终结果应该为1111 1101
结果的确是算出来了,但是还不够,我们还得观察出一个结论,在此之前,我们设C = 1111 1101(也就是上面得出的结果)
然后再计算C xor B=1011 0011,我们设这个结果为D(即D = 1011 0011),通过仔细观察,不难发现:D的值和A的值相等
这一点便是异或运算比较微妙的地方,然后我再把上面提到的那些A、B、C、D加以形象的文字表述。A:原文,B:密钥,C:密文,D:明文,根据上面的数学表述,可以转换成如下表达:原文与密钥进行结合,可以得到密文(加密的数据),然后这个密文如果再和密钥结合,便可以得到明文(解密了的数据),从而实现数据的加密/解密。
实际上,图片在计算机内部,也都是以0和1这种形式来进行存储的,也就是说我们可以用这种方式来对图片进行处理
好了,理论存在,下面开始实践:
首先,导入我们接下来会用到的两个库,分别是OpenCV和NumPy库(没有安装这两个库的朋友,请参考其他教程进行安装)
import cv2
import numpy
然后,我们用随机数产生一个密钥Key(也可以直接将一张图片作为密钥)
Key_1 = numpy.random.randint(0, 255, size=[300, 500], dtype=numpy.uint8)
为了能使我们后续可以正常对图片进行解密,应当将密钥存入文件,妥善保管
cv2.imwrite("Key_1.jpg", Key_1) # 保存密钥
打开密钥的输出路径,就可以看到我们的密钥啦(也是一张图片)
(用随机数产生的密钥 样例)
接下来是加载待加密的图片,并显示
img_originalData = cv2.imread("demo.jpg", -1)
img_originalData = cv2.resize(img_originalData, (500, 300))
cv2.imshow("OriginalData", img_originalData)
(待加密的图片)
由于这是一张彩色图片,因此在加密之前我们需要将图片分解为三个通道(Blue、Green、Red)便于在后续的操作中,分别对三个通道进行处理
img_originalData_B = img_originalData[:, :, 0]
img_originalData_G = img_originalData[:, :, 1]
img_originalData_R = img_originalData[:, :, 2]
接着我们用密钥分别与三个通道进行逻辑异或运算,然后再将三个通道合并
ciphertext_B = cv2.bitwise_xor(img_originalData_B, Key_1)
ciphertext_G = cv2.bitwise_xor(img_originalData_G, Key_1)
ciphertext_R = cv2.bitwise_xor(img_originalData_R, Key_1)
ciphertext_BGR = cv2.merge([ciphertext_B, ciphertext_G, ciphertext_R])
此时便得到一张加密的图片,我们进行预览,看看加密效果
cv2.imshow("Ciphertext", ciphertext_BGR) # 显示已加密的图片
(已加密的图片)
是不是已经完全看不出原图长什么样子了呢?至此,图片的加密就已经完成
如果想要查看原图,就得用完全一致的密钥来进行解密,基本思路和加密过程是一样的,就不在详细分析,直接上代码
decryptedtext_B = cv2.bitwise_xor(ciphertext_B, Key_1) # 将密文的B通道与密钥进行异或运算
decryptedtext_G = cv2.bitwise_xor(ciphertext_G, Key_1) # 将密文的G通道与密钥进行异或运算
decryptedtext_R = cv2.bitwise_xor(ciphertext_R, Key_1) # 将密文的R通道与密钥进行异或运算
decryptedtext_BGR = cv2.merge([decryptedtext_B, decryptedtext_G, decryptedtext_R]) # 合并通道
cv2.imshow("Decryptedtext", decryptedtext_BGR) # 显示已解密的图片
以下为解密之后的图片,是不是和原图完全长得完全一样呢?至此,我们就成功实现了图片的加密与解密
(解密后的图片)
写在最后:上面所演示的这种加密方法主要是根据逻辑异或运算的特性来操作的(引入OPenCV主要是为了便于操作图片的二进制数据),本身是很容易通过代码就能实现,但是想要对加密的图片进行暴力破解却没那么容易,几乎永远无法破解成功。二进制数据还有很多方面可以让我们去探索,比如图片的位平面分解的一个应用:我们可以往图片的“最低有效位”位平面里面添加数字水印,实现版权的标识。以上所提到这些实际上是图像处理的基础应用,后面一些所谓的更高级用法,都是建立在这基础之上的。