1、栅栏加密
栅栏加密就是将明文按照顺序分成n组,然后将这n组,组合成一个密文。
比如以加密字符串“abcdefghijklm”为例
分成3组,加密过程如下:
a | d | g | j | m |
b | e | h | k |
|
c | f | i | l |
|
得到密文:adgjmbehkcfil
如果分成4组,那么结果如下:
a | e | i | m |
b | f | j |
|
c | g | k |
|
d | h | l |
|
得到密文:aeimbfjcgkdhl
加密是,以行优先,来生产数组(fence为分组数),那么从一个字符的位置加上fence的就等于密文中下一个字符的位置,例如pos(a)+4=pos(e)。所有加密算法大致如下:
string Crypt::doFenceEncrypt(string text) { //auther:cssalp&csalp //strreplace(text," ","*"); text=strnospace(text); string ret=""; int i=0,j=0; int len=text.length(); int step=fenceNum; for(i=0;i<fenceNum;i++) { j=i; while(j<len) { ret+=text.at(j); j+=fenceNum; } } //strreplace(ret,"*"," "); return ret; } |
2、 栅栏解密
栅栏解密相对要复杂些。在前面我们可以看到,加密是会产生一些空白,而这些空白在生产密文是并没有记录,所以这就造成了解密的复杂度。
我们以密文:aeimbfjcgkdhl为例
a | e | i | m |
b | f | j |
|
c | g | k |
|
d | h | l |
|
这里要定义一些变量,以方便讲解:
Len | 密文长度(这里是13) |
Column | Colum(这里是4) |
Fence(row) | 分组数(这里是4) |
Space_num | 空格数,也代表了有空格的行数 |
我们发现,a、e、i都可以通过通过移动column位找到相邻的下一个字符,而从b开始所有字符都可以通过移动column-1位找到相邻的下一个字符。但是对于m,必须提升考虑,因为如果m移动column为,本来应该为空的,应该结束的。但是在密文中为m,移动column位,是字符c(因为比没有标记空格的原因)。
针对这样的情况,可以按如下的方法处理。
首先找到startpos(在这里为b的位置),
如果当前位置>startpos,那么移动column-1
如果是最后一行,并且当前位置>startpos那么结束
如果当前位置<startpos,那么移动column
Startpos=(fence-space_num)*col+1;
Space_num=fence-(len%fence)
string Crypt::doFenceDecrypt(string fence) { string ret=""; int len=fence.length(); int spaceNum=(fenceNum-(len%fenceNum))%fenceNum;//number of space of last column l int col=0; if(spaceNum==0) { col=len/fenceNum; }else{ col=len/fenceNum+1; } int startpos=(fenceNum-spaceNum)*col;//should+1,ê?but for computor,ê? it's ok! int step=col; int i=0,j=0; for(i=0;i<col;i++) { //read column by column j=i; while(j<len) { ret+=fence.at(j); if(j>=startpos) { j+=(step-1); }else{ j+=step; }
if((i==(col-1))&&j>startpos) { //last colum and step over the startpos,then break; break; } } } return ret; }
|