栅栏密码
栅栏密码定义如下:
栅栏密码是将明文分成多个组,取每组第一个字符连成一段,每组第二个字符连成一段……最后将各段连接起来得到密文。
同时也可看成是按一定的步长取几组字符,再将这几组字符连起来得到密文。解密同理。
这里的步长就是密钥(栏数)。
传统栅栏密码的密钥是密文长度的因数。
如密文长度为n,加密密钥为x,则有n%x==0。且解密密钥即为n/x。
代码:
'''
遍历所有可能的栏数,并得到加/解密结果
'''
s = 'KYsd3js2E{a2jda}'
factors = [fac for fac in range(2, len(s)) if len(s)%fac == 0] #取得密文长度的所有因数
for fac in factors:
flag = ''
for i in range(fac): #按一定的步长取几组字符,并连接起来,这里组数就等于步长数
flag += s[i::fac]
print(str(fac)+'栏:'+flag)
W型栅栏密码
W型栅栏密码是栅栏密码的变种,
将明文按w型排列,然后将每一行的字母依次连起来组成密文,行数就是密钥。
解密则同样画出这个w型图案,将每一列的字母依次连接起来组成明文。
W型栅栏密码的密钥不只是密文长度的因数,任何小于密文长度大于1的整数都有可能。
代码:
'''
若知道栏数,则使用decode解密,若不知道,则使用crack_cipher遍历所有可能性
'''
def generate_w(string, n):
'''将字符排列成w型'''
array = [['.']*len(string) for i in range(n)] #生成初始矩阵
row = 0
upflag = False
for col in range(len(string)): #在矩阵上按w型画出string
array[row][col] = string[col]
if row == n-1:
upflag = True
if row == 0:
upflag = False
if upflag:
row -= 1
else:
row += 1
return array
def encode(string, n):
'''加密'''
array = generate_w(string, n)
msg = []
for row in range(n): #将每行的字符连起来
for col in range(len(string)):
if array[row][col] != '.':
msg.append(array[row][col])
return array, msg
def decode(string, n):
'''解密'''
array = generate_w(string, n)
sub = 0
for row in range(n): #将w型字符按行的顺序依次替换为string
for col in range(len(string)):
if array[row][col] != '.':
array[row][col] = string[sub]
sub += 1
msg = []
for col in range(len(string)): #以列的顺序依次连接各字符
for row in range(n):
if array[row][col] != '.':
msg.append(array[row][col])
return array, msg
def crack_cipher(string):
'''破解密码'''
for n in range(2,len(string)): #遍历所有可能的栏数
print(str(n)+'栏:'+''.join(decode(string, n)[1]))
if __name__ == "__main__":
string = "ccehgyaefnpeoobe{lcirg}epriec_ora_g"
n = 5 #栏数
#若不知道栏数,则遍历所有可能
# crack_cipher(string)
#若知道栏数
array,msg = decode(string, n)
# array,msg = encode(string, n)
for i in array: print(i)
print(''.join(msg))