任务描述
本关任务:编写程序,通过维吉尼亚密码将密文解密成文本。
相关知识
维吉尼亚密码——解密
凯撒密码的加密强度是很低的,只需简单地统计字频就可以破译。人们在单一凯撒密码的基础上扩展出多表密码,称为维吉尼亚
密码。
维吉尼亚密码引入了密钥
的概念,即根据密钥来决定用哪一行的密码表来进行替换,以此来对抗字频统计。
假如以上面第一行代表明文字母,左面第一列代表密钥字母,对如下明文加密:
TO BE OR NOT TO BE THAT IS THE QUESTION
当选定RELATIONS作为密钥时,加密过程是:明文一个字母为 T
,第一个密钥字母为 R
,因此可以找到在 R
行中代替 T
的为 K
,依此类推,得出对应关系如下:
密钥: RE LA TI ONS RE LA TION SR ELA TIONSREL
明文: TO BE OR NOT TO BE THAT IS THE QUESTION
密文: KS ME HZ BBL KS ME MPOG AJ XSE JCSFLZSY
小写字母采用相同的加密表格和加密方法(将上述方法里的大写字母换为小写字母即可)。
遇到数字时,可将其密钥字母在密码表中的偏移量对10取模的结果作为在数字表格中的偏移量,例如:
1
的密钥 R
在表格中的偏移量为 17
( A
在字母表里的偏移量为 0
),偏移量对 10
取模结果为 7
,加密时,查表格中 1
对应的列 1 2 3 4 5 6 7 8 9 0
中序号为 7
的数字,得到加密结果应为 8
, 9
的密钥“E”的偏移量是 4
,在 9
对应的行中序号为 4
的数字是 3
。
第1关:维吉尼亚密码——解密
import string
def vigenere_decrypt(text, key):
"""接收密文字符串和密钥字符串为参数,返回解密后的字符串.
解密时字母和数字以外的其他字符原样输出。"""
lower_tab = string.ascii_lowercase # 小写字母
upper_tab = string.ascii_uppercase # 大写字母
digit_tab = string.digits
#####################Begin#####################################
# 此处去掉注释符号“#”并补充你的代码
times = 0
plaintext = ''
for letter in text:
index = times % len(key)
offset = upper_tab.find(key[index])
if letter in upper_tab:
upper_offset = upper_tab[offset:] + upper_tab[:offset]
plaintext = plaintext + upper_tab[upper_offset.find(letter)]
times = times + 1
elif letter in lower_tab:
lower_offset = lower_tab[offset:] + lower_tab[:offset]
plaintext = plaintext + lower_tab[lower_offset.find(letter)]
times = times + 1
elif letter in digit_tab:
offset = offset % 10
digit_offset =digit_tab[offset:] + digit_tab[:offset]
plaintext = plaintext + digit_tab[digit_offset.find(letter)]
times = times + 1
else:
plaintext = plaintext + letter
return plaintext
#####################End#####################################
if __name__ == '__main__':
secret_key = input()
cipher_text = input()
plain_text = vigenere_decrypt(cipher_text, secret_key)
print(f'解密后得到的明文是{plain_text}')
第2关:维吉尼亚密码——加密
import string
def vigenere_encryption(text, key):
"""接收明文字符串和密钥字符串为参数,返回加密后的字符串.
加密时字母和数字以外的其他字符原样输出。
数字加密时,根据对应的密钥字符在字母表中的偏移量对10取模得到数字的偏移量。
例如当前数字为1,对应的密钥字母是R,R的偏移量是17,对10取模为7,1 2 3 4 5 6 7 8 9 0 中序号为7的数字是8,加密结果即为8"""
lower_tab = string.ascii_lowercase # 小写字母
upper_tab = string.ascii_uppercase # 大写字母
digit_tab = string.digits
# 补充你的代码
times = 0
cipher_text = ''
key = key.upper()
for letter in text:
index = times % len(key)
offset = upper_tab.find(key[index])
if letter in upper_tab:
upper_offset = upper_tab[offset:] + upper_tab[:offset]
cipher_text = cipher_text + upper_offset[upper_tab.find(letter)]
times = times + 1
elif letter in lower_tab:
lower_offset = lower_tab[offset:] + lower_tab[:offset]
cipher_text = cipher_text + lower_offset[upper_tab.find(letter.upper())]
times = times + 1
elif letter in digit_tab:
offset = upper_tab.find(key[index])
offset = offset % 10
digit_offset = digit_tab[offset:] + digit_tab[:offset]
cipher_text = cipher_text + digit_offset[digit_tab.find(letter)]
times = times + 1
else:
cipher_text = cipher_text + letter
return cipher_text
if __name__ == '__main__':
secret_key = input()
plain_text = input()
plain_to_cipher_text = vigenere_encryption(plain_text, secret_key)
print(f'加密后得到的密文是{plain_to_cipher_text}')
不负青春,不留遗憾,愿所有的磨练,都能让我们有所收获,有所成长!✌️