栅栏加解密是对较短字符串的一种处理方式,给定行数row,根据字符串长度计算出列数column,构成一个方阵。
加密过程:就是按列依次从上到下对明文进行排列,然后按照密钥对各行进行打乱,最后以行顺序从左至右进行合并形成密文。
解密过程:将上述过程进行逆推,对每一行根据密钥的顺序回复到原始的方阵的顺序,并从密文回复原始的方阵,最后按列的顺序从上到下从左至右解密。
具体实现如下:所有实现封装到一个类railfence中,初始化时可以指定列数和密钥,默认列数为2,无密钥。初始化函数如下:
python" id="highlighter_149173">
1
2
3
4
5
6
7
8
9
|
def __init__( self , row = 2 , mask = none): if row < 2 : raise valueerror(u 'not acceptable row number or mask value' ) self .row = row if mask ! = none and not isinstance (mask, (types.stringtype, types.unicodetype)): raise valueerror(u 'not acceptable mask value' ) self .mask = mask self .length = 0 self .column = 0 |
加密过程,可以选择是否去除空白字符。首先是类型检查,列数计算等工作,核心是通过计算的参数得到gird这个二维列表表示的方阵,也是栅栏加密的核心。具体实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
def encrypt( self , src, nowhitespace = false): if not isinstance (src, (types.stringtype, types.unicodetype)): raise typeerror(u 'encryption src text is not string' ) if nowhitespace: self .nowhitespace = '' for i in src: if i in string.whitespace: continue self .nowhitespace + = i else : self .nowhitespace = src self .length = len ( self .nowhitespace) self .column = int (math.ceil( self .length / self .row)) try : self .__check() except exception, msg: print msg #get mask order self .__getorder() grid = [[] for i in range ( self .row)] for c in range ( self .column): endindex = (c + 1 ) * self .row if endindex > self .length: endindex = self .length r = self .nowhitespace[c * self .row : endindex] for i,j in enumerate (r): if self .mask ! = none and len ( self .order) > 0 : grid[ self .order[i]].append(j) else : grid[i].append(j) return ' '.join([' '.join(l) for l in grid]) |
其中主要的方法是按照列数遍历,每次从明文中取列数个数的字符串保存在遍历 r 中,其中需要处理最后一列的结束下标是否超过字符串长度。然后将这一列字符串依次按照顺序加入到方阵grid的各列对应位置。
解密过程复杂一些,因为有密钥对顺序的打乱,需要先恢复打乱的各行的顺序,得到之前的方阵之后,再按照列的顺序依次连接字符串得到解密后的字符串。具体实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
def decrypt( self , dst): if not isinstance (dst, (types.stringtype, types.unicodetype)): raise typeerror(u 'decryption dst text is not string' ) self .length = len (dst) self .column = int (math.ceil( self .length / self .row)) try : self .__check() except exception, msg: print msg #get mask order self .__getorder() grid = [[] for i in range ( self .row)] space = self .row * self .column - self .length ns = self .row - space preve = 0 for i in range ( self .row): if self .mask ! = none: s = preve o = 0 for x,y in enumerate ( self .order): if i = = y: o = x break if o < ns: e = s + self .column else : e = s + ( self .column - 1 ) r = dst[s : e] preve = e grid[o] = list (r) else : startindex = 0 endindex = 0 if i < self .row - space: startindex = i * self .column endindex = startindex + self .column else : startindex = ns * self .column + (i - ns) * ( self .column - 1 ) endindex = startindex + ( self .column - 1 ) r = dst[startindex:endindex] grid[i] = list (r) res = '' for c in range ( self .column): for i in range ( self .row): line = grid[i] if len (line) = = c: res + = ' ' else : res + = line[c] return res |
实际运行
测试代码如下,以4行加密,密钥为bcaf:
1
2
3
4
|
rf = railfence( 4 , 'bcaf' ) e = rf.encrypt( 'the anwser is wctf{c01umnar},if u is a big new,u can help us think more question,tks.' ) print "encrypt: " ,e print "decrypt: " , rf.decrypt(e) |
结果如下图:
说明:这里给出的解密过程是已知加密的列数,如果未知,只需要遍历列数,重复调用解密函数即可。
完整代码详见这里
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/u010487568/article/details/46642955