栅栏加解密是对较短字符串的一种处理方式,给定行数row,根据字符串长度计算出列数column,构成一个方阵。
加密过程:就是按列依次从上到下对明文进行排列,然后按照密钥对各行进行打乱,最后以行顺序从左至右进行合并形成密文。
解密过程:将上述过程进行逆推,对每一行根据密钥的顺序回复到原始的方阵的顺序,并从密文回复原始的方阵,最后按列的顺序从上到下从左至右解密。
具体实现如下:所有实现封装到一个类railfence中,初始化时可以指定列数和密钥,默认列数为2,无密钥。初始化函数如下:
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