2023.10.25
Polybius
棋盘密码是利用波利比奥斯方阵(Polybius Square)进行加密的密码方式,产生于公元前两世纪的希腊,相传是世界上最早的一种密码。
密码表
1 | 2 | 3 | 4 | 5 | |
1 | A | B | C | D | E |
2 | F | G | H | I/J | K |
3 | L | M | N | O | P |
4 | Q | R | S | T | U |
5 | V | W | X | Y | Z |
示例:
以FLAG为例
F | L | A | G | |
密文 | 21 | 31 | 11 | 22 |
代码解密实现
def polybius_decode(ciphertext):
num,x,y = 0,0,0;text = '';checkerboard = ['abcde','fghik','lmnop','qrstu','vwxyz']
for i in ciphertext:
if ord('1')<=ord(i)<=ord('5'):
if num%2 == 0:
x = int(i)-1
else:
y = int(i)-1
text += checkerboard[x][y]
num += 1
else:
text += i
return text
ADFGX
1918年,第一次世界大战将要结束时,法军截获了一份德军电报,电文中的所有单词都由A、D、F、G、X五个字母拼成,因此被称为ADFGX密码。ADFGX密码是1918年3月由德军上校FritzNebel发明的,是结合了波利比奥斯方阵和置换密码的双重加密方案。
ADFGX密码之所以选择ADFGX一个字母,是因为它们译成摩斯密码时不容易混淆,可以降低传输错误的机率。
密码表:
A | D | F | G | X | |
A | A | B | C | D | E |
D | F | G | H | I/J | K |
F | L | M | N | O | P |
G | Q | R | S | T | U |
X | V | W | X | Y | Z |
ps:密码表的字母顺序可自定义
示例:
以明文:flag,秘钥:key
第一步:按密码表生成密码文
F | L | A | G | |
编码 | DA | FA | AA | DD |
第二步:利用移位钥匙加密
设钥匙字是“key”,将之写在新格子的第一列
再将上一阶段的密码文一列一列写进新方格里
k | e | y |
D | A | F |
A | A | A |
D | D |
第三步:
按照钥匙字字母顺序「eky」依次抄下该字下整行讯息,形成新密文
AAD DAD FA
解密脚本实现:
def adfgx_decode(ciphertext):
#判断密文是否正确
def check(ciphertext):
ciphertext = ''.join([i for i in ciphertext if i in dic])
if len(ciphertext) %2 != 0:return False
for i in ciphertext:
if i not in dic and i != ' ':return False
return True
dic={'A':0,'D':1,'F':2,'G':3,'X':4}
if not check(ciphertext):return '密文错误'
#判断关键字是否正确
while True:
key = input('请输入关键字:\n')
if not key.isalpha():return '关键字错误'
else:break
#判断棋盘是否正确
s = 'abcdefghiklmnopqrstuvwxyz'
while True:
s = input('请输入棋盘序列:\n')
if len(s) != 25 : print('长度错误,请重输')
else : break
checkerboard = [s[:5],s[5:10],s[10:15],s[15:20],s[20:]]
#分配密文
list_key,list_1= [i for i in key],[]
ciphertext = ''.join([i for i in ciphertext if i in dic])
num = len(ciphertext)
a = [1 for i in range(num%len(key))]+[0 for i in range(len(key)-num%len(key))]
for i in range(len(key)):
for j in range(i,len(key)):
if list_key[i] > list_key[j]:
list_key[i],list_key[j] = list_key[j],list_key[i]
a[i],a[j] = a[j],a[i]
for i in range(len(key)):
if a[i] == 1:
list_1.append(ciphertext[:num // len(key) + 1])
ciphertext = ciphertext[num // len(key) + 1:]
else:
list_1.append(ciphertext[:num // len(key)])
ciphertext = ciphertext[num // len(key):]
#还原排序
for i in range(len(key)):
for j in range(i,len(list_key)):
if key[i] == list_key[j]:
list_key[i],list_key[j] = list_key[j],list_key[i]
list_1[i],list_1[j] = list_1[j],list_1[i]
string_1 =''.join([list_1[j][i] for i in range(len(list_1[0])) for j in range(len(list_1)) if len(list_1[j]) > i])
#解码
text = ''
for i in range(len(string_1)):
if i %2 == 0: x = string_1[i]
else:
y = string_1[i]
text += checkerboard[dic[x]][dic[y]]
return text
ADFGVX
在 1918年 6月,再加入一个字 V 扩充。变成以 6 × 6 格共 36 个字符加密。这使得所有英文字母(不再将 I 和 J 视为同一个字)以及数字 0 到 9 都可混合使用。这次增改是因为以原来的加密法发送含有大量数字的简短信息有问题。
A | D | F | G | V | X | |
A | A | B | C | D | E | J |
D | F | G | H | I | K | 9 |
F | L | M | N | O | P | 8 |
G | Q | R | S | T | U | 7 |
V | V | W | X | Y | Z | 6 |
X | 0 | 1 | 2 | 3 | 4 | 5 |
编码规则和ADFGX一样
解码脚本实现:
def adfgvx_decode(ciphertext):
#判断密文是否正确
def check(ciphertext):
ciphertext = ''.join([i for i in ciphertext if i in dic])
if len(ciphertext) %2 != 0:return False
for i in ciphertext:
if i not in dic and i != ' ':return False
return True
dic={'A':0,'D':1,'F':2,'G':3,'V':4,'X':5}
if not check(ciphertext):return '密文错误'
#判断关键字是否正确
while True:
key = input('请输入关键字:\n')
if not key.isalnum():return '关键字错误'
else:break
#判断棋盘是否正确
s = 'abcdefghijklmnopqrstuvwxyz0123456789'
while True:
s = input('请输入棋盘序列:\n')
if len(s) != 36 : print('长度错误,请重输')
else : break
checkerboard = [s[:6],s[6:12],s[12:18],s[18:24],s[24:30],s[30:]]
#分配密文
list_key,list_1= [i for i in key],[]
ciphertext = ''.join([i for i in ciphertext if i in dic])
num = len(ciphertext)
a = [1 for i in range(num%len(key))]+[0 for i in range(len(key)-num%len(key))]
for i in range(len(key)):
for j in range(i,len(key)):
if list_key[i] > list_key[j]:
list_key[i],list_key[j] = list_key[j],list_key[i]
a[i],a[j] = a[j],a[i]
for i in range(len(key)):
if a[i] == 1:
list_1.append(ciphertext[:num // len(key) + 1])
ciphertext = ciphertext[num // len(key) + 1:]
else:
list_1.append(ciphertext[:num // len(key)])
ciphertext = ciphertext[num // len(key):]
#还原排序
for i in range(len(key)):
for j in range(i,len(list_key)):
if key[i] == list_key[j]:
list_key[i],list_key[j] = list_key[j],list_key[i]
list_1[i],list_1[j] = list_1[j],list_1[i]
string_1 =''.join([list_1[j][i] for i in range(len(list_1[0])) for j in range(len(list_1)) if len(list_1[j]) > i])
#解码
text = ''
for i in range(len(string_1)):
if i %2 == 0: x = string_1[i]
else:
y = string_1[i]
text += checkerboard[dic[x]][dic[y]]
return text