24 位 BMP 位图文件
要利用 BMP 位图进行加密首先需要了解 BMP 文件的存放格式,24 位真彩 BMP 位图文件
包括 3 部分:
第 一 部 分 是 BMP 文件头:前 2 个字节是“ BM” , 是 用 于 识 别 BMP 文件的标志;第
3、4、5、6 字节存放的是位图文件的大小,以字节为单位;第 7、8、9、10 字节是保留的,
必须为 0;第 11、12、13、14 字节给出位图阵列相对于文件头的偏移。
第二部分是点位图信息:从第 29 个字节开始,第 29、30 字节描述的是像素的位数;第
35、36、37、38 字节确定图像字节数的多少,但通常此项为空。
第三部分是位图阵列:从第 39 个字节开始,每 3 个字节表示一个像素,这 3 个字节依次表
示该像素的红、绿、蓝亮度分量值。要从位图文件中“挤"出用来隐藏其他重要信息的存储
空间,就需要从这里入手。
实现原理
根据亮度公式:I=0.3R+0.59G+0.11B 可以知道人眼对于绿色分量最为敏感,对蓝色分量
最不敏感,绿色分量值改变 1 个单位就相当于蓝色分量改变 5 个、红色分量改变 2 个单位。
折算为二进制,红色分量可以改变其低两位、绿色分量可以改变其最低位、蓝色分量可以
改变其低三位。这样就可以从描述每个像素的 3 个字节中得到 2+1+3=6 个比特的冗余信
息位用于存储其他文件的比特流。按此比率,从一幅 24 位 BMP 位图中可以得到的最大存
储空间为:((位图文件大小-40)×6)/(3×8),大约是其位图文件长度的 1/4。
由于位图文件中每 3 个字节只能提供 6 个比特的存储空间,所以需要 12 个字节才能完整保
存源文件的 3 个字节。
本文制定的加密协议是先通过程序窗口输入密码,从位图文件的第 39 个字节即位图阵列部
分开始存储,依次为:源文件名、分割符“*”、源文件的长度、分割符“*”、源文件的内容。
其中源文件内容的每个字节需与密码相异或,以起到对文件进一步加密的效果。
这里需要特别指出的是:如果在网络传输时该文件被截获,从中将加密文件恢复出来的可
能性是非常小的。首先,从外观上加密后的文件和一般的 BMP 文件没有任何区别,而且加
密前后位图文件大小也不会发生变化,不会引起截获者的注意。其次,由于只有大约 1/4
的空间存有隐含信息,对于被加密信息而言,其他 3/4 的内容都是冗余位。在密码学上,
往往采取加大冗余位的方式来提高加密的可靠性,显然这种拥有 75%的冗余码的加密方法
还是颇为可靠的。最后,破译者并不知晓加密所采取的协议,而且待加密的内容都同加密
密钥经过了异或运算,在没有正确解密密码的情况下也是很难破译的。
源文件的加密
由于进行加密处理的过程中要频繁进行位运算,所以选用在这方面较有优势的 Micorsoft
Visual C++ 6.0 作为开发工具。
加密的关键是将待加密信息组成比特流,并将其按规定的格式依次填入载体位图文件的指
定位中。首先要做好准备工作,由于每 12 个位图文件的字节恰好可以用于保存 3 个源文件
的字节,而 12 又是 3 的整数倍,所以可以设定每 12 个字节为一个循环。下面 5 个数组中
存放的数据用于处理每个循环中的各个字节所要进行的移位量和掩码值等:
//填冗余位时的移位序列
int move1[13]={6,5,2,0,7,4,2,1,-2,6,4,3,0};
//源文件的字节掩码序列
unsigned char mask1[13]={192,32,28,3,128,112,12,2,1,192,48,8,7};
//位图文件的字节掩码序列
unsigned char mask2[13]={252,254,248,252,254,248,252,254,251,252,252,254,248};
//为 1 时,存放待加密信息的缓存指针加一