【问题标题】:Vigenère Cipher function implementationPython 中的 Vigenère 密码函数
【发布时间】:2025-05-29 02:05:02
【问题描述】:

在观看了this tutorial 关于 Vigenere Cipher 的内容后,我(希望)了解了它的基本概念。我们想为一个字符串分配一个键,然后将字符串中的每个字母移动键中每个字母的(从 0 开始的)字母位置值。所以当用培根做key的时候,

Meet me in the park at eleven am
baco nb ac onb acon ba conbac on

变成

Negh zf av huf pcfx bt gzrwep oz

当我从头开始编写 Vigenere Cipher 时,我只知道第一步是将密钥分配给字符串。在执行此操作时,我想识别每个字符是否为 alpha,以便我可以保留字符串中的任何特殊字符(!、@、# 等)(如果有)。

text = input("Enter some text:")

def encrypt(text):

#key = bacon
encrypted = []
baconvalue = {'A':0, 'a':0, 'B':1, 'b':1, 'C':2, 'c':2, 'D':3, 'd':3, 'E':4, 'e':4, 'F':5, 'f':5, 'G':6, 'g':6, 'H':7, 'h':7, 'I':8, 'i':8, 'J':9, 'j':9, 'K':10, 'k':10, 'L':11, 'l':11, 'M':12, 'm':12, 'N': 13, 'n':13, 'O':14, 'o':14, 'P':15, 'p':15, 'Q':16, 'q':16, 'R':17, 'r':17, 'S':18, 's':18, 'T':19, 't':19, 'U':20, 'u':20, 'V':21, 'v':21, 'W':22, 'w':22, 'X':23, 'x':23, 'Y':24, 'y':24, 'Z':25, 'z':25 }


for letter in text:

#assign 'bacon' to text to get rotation value for each character
#preserve alpha characters

        if letter.isalpha():  

#character in string rotates x amount according to the corresponding value of char in bacon

            encrypted.append(letter, baconvalue)        

        else:    

            encrypted.append(letter)            

        return ''.join(encrypted)

print(encrypt(text,))

但是正如你所看到的,我不知道如何将 bacon 分配给字符串。我至少在正确的轨道上吗?如果可以的话请帮忙。谢谢你。

【问题讨论】:

  • 检查 alpha 是一个红鲱鱼,只会让您和您的实现感到困惑。使用模数或异或。这里有一组很好的练习,可以带你了解第 1 组的基本替换密码,如果你继续的话,还有更多 - cryptopals.com

标签: python function python-3.x encryption vigenere


【解决方案1】:

使用用户输入的值作为键来索引字符串的方法是创建一个变量starting_index 并将其设置为= 0。这样,迭代将从字符串中的第一个字符开始,您将能够使用您之前创建的 alphabet_pos 字典生成 rotation 值。

使用您的rotate 函数通过您创建的新旋转变量来旋转字母。如果在您的字典中找到该字母,encrypt 函数将附加此新字母并继续,直到您到达键中的最后一个索引值。然后它将加密的字母连接在一起。

alphabet_pos = {'A':0, 'a':0, 'B':1, 'b':1, 'C':2, 'c':2, 'D':3, 'd':3,
'E':4, 'e':4, 'F':5, 'f':5, 'G':6, 'g':6, 'H':7, 'h':7, 'I':8, 'i':8,
'J':9, 'j':9, 'K':10, 'k':10, 'L':11, 'l':11, 'M':12, 'm':12, 'N': 13,
'n':13, 'O':14, 'o':14, 'P':15, 'p':15, 'Q':16, 'q':16, 'R':17, 'r':17,
'S':18, 's':18, 'T':19, 't':19, 'U':20, 'u':20, 'V':21, 'v':21, 'W':22,
'w':22, 'X':23, 'x':23, 'Y':24, 'y':24, 'Z':25, 'z':25 }

def alphabet_position(letter):
    alphabet_pos = {'A':0, 'a':0, 'B':1, 'b':1, 'C':2, 'c':2, 'D':3,
'd':3, 'E':4, 'e':4, 'F':5, 'f':5, 'G':6, 'g':6, 'H':7, 'h':7, 'I':8,
'i':8, 'J':9, 'j':9, 'K':10, 'k':10, 'L':11, 'l':11, 'M':12, 'm':12,
'N': 13, 'n':13, 'O':14, 'o':14, 'P':15, 'p':15, 'Q':16, 'q':16,
'R':17, 'r':17, 'S':18, 's':18, 'T':19, 't':19, 'U':20, 'u':20, 'V':21,
'v':21, 'W':22, 'w':22, 'X':23, 'x':23, 'Y':24, 'y':24, 'Z':25, 'z':25
}
    pos = alphabet_pos[letter]
    return pos

def rotate(letter, rot):
    shift = 97 if letter.islower() else 65
    return chr((ord(letter) + rot - shift) % 26 + shift)

def encrypt(text, key):
    encrypted = []    
    starting_index = 0
    for letter in text:
    # if it's alphanumerical, keep it that way
    # find alphabet position
        rotation = alphabet_position(key[starting_index])
    # if it's a space or non-alphabetical character, append and move on
        if not letter in alphabet_pos:
            encrypted.append(letter)
        elif letter.isalpha():            
            encrypted.append(rotate(letter, rotation))             

    #if we've reached last index, reset to zero, otherwise + by 1
        if starting_index == (len(key) - 1): 
            starting_index = 0
        else: 
            starting_index += 1

    return ''.join(encrypted)    

text = input("Enter some text:")
key = input("Enter a key:")

print(encrypt(text,key))

【讨论】:

  • 我相信即使在非字母字符上,这也会迭代密钥,这可能是不可取的。不过,您可以通过在非字母字符的字母追加后添加 continue 来防止这种情况发生。
【解决方案2】:

可能我解密 Vigenère 密码的完整实现可能会帮助您和其他人(它使用具有自相关的弗里德曼测试方法)理解该方法。

您可以在这里找到代码:https://github.com/ferreirafabio/vigenere-py

【讨论】:

    【解决方案3】:

    所以我的代码很长但运行良好。希望对你有帮助

    def VigenereCiphre(line, key):
        isupper = True
        key = key.strip(' ')
        key = key.upper()
        k = list(key)
        print(k)
        returnLine = []
        i = 0
        for char in list(line):
    
            # Check if current character is symbol. If true append it to encrypted line
            if ord(char) < 65 or ord(char) > 122:
                returnLine.append(char)
            elif ord(char) > 90 and ord(char) < 97:
                returnLine.append(char)
            else:
                # Checks if letter is capital. If it's not, stores isupper to false and make it uppercase
                if ord(char) > 90:
                    isupper = False
                    char = char.upper()
    
                else:
                    isupper = True
    
                # Checks if key's index isn't out of range, if it is, set it back to 0
                print(isupper)
                if i == len(k):
                    i = 0
    
                # create new character based on it's value
    
                c = ord(char) + ord(k[i]) - 65
                if c > 90:
                    c = c - 25
    
                if isupper == False:
                    print(c)
                    c = c + 32
                    print(c)
    
                returnLine.append(chr(c))
    
                i += 1
    
        a = ''
        return a.join(returnLine)
    

    【讨论】: