一種Xml數(shù)據(jù)文件壓縮加密算法

在數(shù)據(jù)交換過(guò)程中,實(shí)現(xiàn)交換數(shù)據(jù)文件的壓縮、文件加密是提高傳輸效率、加強(qiáng)信息傳輸安全的重要手段,我們?cè)谘芯繕?gòu)建企業(yè)信息交換體系基礎(chǔ)上,針對(duì)xml數(shù)據(jù)文件,提出了一種混合壓縮加密算法,有效提高了數(shù)據(jù)交換的效率。

一、壓縮加密方法的分析

本文采用如下3個(gè)方法的組合加密,LZW數(shù)據(jù)壓縮方法;換位法;序列加密法。

1、LZW數(shù)據(jù)壓縮方法

LZW數(shù)據(jù)壓縮方法對(duì)原文進(jìn)行編碼,產(chǎn)生的壓縮文本保留的是碼本的序號(hào)。由于這些序號(hào)沒(méi)有自然語(yǔ)言的上下文關(guān)系,離開LZW算法破譯者不可能直接從保存的碼本序號(hào)中湊出原文。LZW方法的一個(gè)巧妙之處是并不保留碼本本身,解壓縮時(shí)碼本和原文從壓縮文本中遞推出來(lái)。一旦壓縮文本中有哪怕一個(gè)字節(jié)的錯(cuò)誤,都無(wú)法還原原文。利用LZW數(shù)據(jù)壓縮方法的加密是通過(guò)密鑰修改碼本編碼規(guī)則。沒(méi)有密鑰,即使通過(guò)LZW算法也不能恢復(fù)原文。另外,我們根據(jù)本應(yīng)用的特點(diǎn),對(duì)LZW算法做了改進(jìn)。如果破譯者不知道修改后LZW算法的細(xì)節(jié),也無(wú)法用密文還原出原文。

2、換位法

這是一個(gè)經(jīng)典的加密方法。根據(jù)應(yīng)用特點(diǎn),考慮到信道的數(shù)據(jù)傳輸效率,壓縮加密后的數(shù)據(jù)是數(shù)字串。我們用換位法,把密文中的多個(gè)數(shù)字對(duì)對(duì)換。置換表通過(guò)密鑰生成。換位法不依賴
于上下文關(guān)系,也與數(shù)據(jù)內(nèi)容無(wú)關(guān)。復(fù)合換位法的目的是進(jìn)一步把LZW生成的碼本序號(hào)搞亂,增加破譯者湊出原文的難度。

3、序列加密法

序列加密法的基本思想是依據(jù)原文和密鑰生成一個(gè)和原文長(zhǎng)度相同的隨機(jī)序列,然后隨機(jī)序列和原文通過(guò)某些運(yùn)行產(chǎn)生密文。隨機(jī)序列的產(chǎn)生方法有:線性反饋移位寄存器、線性同余產(chǎn)生器、非線性隨機(jī)數(shù)產(chǎn)生器、裁剪隨機(jī)數(shù)產(chǎn)生器、利用數(shù)學(xué)方法的隨機(jī)數(shù)產(chǎn)生器。我們采用線性反饋移位寄存器(LinearFee(11,ack ShiIL Regisler,L14SR)方法,其考慮是計(jì)算量小。

復(fù)合如上三種加密方法的核心是隱藏LZW壓縮方法產(chǎn)生的碼本序號(hào)。整個(gè)加密過(guò)程的關(guān)鍵點(diǎn)是:根據(jù)應(yīng)用特點(diǎn)對(duì)LZW的修改方法、根據(jù)密鑰對(duì)LZW編碼的修改方法、由密鑰生成置換表的方法、數(shù)據(jù)分段長(zhǎng)度n的大小、生成山、SR輸入的方法、確定山、SR初值的方法、偽隨機(jī)序列與原文的運(yùn)算方法。只要破譯者不知道這些細(xì)節(jié),無(wú)法恢復(fù)原文對(duì)應(yīng)的碼本序號(hào),破譯幾乎
是不可能的。

二、壓縮加密方法的實(shí)現(xiàn)

1、總體設(shè)計(jì)

常用壓縮算法有LZW、和llutfrnan方法。lluffrnan方法需要事先統(tǒng)計(jì)文本中字符串的頻率,根據(jù)字符串的頻率再編碼、壓縮。找出文本中多次重復(fù)的字符串本身是一個(gè)非常復(fù)雜的問(wèn)題,
所以,lluffmarri方法中,編碼的字符串較短,而且壓縮后的數(shù)據(jù)一般是二進(jìn)制的。LZW方法的巧妙之處在于在壓縮過(guò)程中找出多次重復(fù)的串,而且碼表并不需要保存到壓縮后的數(shù)據(jù)中。一般來(lái)說(shuō),LZW方法比lluffrnan方法更靈活,壓縮比也更小。我們的應(yīng)用中對(duì)壓縮的一個(gè)特別要求是壓縮后是阿拉伯?dāng)?shù)字串。如果用阿拉伯?dāng)?shù)字串表示lluffman方法中的編碼,則碼串會(huì)比原串更長(zhǎng),壓縮后的數(shù)據(jù)比原數(shù)據(jù)更大。

權(quán)衡各種利弊,我們認(rèn)為選擇LZW方法更合適。LZW方法有一個(gè)難以克服的缺點(diǎn),要對(duì)一個(gè)特定的字符串編碼,需要這個(gè)字符串出現(xiàn)的最小次數(shù)和串的長(zhǎng)度成正比。例如,要對(duì)“軍需物資油料部”實(shí)現(xiàn)編碼,則至少應(yīng)出現(xiàn)12次,在數(shù)據(jù)中前1 1次出現(xiàn)的這個(gè)字符串編碼效率都不高。這個(gè)詞在出現(xiàn)12次后,由于有了這個(gè)詞的編碼,以后的出現(xiàn)僅用一個(gè)碼表示,和原串相比小了很多。所以說(shuō),LZW方法對(duì)大的文件壓縮效果特別明顯。我們需要壓縮的數(shù)據(jù)是xrnl文件,而且一般較小,一些重復(fù)出現(xiàn)的字符串其重復(fù)次數(shù)也不是很多。因此直接用LZW方法效果并不理想。

為此,我們首先根據(jù)xml文件的特點(diǎn),對(duì)xrnl文件進(jìn)行預(yù)處理,然后對(duì)預(yù)處理生成的文件再用LZW方法壓縮。根據(jù)xml文件的格式,可以大大簡(jiǎn)化重復(fù)串的查找。找出這些重復(fù)串后剔除位置冗余已經(jīng)明顯減小了文件的長(zhǎng)度,再結(jié)合LZW方法,其壓縮效果非常明顯。由于壓縮后的數(shù)據(jù)必須是阿拉伯?dāng)?shù)字串,對(duì)某些非常小的xrnl文件壓縮效果一般。

2、xml文件的預(yù)處理算法

在xml文件中,域的標(biāo)示、域的內(nèi)容有些重復(fù)。由于在系統(tǒng)的應(yīng)用中,xml文件都較小,重復(fù)次數(shù)也不是很多,僅依靠LZW算法對(duì)這些重復(fù)詞編碼效率低。xml預(yù)處理過(guò)程如下:

第一步:提取域的標(biāo)示、域的內(nèi)容,形成一個(gè)標(biāo)示列表和一個(gè)內(nèi)容列表,列表中項(xiàng)的序號(hào)用ASCU碼表示,而非數(shù)字。例如“<aaa>xxx</aaa>”中,很容易找出標(biāo)示“aaa”和內(nèi)容“xxx”;

第二步:以在標(biāo)示、內(nèi)容列表中的序號(hào)替換文件中的域標(biāo)示和域內(nèi)容,同時(shí)只保留一個(gè)尖括號(hào)。例如:標(biāo)示“<aaa>”變?yōu)椤?lt;12”,而與其配對(duì)的標(biāo)示“也aa>”變?yōu)椤?gt;12”。其中“12”是標(biāo)示在列表中的序號(hào);

第三步:生成處理后的文件。文件的前面是標(biāo)示列表、和內(nèi)容列表,后面是替換后的xml文件體。

類C.XmLProcess用于完成xml的預(yù)處理,有兩個(gè)輸出函數(shù):

BOOLSimplifyXmlStr(char*cXmlStr)

BOOLCXmlProcess::RecoverXmlStr(char*cXmlStr)

分別用于預(yù)處理、還原xml文件。

3、壓縮算法的實(shí)現(xiàn)

為了便于傳輸,要求壓縮后的數(shù)據(jù)是0~9的數(shù)字。LZW算法生成的壓縮數(shù)據(jù)其實(shí)是壓縮過(guò)程中數(shù)據(jù)對(duì)應(yīng)的碼本序號(hào)。把這些碼本的序號(hào)用0~9數(shù)字表示,即可使輸出的數(shù)據(jù)全是數(shù)字。這樣做的不利是增加數(shù)據(jù)的冗余度,使輸出數(shù)據(jù)的長(zhǎng)度至少增加一倍。為了進(jìn)一步減小輸出數(shù)據(jù)的長(zhǎng)度,對(duì)使用頻率高的碼本用短的序號(hào)表示。例如,經(jīng)LZW壓縮后生成2000個(gè)碼本,則每個(gè)碼本序號(hào)需要用4位數(shù)字表示。但是從2001~9999間的序號(hào)是沒(méi)有用的,而全用三位數(shù)字表示碼本序號(hào)又不夠用。一個(gè)折衷辦法是,在0~2000個(gè)碼本之間找一個(gè)區(qū)間(簡(jiǎn)稱半碼區(qū)間),這個(gè)區(qū)間內(nèi)的碼本序號(hào)用兩位數(shù)字(簡(jiǎn)稱半碼)表示。自然找那些出現(xiàn)頻率高的碼本區(qū)間。這個(gè)區(qū)間的起始位置和長(zhǎng)度必須保存在輸出數(shù)據(jù)中。如果選擇的區(qū)間多,保存的區(qū)間起始位置、長(zhǎng)度數(shù)據(jù)也多。這對(duì)于較小的數(shù)據(jù)文件來(lái)說(shuō)并不劃算。所以只設(shè)定一個(gè)區(qū)間,其長(zhǎng)度由其碼本數(shù)決定。過(guò)程如下:

第一步:用標(biāo)準(zhǔn)LZW算法生成數(shù)據(jù)的碼序列。設(shè)碼本數(shù)為n;

第二步:計(jì)算半碼區(qū)間的最大長(zhǎng)度l(其值的大小依賴于n);

第三步:計(jì)算半碼區(qū)間的最佳起始位置s,使區(qū)間內(nèi)碼本出現(xiàn)頻率之和最大;

第四步:在輸出文件中保存碼本序號(hào)位數(shù)、n、l、s,以及輸入內(nèi)容的碼序列;

第五步:計(jì)算C.RC校驗(yàn)碼并保存到輸出數(shù)據(jù)中。

4、部分算法代碼實(shí)現(xiàn)

類CDgtLzw用于完成處理后的xml數(shù)據(jù)的壓縮,有兩個(gè)輸出函數(shù):

BOOLCompress(unsignedchar*cStr)

BOOLDeCompress(unsignedchar*cStr)

分別用于壓縮和解壓縮。

有幾個(gè)非輸出函數(shù),其中函數(shù)Compress(unsignedchar*cStr)用于完成標(biāo)準(zhǔn)的LZW壓縮算法,其過(guò)程如下:

BOOLCDgtLzw::Compress(unsignedchar*cStr)

{

inti,iCodeIdx;

//初始化,碼本數(shù)置零

m_iOutputCodeNum=0;

m_iOutputStrLen=0;

m_iCodeTableLen=c_sCodeRootLen;

//初始化,生成符號(hào)表,也作為初始的碼本

for(i=0;i<c_sCodeRootLen;i++)

{

m_CodeTable[i].iOutputTimes=0;

m_CodeTable[i].sCodeLen=1;

m_CodeTable[i].iCodePos=i;

}

intiStrLen=strlen((char*)cStr);

CODETABLECurCode;

CurCode.iCodeL=c_UselessUInt;

CurCode.ucCodeR=cStr[0];

i=1;

while(1)

{

iCodeIdx=GetCodeIndex(&CurCode);

if(iCodeIdx>=0)

{

//新加入的數(shù)據(jù)和前面的數(shù)據(jù)構(gòu)成一個(gè)已經(jīng)存在的碼本

if(i>=iStrLen)

{

//當(dāng)前字節(jié)是輸入數(shù)據(jù)的最后一個(gè),LZW結(jié)束

//outputthelastindexReSizeOutputCodeIndexBuf(m_iOutputCode-Num+1);

m_iOutputCodeIndexBuf[m_iOutputCode-Num++]=iCodeIdx;

//m_CodeTable[iCodeIdx].iOutputTimes+=1;

break;

}

i++;

}

else

{

//出現(xiàn)一個(gè)新的碼本

//addtocodetableReSizeCodeTable(m_iCodeTableLen+1);

m_CodeTable[m_iCodeTableLen]=CurCode;

//更新當(dāng)前碼本

m_CodeTable[m_iCodeTableLen].iOutputTimes=0;

m_iCodeTableLen++;

//outputtheindexReSizeOutputCodeIndexBuf(m_iOutputCodeNum+1);

//保存當(dāng)前碼本序號(hào)

m_iOutputCodeIndexBuf[m_iOutputCodeNum++]=CurCode.iCodeL;

m_CodeTable[CurCode.iCodeL].iOutputTimes+=1;

//[.c.]=kCurCode.iCodeL=c_UselessUInt;

//CurCode.ucCodeR=CurCode.ucCodeR;

}

}

//m_iMaxAppearedCode=m_iCodeTableLen-1;

while(m_CodeTable[m_iMaxAppearedCode].iOutputTimes<=0)

{

m_iMaxAppearedCode--;

//后面的碼沒(méi)有出現(xiàn)在輸出數(shù)據(jù)中

if(m_iMaxAppearedCode<=0)break;

}

m_iMinAppearedCode=0;

while(m_CodeTable[m_iMinAppearedCode].iOutputTimes<=0)

{

m_iMinAppearedCode++;

//前面的碼沒(méi)有出現(xiàn)在輸出數(shù)據(jù)中

if(m_iMinAppearedCode>=m_iMaxAppearedCode)break;

}

//計(jì)算用數(shù)字0~9表示的碼本序號(hào)的長(zhǎng)度

m_iOutputStrLen=0;

ReSizeOutputStrBuf(m_sCodeIndexStrLen*m_iOutputCode-Num+50);

//輸出碼轉(zhuǎn)換成數(shù)字文本ConvertCodeFromBinToDigit();

//ConvertCodeFromBinToDigitDirect();

//加密變換

CipherTransform(NULL);

returnTRUE;

}

小知識(shí)之LZW

LZW就是通過(guò)建立一個(gè)字符串表,用較短的代碼來(lái)表示較長(zhǎng)的字符串來(lái)實(shí)現(xiàn)壓縮。 LZW壓縮算法是Unisys的專利,有效期到2003年,所以對(duì)它的使用是有限制的。