2. 维吉尼亚密码加密与解密

任务目标

实现维吉尼亚密码的加密与解密函数,支持任意大小写英文字母与任意非空密钥。密钥按字母序重复使用(A/a 对应位移 0,B/b 对应位移 1,依此类推),加密与解密共用同一套位移逻辑。最后通过一组已知明文/密钥/密文对验证正确性。

核心实现

def vigenere(text: str, key: str, decrypt: bool = False) -> str:
    """
    维吉尼亚密码加解密。
    text: 明文(encrypt=False)或密文(decrypt=True),仅处理英文字母,其余字符原样保留。
    key:  非空字符串,仅取其中的英文字母参与位移;若不含字母则抛出 ValueError。
    decrypt: False=加密,True=解密。
    """
    key_letters = [c for c in key if c.isalpha()]
    if not key_letters:
        raise ValueError("密钥必须包含至少一个英文字母")

    result = []
    key_idx = 0
    for ch in text:
        if ch.isalpha():
            # 统一转为大写计算位移量
            shift = ord(key_letters[key_idx % len(key_letters)].upper()) - ord('A')
            if decrypt:
                shift = -shift
            if ch.isupper():
                base = ord('A')
            else:
                base = ord('a')
            result.append(chr((ord(ch) - base + shift) % 26 + base))
            key_idx += 1
        else:
            result.append(ch)  # 非字母字符不参与加密,也不消耗密钥位置
    return ''.join(result)

def encrypt(plaintext: str, key: str) -> str:
    return vigenere(plaintext, key, decrypt=False)

def decrypt(ciphertext: str, key: str) -> str:
    return vigenere(ciphertext, key, decrypt=True)

运行与验证

将上述代码保存为 vigenere.py,在命令行执行以下验证脚本:

from vigenere import encrypt, decrypt

# 测试用例:明文、密钥、预期密文
cases = [
    ("HELLO", "KEY", "RIJVS"),
    ("hello, world!", "abc", "hfnlp, yosnd!"),
    ("AttackAtDawn", "LEMON", "LXFOPVEFRNHR"),
]

for plain, key, expected in cases:
    cipher = encrypt(plain, key)
    decrypted = decrypt(cipher, key)
    assert cipher == expected, f"加密失败: {plain} -> {cipher}, 期望 {expected}"
    assert decrypted == plain, f"解密失败: {cipher} -> {decrypted}, 期望 {plain}"
    print(f"通过: {plain!r} + {key!r} => {cipher!r}")

print("全部测试通过")

运行命令:python test_vigenere.py

通过条件:控制台输出三行“通过: ...”且最后一行显示“全部测试通过”,无断言错误。三个用例分别覆盖了纯大写、含小写与标点、大小写混合三种情况,同时验证了密钥重复使用(如 "abc" 在第二例中循环作用于 "hello, world!" 的字母部分)以及非字母字符原样保留、不消耗密钥位置的逻辑。

验证逻辑说明

加密时位移量为密钥字母的序号(A=0, B=1, ..., Z=25),解密时取相反数。密钥索引仅在遇到字母时递增,因此标点与空格不会干扰密钥对齐。上述测试中的预期密文均由位移规则独立推算得出,与代码逻辑一致。