凯撒密码Python项目



我正在尝试用Python做一个简单的Caesar密码。我的加密有效,但解密函数会给出字符串索引超出范围的错误消息。我已附上我的代码。欢迎任何评论。

import random
symbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!?@#$%^&*()' " 
def encrypt_symbols(message, key):
encrypted = ''
index = 0
for letter in message:
index = symbols.find(letter) + key
if index > len(symbols):
index = index - (len(symbols) + 1)
encrypted = encrypted + symbols[index] 
return encrypted

def decrypt(message, key):
decrypted = ''
index = 0
for letter in message:
index = symbols.find(letter) - key
if index < len(symbols):
index = index + len(symbols)
decrypted = decrypted + symbols[index]
return decrypted
test = "Wow! This works well, don't you think so?"
key = random.randrange(1, len(symbols))
secret_message = encrypt_symbols(test, key)
print(encrypt_symbols(test, key))
print(decrypt(secret_message, key))

最大的问题是不理解组/模运算和一些一次性错误。


在加密操作中:

if index > len(symbols):

索引从零开始,所以如果你有一个包含26个字符的普通ABC字母表,然后是Z,那么索引最高的字符将位于索引25。在上述代码中,假设最高索引为26;您需要使用>=

index = index - (len(symbols) + 1)

我有一个强烈的想法,这是为了弥补以前的错误,但失败了。大小为N的组中的任何运算都将使用模N运算。换句话说,对于ABC,这里减去N=26,而不是N=27,应该删除+ 1(以及一对括号,因为它们不再需要了)。


在解密操作中:

if index < len(symbols):

这是错误的假设;在[0,N)范围内的指数是可以的。你需要在这里与zero进行比较,因为减法可能会导致负值。

index = index + len(symbols)

现在,这就是错误发生的地方,因为您现在试图修复已经在正确范围内的值。幸运的是,您正确地使用了len(symbols)而不是len(symbols) + 1


通常,我们使用模运算符对群运算符进行编程。

所以你只需要:

index = (symbols.find(letter) + key) % len(symbols)

加密期间,以及:

index = (symbols.find(letter) - key) % len(symbols)

在解密期间-没有任何if语句。但是,由于您现在已经实现了组操作,您还可以输入加密例程-key而不是key,并获得解密例程";免费";。


备注:

  • 其他(基于C的)语言,如Java,可能会让%表示余数,这可能会产生负面结果,所以你必须使用另一个mod函数——幸运的是,Python使用了实际的模运算
  • 如果要在一个组中进行乘法或求幂,那么出于效率原因,应该使用modmulmodpow(即Python中有3个参数的pow())等函数

假设您的symbol[letter]是"a",键是2,你的加密会给你"a"+2="c",这是正确的

但用于解密index = symbols.find('c') - key=1但是,您将符号的长度添加到索引中,并超出的范围

if index < len(symbols)
index = index + len(symbols) 

而你实际上超出了范围你可以代替if index < len(symbols)

if index < 0

首先,您需要更换

index = index - (len(symbols) + 1)

带有

index = index - (len(symbols)) 

在您的encrypt_symbols函数中,然后用以下代码替换您的解密函数:

def decrypt(message, key):
decrypted = ''
index = 0
for letter in message:
index = symbols.find(letter) - key
if index < len(symbols):
index = index + (len(symbols))
index = (index%len(symbols))
decrypted = decrypted + symbols[index]
return decrypted

在这里,我使用了模(%)来获得secret_message的各个字母的余数。

此外,替换字母的最佳实践是使用模数并避免加法/减法。

使用模数供您参考的代码:

def encrypt_symbols(message, key):
encrypted = ''
index = 0
for letter in message:
index = symbols.find(letter) + key
if index > len(symbols):
index = (index%len(symbols))
encrypted = encrypted + symbols[index] 
return encrypted

def decrypt(message, key):
decrypted = ''
index = 0
for letter in message:
index = symbols.find(letter) - key
if index < len(symbols):
index = (index%len(symbols))
decrypted = decrypted + symbols[index]
return decrypted

请确保包含所有符号,否则find将用空格替换它。

我使用了以下

symbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!?@#$%^&*()', "

最新更新