雙向流式加密算法

由于在很多加密應(yīng)用中,要求加密后的信息具有抗反向分析(例如,破解者知道明文的前若干個字符,在此基礎(chǔ)上力圖反推出密鑰,并解密其余的信息)的能力。本文提出了一種等長雙向流式加密算法,經(jīng)此算法加密的信息,其中的數(shù)據(jù)有全局的信息相關(guān)性,具有極強(qiáng)的抗反向分析以及差分分析的能力。

算法思路:

將加解密對象看成一個Byte數(shù)組A[N]。首先,我們從頭到尾對它進(jìn)行遍歷,將每次遇到的元素的值與前一個元素的值相加,并寫回到數(shù)組中。即 A[i]+A[i-1] => A[i] (i從2遞增到N)。這樣一來,后面元素的密文就直接依賴于之前的元素的值,達(dá)到了部分抗分析的目的。不難發(fā)現(xiàn),進(jìn)行一遍遍歷,只能讓數(shù)組中下標(biāo)大的元素對下標(biāo)小的元素形成依賴,而理想中的情況應(yīng)該是混合型的依賴。為了解決這個缺陷,我們很容易的想到了反向遍歷——思路與正向遍歷相同,只是起止點顛倒了一下: A[i]+A[i+1] => A[i] (i從N-1遞減到1)。經(jīng)過了正反兩次遍歷,數(shù)組中的每個元素的值都變得和其它所有元素的值相關(guān)了——由此,本算法也就相應(yīng)的具備了抗反向分析以及差分分析的能力。

在解決了信息相關(guān)性的問題之后,我們接下來需要思考的是,作為一個加密算法,密鑰如何被放置在上面的計算過程中去。首先,我分別在正向遍歷和反向遍歷中的求和計算過程中加入了一個長度為一個字節(jié)的密鑰,于是,加密過程就變成了:

(A[i]+A[i-1]) xor Key1 => A[i] ——正向遍歷
(A[i]+A[i+1]) xor Key2 => A[i] ——反向遍歷

讓我們再仔細(xì)看看遍歷過程,不難發(fā)現(xiàn),在每次遍歷中,都有一個位于起點的元素的值不會發(fā)生變化(正向遍歷中的A[1]以及逆向遍歷中的A[N])——這顯然是一個切入點——于是,我們在數(shù)組的兩端再各放一個“隱含元素”(A[0]、A[N+1]),也就是繼前面的Key1、Key2之后的第三個和第四個密鑰(它們的當(dāng)然也是一個字節(jié)),讓它們在兩次遍歷開始時分別作用于本來在遍歷中不會改變的起始元素值:

A[1]+Key3 => A[1] ——正向遍歷
A[N]+Key4 => A[N] ——反向遍歷

現(xiàn)在,密鑰的復(fù)雜度達(dá)到了四個字節(jié),即32Bits,能夠滿足一般的加解密要求(考慮到本算法的加密對象是以字節(jié)為單位的,比起那些以定長(64Bit或者更大)數(shù)據(jù)塊為加密對象的分塊加密算法,本算法的密鑰較之簡單一些是可以理解的),為了獲得更大的密鑰空間,用戶完全可以采用多次加密或者多層加密的方法(考慮到本算法的簡單性、易實現(xiàn)性,執(zhí)行速度較一般的分塊加密算法快很多,多層嵌套加密是一個很好的選擇)。需要指出的是,由于本算法每次的加密對象都是整個明文,而不是某個定長區(qū)塊,因此,多次嵌套加密后,所有的密鑰信息都會被密文均勻的包容(除非密鑰的信息量已經(jīng)大于明文的信息量——例如:用總共1024Bit的密鑰加密兩個字節(jié)的信息??。?,而不是在固定長度的區(qū)塊中相互混迭(嘿嘿,如果你用DES進(jìn)行嵌套加密的話就會發(fā)生這種情況)。

在下面的算法具體代碼中,我不但實現(xiàn)了上面的算法,還將多次加密直接封裝到了加解密過程之中。

{
名稱:雙向流式加密算法
作者:creation_zy
時間:2004-4
備注:
適當(dāng)?shù)脑龃髤?shù)Times(加密次數(shù))可以極大的提高密文的難解性,但是耗時也會成比例增加,對于長度在1KB以內(nèi)的文本,建議將其控制在1-1024之內(nèi)。如果采用嵌加密的話,可以進(jìn)一步控制在1-8之間。
}
procedure SeqEnc(var Str:String;Key:Integer;Times:Integer);
var
i,c,n:Integer;
Key1,Key2,Key3,Key4:Byte;
begin
n:=Length(Str);
if n=0 then
exit;
Key4:=Byte(Key shr 24);
Key3:=Byte(Key shr 16);
Key2:=Byte(Key shr 8);
Key1:=Byte(Key);
for c:=Times-1 downto 0 do
begin
Str[1]:=Char(Byte(Str[1])+Key3);
for i:=2 to n do
Str[i]:=Char((Byte(Str[i-1])+Byte(Str[i])) xor Key1);
Str[n]:=Char(Byte(Str[n])+Key4);
for i:=n-1 downto 1 do
Str[i]:=Char((Byte(Str[i+1])+Byte(Str[i])) xor Key2);
end;
end;
procedure SeqDec(var Str:String;Key:Integer;Times:Integer);
var
i,c,n:Integer;
Key1,Key2,Key3,Key4:Byte;
begin
n:=Length(Str);
if n=0 then
exit;
Key4:=Byte(Key shr 24);
Key3:=Byte(Key shr 16);
Key2:=Byte(Key shr 8);
Key1:=Byte(Key);
for c:=Times-1 downto 0 do
begin
for i:=1 to n-1 do
Str[i]:=Char(Byte(Str[i]) xor Key2-Byte(Str[i+1]));
Str[n]:=Char(Byte(Str[n])-Key4);
for i:=n downto 2 do
Str[i]:=Char(Byte(Str[i]) xor Key1-Byte(Str[i-1]));
Str[1]:=Char(Byte(Str[1])-Key3);
end;
end;

使用范例:
var
Str:String;
begin
Str:='名稱:雙向流式加密算法 作者:creation_zy';
SeqEnc(Str,6,927506813); //用密鑰927506813執(zhí)行6次加密
//Str已被加密
SeqEnc(Str,2,200498157); //用密鑰200498157執(zhí)行2次加密
//Str已被二次加密...
SeqDec(Str,2,200498157); //用密鑰200498157執(zhí)行2次解密
//解密第一層...
SeqDec(Str,6,927506813); //用密鑰927506813執(zhí)行6次解密
//解密第二層——Str已被還原
end;

加密效果例子:
Str: "VarPool.SetValue('TableStr',Str1);"
Key: 927506813
Times: 5

以十六進(jìn)制顯示的加密結(jié)果:
"5FC4305B6A2ABFA0B13DD4F5253AC697092853741E12175C2886C7682EB3F41D1AF3"

將明文Str中的 "1" 替換成 "2" 之后的加密結(jié)果(以十六進(jìn)制顯示):
"AA57C2B25A07C30EC1C955074C62A7D2CAB10709E89D2D907210FEEC2F9DB75AEDF2"