二、 BMP位图的内部结构
由于邮件接收方必须根据收到的仅有的一个文件(此处为一幅BMP位图)对其原始性做出判断,那么用来标识该文件的信息只有隐藏在该文件中才能被接收者识别出来,而且该信息不能隐藏到文件的内容信息区中(此处为位图点阵),因为如果这样的话在设置印鉴的同时就已经把原始内容破坏了,文件也就失去了原始性了。因此我们所设置的印鉴水印必须设置到标识文件结构的保留字段中,所以在处理之前有必要对文件的内部结构作些了解。下表就是我们所要研究的对象BMP位图的内部结构:
文件块 |
类型 |
字段 |
地址 |
说明 |
BMP文件头 |
Int |
BfType |
0--1 |
规定必须是\"BM\"作为识别BMP文件的标志 |
Long |
BfSize |
2--5 |
给出了文件的长度,单位为字节 |
Int |
BfReserved1 |
6--7 |
保留,平时为0 |
Int |
BfReserved2 |
8--9 |
保留,平时为0 |
Long |
BfOffbits |
10--13 |
给出了位图阵列相对于文件头的偏移 |
点位图信息 |
Long |
Width |
18--21 |
给出了位图的宽度 |
Long |
Height |
24--27 |
给出了位图的高度 |
Int |
BitCount |
28--29 |
像素的位数,如24为24位真彩、8为256色等 |
Long |
BitSizeImage |
34--37 |
确定图像字节数的多少,但通常此项为0 |
位图阵列 |
从第38字节开始,位图阵列中保存有全部图像像素的RGB三分量值。 |
从上表可以看出,我们设置的印鉴水印只能放在第6--9字节之间的这两段保留字段中。才不会破坏文件的内容和整体结构。
三、用CRC校验码作为印鉴的可靠性能 在网络通讯中经常会用到CRC循环冗余校验码,并广泛的应用于报文的检错。在网络中对报文检错的工作环境同本文的有些类似:都是接收方根据发送方发来的数据来判断这段数据到底是不是同发送方发送时的内容一模一样。我们不妨把发送方发送出来的BMP位图当作一个大报文,对其加上CRC校验,把通常放在帧尾的CRC校验码放到BMP位图的保留字段中,这样接收方只须象网络中的检验报文一样看看校验码的正确与否即可断定出该位图是否被作过处理。
CRC校验码是基于将位串看作是系数为0或1的多项式,一个k位的数据流可以看作是关于x的从k-1阶到0阶的k次多项式的系数序列。采用此编码,发送方和接收方必须事先商定一个生成多项式G(x),其高位和低位必须是1。要计算m位的帧M(x)的校验和,基本思想是将校验和加在帧的末尾,使这个带校验和的帧的多项式能被G(x)除尽。当接收方收到加有校验和的帧时,用G(x)去除它,如果有余数,则CRC校验错误,只有没有余数的校验才是正确的。具体计算校验和的算法如下:
1. 设G(x)为r阶,在帧末尾附加r个0,将帧扩展到m+r位长。
2. 按模2除法用对应于G(x)的位串去除对应于扩展后的M(x)的位串。
3. 按模2减法从对应于扩展后的M(x)的位串中减去余数,其结果就是要传送的带校验和的帧T(x)了。
我们在使用之前有必要对该校验方法的可靠性能做一下分析,如果内容数据做了改动,正确的T(x)位串变成了T(x)+E(x)。在E(x)中每一位都对应着要转换的一位。如果E(x)中有k个1位,那么就会发生k个单个错误。一旦接收方用G(x)去除,即计算[T(x)+E(x)]/G(x),而T(x)/G(x)=0,所以其结果为E(x)/G(x)。除了是G(x)整倍数的多项式差错检测不到以外,其他错误都可以捕获到。如果E(x)中发生单个位(I 位)错误,若G(x)包括至少I项,就永远也除不尽E(x),换句话说,所有单个位错误都可以被检测出来。另外,如果集中差错长度为r+1时,而且当集中差错和G(x)一样时,被G(x)除的余数也可能为0。根据集中差错的定义第一位和最后一位必须是1,因此,集中差错是否同G(x)一样取决于其余的r-1位。如果所有的0、1排列情况出现概率均等,那么图片被更改而没有被检出的概率就是1/2^(r-1)。按照现在流行的四种已成为国际标准的多项式:V.41的CRC-CCITT、ANSI的CRC-16以及CRC-12和CRC-32,他们的r值分别为16、16、12、32,漏检的概率在0.00000000002~0.000244之间,这样的概率还是令人满意的。
经过以上的分析,采用CRC循环冗余校验码作为检测BMP位图是否被改动的印鉴水印是可靠、合理的。接下来就通过一段Microsoft Visual C++ 6.0的程序片段来完成对此算法的具体实现。
阅读(1413) | 评论(0) | 转发(0) |