Skip to content

Latest commit

 

History

History
142 lines (113 loc) · 6.03 KB

File metadata and controls

142 lines (113 loc) · 6.03 KB

六、凯撒密码

原文:http://inventwithpython.com/bigbookpython/project6.html

凯撒密码是朱利叶斯·凯撒使用的一种古老的加密算法。它通过将字母在字母表中移动一定的位置来加密字母。我们称移位的长度为密钥。比如,如果密钥是 3,那么A变成DB变成EC变成F,以此类推。要解密信息,你必须将加密的字母向相反的方向移动。这个程序让用户根据这个算法加密和解密信息。

在现代,凯撒密码不是很复杂,但这使它成为初学者的理想选择。Project 7 中的程序“凯撒破解”可以暴力破解所有 26 个可能的密钥来解密消息,即使你不知道原始密钥。此外,如果您使用密钥 13 对消息进行加密,凯撒密码将与项目 61 的“ROT 13 密码”相同。在en.wikipedia.org/wiki/Caesar_cipher了解更多关于凯撒密码的信息。如果你想学习一般的密码和密码破解,你可以阅读我的书《Python 密码破解指南》(NoStarch 出版社,2018)。

运行示例

当您运行caesarcipher.py时,输出将如下所示:

Caesar Cipher, by Al Sweigart email@protected
Do you want to (e)ncrypt or (d)ecrypt?
> e
Please enter the key (0 to 25) to use.
> 4
Enter the message to encrypt.
> Meet me by the rose bushes tonight.
QIIX QI FC XLI VSWI FYWLIW XSRMKLX.
Full encrypted text copied to clipboard.

Caesar Cipher, by Al Sweigart email@protected
Do you want to (e)ncrypt or (d)ecrypt?
> d
Please enter the key (0 to 26) to use.
> 4
Enter the message to decrypt.
> QIIX QI FC XLI VSWI FYWLIW XSRMKLX.
MEET ME BY THE ROSE BUSHES TONIGHT.
Full decrypted text copied to clipboard.

工作原理

像大多数密码程序一样,凯撒密码的工作原理是将字符翻译成数字,对这些数字执行一些数学运算,然后将数字翻译回文本字符。在密码的上下文中,我们称这些文本字符为符号。符号可以包括字母、数字和标点符号,每个符号都被赋予一个唯一的整数。在凯撒密码程序的情况下,符号都是字母,它们的整数就是它们在SYMBOLS字符串:'ABCDEFGHIJKLMNOPQRSTUVWXYZ'中的位置。

"""Caesar Cipher, by Al Sweigart email@protected
The Caesar cipher is a shift cipher that uses addition and subtraction
to encrypt and decrypt letters.
More info at: https://en.wikipedia.org/wiki/Caesar_cipher
View this code at https://nostarch.com/big-book-small-python-projects
Tags: short, beginner, cryptography, math"""

try:
   import pyperclip  # pyperclip copies text to the clipboard.
except ImportError:
    pass  # If pyperclip is not installed, do nothing. It's no big deal.

# Every possible symbol that can be encrypted/decrypted:
# (!) You can add numbers and punctuation marks to encrypt those
# symbols as well.
SYMBOLS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

print('Caesar Cipher, by Al Sweigart email@protected')
print('The Caesar cipher encrypts letters by shifting them over by a')
print('key number. For example, a key of 2 means the letter A is')
print('encrypted into C, the letter B encrypted into D, and so on.')
print()

# Let the user enter if they are encrypting or decrypting:
while True:  # Keep asking until the user enters e or d.
    print('Do you want to (e)ncrypt or (d)ecrypt?')
    response = input('> ').lower()
    if response.startswith('e'):
        mode = 'encrypt'
        break
    elif response.startswith('d'):
        mode = 'decrypt'
        break
    print('Please enter the letter e or d.')

# Let the user enter the key to use:
while True:  # Keep asking until the user enters a valid key.
    maxKey = len(SYMBOLS) - 1
    print('Please enter the key (0 to {}) to use.'.format(maxKey))
    response = input('> ').upper()
    if not response.isdecimal():
        continue

    if 0 <= int(response) < len(SYMBOLS):
        key = int(response)
        break

# Let the user enter the message to encrypt/decrypt:
print('Enter the message to {}.'.format(mode))
message = input('> ')

# Caesar cipher only works on uppercase letters:
message = message.upper()

# Stores the encrypted/decrypted form of the message:
translated = ''

# Encrypt/decrypt each symbol in the message:
for symbol in message:
    if symbol in SYMBOLS:
        # Get the encrypted (or decrypted) number for this symbol.
        num = SYMBOLS.find(symbol)  # Get the number of the symbol.
        if mode == 'encrypt':
            num = num + key
        elif mode == 'decrypt':
            num = num - key

        # Handle the wrap-around if num is larger than the length of
        # SYMBOLS or less than 0:
        if num >= len(SYMBOLS):
            num = num - len(SYMBOLS)
        elif num < 0:
            num = num + len(SYMBOLS)

        # Add encrypted/decrypted number's symbol to translated:
        translated = translated + SYMBOLS[num]
    else:
        # Just add the symbol without encrypting/decrypting:
        translated = translated + symbol

# Display the encrypted/decrypted string to the screen:
print(translated)

try:
    pyperclip.copy(translated)
    print('Full {}ed text copied to clipboard.'.format(mode))
except:
    pass  # Do nothing if pyperclip wasn't installed. 

在输入源代码并运行几次之后,尝试对其进行实验性的修改。标有(!)的注释对你可以做的小改变有建议。您可以通过向SYMBOLS字符串添加字符来扩展可加密的符号。

探索程序

试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。

  1. 如果把第 16 行的SYMBOLS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'改成SYMBOLS = 'ABC'会怎么样?
  2. 用密钥0加密一条消息会发生什么?
  3. 如果删除或注释掉第 56 行的translated = '',会得到什么错误信息?
  4. 如果删除或注释掉第 45 行的key = int(response),会得到什么错误信息?
  5. 如果把第 76 行的translated = translated + SYMBOLS[num]改成translated = translated + symbol会怎么样?