Python 中的凯撒密码函数
- 2025-01-13 08:53:00
- admin 原创
- 107
问题描述:
我正在尝试用 Python 创建一个简单的凯撒密码函数,该函数根据用户的输入移动字母并在末尾创建一个新的字符串。唯一的问题是最终的密文只显示最后一个移位的字符,而不是包含所有移位字符的整个字符串。
这是我的代码:
plainText = raw_input("What is your plaintext? ")
shift = int(raw_input("What is your shift? "))
def caesar(plainText, shift):
for ch in plainText:
if ch.isalpha():
stayInAlphabet = ord(ch) + shift
if stayInAlphabet > ord('z'):
stayInAlphabet -= 26
finalLetter = chr(stayInAlphabet)
cipherText = ""
cipherText += finalLetter
print "Your ciphertext is: ", cipherText
return cipherText
caesar(plainText, shift)
解决方案 1:
我意识到这个答案并没有真正回答你的问题,但我认为它还是有帮助的。以下是使用字符串方法实现凯撒密码的另一种方法:
def caesar(plaintext, shift):
alphabet = string.ascii_lowercase
shifted_alphabet = alphabet[shift:] + alphabet[:shift]
table = string.maketrans(alphabet, shifted_alphabet)
return plaintext.translate(table)
事实上,由于字符串方法是用 C 实现的,我们将看到此版本的性能有所提升。这就是我认为的“pythonic”做法。
解决方案 2:
您需要cipherText = ""
在 for 循环开始之前移动。每次循环时都要重置它。
def caesar(plainText, shift):
cipherText = ""
for ch in plainText:
if ch.isalpha():
stayInAlphabet = ord(ch) + shift
if stayInAlphabet > ord('z'):
stayInAlphabet -= 26
finalLetter = chr(stayInAlphabet)
cipherText += finalLetter
print "Your ciphertext is: ", cipherText
return cipherText
解决方案 3:
这是@amillerrhodes 答案中代码的改进版本,它适用于不同的字母,而不仅仅是小写字母:
def caesar(text, step, alphabets):
def shift(alphabet):
return alphabet[step:] + alphabet[:step]
shifted_alphabets = tuple(map(shift, alphabets))
joined_aphabets = ''.join(alphabets)
joined_shifted_alphabets = ''.join(shifted_alphabets)
table = str.maketrans(joined_aphabets, joined_shifted_alphabets)
return text.translate(table)
使用示例:
>>> import string
>>> alphabets = (string.ascii_lowercase, string.ascii_uppercase, string.digits)
>>> caesar('Abc-xyZ.012:789?жñç', step=4, alphabets=alphabets)
'Efg-bcD.456:123?жñç'
参考文献:
文档str.maketrans
。
文档str.translate
。图书馆
文档string
解决方案 4:
使用一些 ASCII 数字技巧:
# See http://ascii.cl/
upper = {ascii:chr(ascii) for ascii in range(65,91)}
lower = {ascii:chr(ascii) for ascii in range(97,123)}
digit = {ascii:chr(ascii) for ascii in range(48,58)}
def ceasar(s, k):
for c in s:
o = ord(c)
# Do not change symbols and digits
if (o not in upper and o not in lower) or o in digit:
yield o
else:
# If it's in the upper case and
# that the rotation is within the uppercase
if o in upper and o + k % 26 in upper:
yield o + k % 26
# If it's in the lower case and
# that the rotation is within the lowercase
elif o in lower and o + k % 26 in lower:
yield o + k % 26
# Otherwise move back 26 spaces after rotation.
else: # alphabet.
yield o + k % 26 -26
x = (''.join(map(chr, ceasar(s, k))))
print (x)
解决方案 5:
问题是你在每个循环迭代中将 cipherText 设置为空字符串,即
cipherText = ""
必须在循环之前移动。
解决方案 6:
正如其他人指出的那样,您正在 for 循环的迭代中重置 cipherText。将 cipherText 放在 for 循环开始之前将解决您的问题。
此外,还有另一种方法可以使用 Python 标准库来解决此问题。Python 标准库定义了一个函数 maketrans() 和一个对字符串进行操作的方法 Translation。
函数 maketrans() 创建转换表,可与 convert 方法一起使用,更有效地将一组字符转换为另一组字符。(引自 Python 标准库示例)。
import string
def caesar(plaintext, shift):
shift %= 26 # Values greater than 26 will wrap around
alphabet_lower = string.ascii_lowercase
alphabet_upper = string.ascii_uppercase
shifted_alphabet_lower = alphabet_lower[shift:] + alphabet_lower[:shift]
shifted_alphabet_upper = alphabet_upper[shift:] + alphabet_upper[:shift]
alphabet = alphabet_lower + alphabet_upper
shifted_alphabet = shifted_alphabet_lower + shifted_alphabet_upper
table = string.maketrans(alphabet, shifted_alphabet)
return plaintext.translate(table)
解决方案 7:
含电池
while 1:
phrase = raw_input("Could you please give me a phrase to encrypt?
")
if phrase == "" : break
print "Here it is your phrase, encrypted:"
print phrase.encode("rot_13")
print "Have a nice afternoon!"
https://docs.python.org/2/library/codecs.html#python-specific-encodings
Python 3 更新
优秀文档说
[现在
rot_13
] 编解码器提供文本转换:str
到str
映射。它不受str.encode()
(仅产生字节输出)支持。
或者换句话说,您必须encode
从codecs
模块导入并将要编码的字符串作为其第一个参数使用。
from codecs import decode
...
print(encode(phrase, 'rot13'))
解决方案 8:
这里,有一个更实用的方法:(如果使用 shift i 进行编码,则使用 -i 进行解码)
def ceasar(story, shift):
return ''.join([ # concentrate list to string
(lambda c, is_upper: c.upper() if is_upper else c) # if original char is upper case than convert result to upper case too
(
("abcdefghijklmnopqrstuvwxyz"*2)[ord(char.lower()) - ord('a') + shift % 26], # rotate char, this is extra easy since Python accepts list indexs below 0
char.isupper()
)
if char.isalpha() else char # if not in alphabet then don't change it
for char in story
])
解决方案 9:
plainText = raw_input("What is your plaintext? ")
shift = int(raw_input("What is your shift? "))
def caesar(plainText, shift):
for ch in plainText:
if ch.isalpha():
stayInAlphabet = ord(ch) + shift
if stayInAlphabet > ord('z'):
stayInAlphabet -= 26
finalLetter = chr(stayInAlphabet)
#####HERE YOU RESET CIPHERTEXT IN EACH ITERATION#####
cipherText = ""
cipherText += finalLetter
print "Your ciphertext is: ", cipherText
return cipherText
caesar(plainText, shift)
作为其他的,如果ch.isalpha()
你可以放finalLetter=ch
。
您应该删除以下行:cipherText = ""
干杯。
解决方案 10:
正如@I82much所说,您需要将其放在cipherText = ""
for循环之外。将其放在函数的开头。此外,您的程序有一个错误,当您输入大写字母时,它将导致它生成加密错误。尝试:
if ch.isalpha():
finalLetter = chr((ord(ch.lower()) - 97 + shift) % 26 + 97)
解决方案 11:
>>> def rotate(txt, key):
... def cipher(i, low=range(97,123), upper=range(65,91)):
... if i in low or i in upper:
... s = 65 if i in upper else 97
... i = (i - s + key) % 26 + s
... return chr(i)
... return ''.join([cipher(ord(s)) for s in txt])
# test
>>> rotate('abc', 2)
'cde'
>>> rotate('xyz', 2)
'zab'
>>> rotate('ab', 26)
'ab'
>>> rotate('Hello, World!', 7)
'Olssv, Dvysk!'
解决方案 12:
我很难记住 char 到 int 的转换,因此可以进行优化
def decryptCaesar(encrypted, shift):
minRange = ord('a')
decrypted = ""
for char in encrypted:
decrypted += chr(((ord(char) - minRange + shift) % 26) + minRange)
return decrypted
解决方案 13:
def encrypt():
plainText = input("What is your plaintext? ")
shift = int(input("What is your shift? "))
cipherText = ""
for ch in plainText:
if ch.isalpha():
stayInAlphabet = ord(ch) + shift
if stayInAlphabet > ord('z'):
stayInAlphabet -= 26
finalLetter = chr(stayInAlphabet)
cipherText += finalLetter
print ("Your ciphertext is: ", cipherText,"with a shift of",shift)
def decrypte():
encryption=input("enter in your encrypted code")
encryption_shift=int(input("enter in your encryption shift"))
cipherText1 = ""
for c in encryption:
if c.isalpha():
stayInAlphabet1 = ord(c) - encryption_shift
if stayInAlphabet1 > ord('z'):
stayInAlphabet1 += 26
finalLetter1 = chr(stayInAlphabet1)
cipherText1 += finalLetter1
print ("Your ciphertext is: ", cipherText1,"with negative shift of",encryption_shift)
from tkinter import *
menu=Tk()
menu.title("menu")
menu.geometry("300x300")
button1= Button(menu,text="encrypt",command=encrypt)
button1.pack()
button2= Button(menu,text="decrypt",command=decrypte)
button2.pack()
button3= Button(menu,text="exit",command=exit)
button3.pack()
menu.mainloop()
解决方案 14:
message = 'The quick brown fox jumped over the lazy dog. 1234567890 !@#$%^&*()_+-'
encrypted = ''.join(chr(ord(char)+3) for char in message)
decrypted = ''.join(chr(ord(char)-3) for char in encrypted)
print(encrypted)
print(decrypted)
# Wkh#txlfn#eurzq#ir{#mxpshg#ryhu#wkh#od}|#grj1#456789:;<3#$C&'(a)-+,b.0
# The quick brown fox jumped over the lazy dog. 1234567890 !@#$%^&*()_+-
解决方案 15:
def encrypt(text,shift):
'''
INPUT: text as a string and an integer for the shift value.
OUTPUT: The shifted text after being run through the Caeser cipher.
'''
# Create a placeholder list
encrypted_text = list(range(len(text)))
alphabet = string.ascii_lowercase
# Create shifted alphabet
first_half = alphabet[:shift]
second_half = alphabet[shift:]
shifted_alphabet = second_half+first_half
for i,letter in enumerate(text.lower()):
# Check for spaces or punctuation
if letter in alphabet:
# Find the original index position
original_index = alphabet.index(letter)
# Shifted letter
new_letter = shifted_alphabet[original_index]
encrypted_text[i] = new_letter
# Punctuation or space
else:
encrypted_text[i] = letter
return ''.join(encrypted_text)
解决方案 16:
例如解码字符串:
“ uo jxuhu!jxyi yi qd unqcfbu ev q squiqh syfxuh。muhu oek qrbu je tusetu yj?y xefu ie!iudt cu q cuiiqwu rqsa myjx jxu iqcu evviuj!”。
该消息的偏移量为 10。
下面的代码:
import string
alphabet = list(string.ascii_lowercase)
print(alphabet, len(alphabet))
messege = "xuo jxuhu! jxyi yi qd unqcfbu ev q squiqh syfxuh. muhu oek qrbu je tusetu yj? y xefu ie! iudt cu q cuiiqwu rqsa myjx jxu iqcu evviuj!"
messege_split = messege.split()
print(messege_split)
encrypted_messege = ""
position = 0
for i in messege_split:
for j in i:
if ord(j) < 65:
encrypted_messege += j
else:
for k in alphabet:
if j == k:
position = alphabet.index(k)
if (position + 10) >= len(alphabet):
encrypted_messege += alphabet[abs((position + 10) - len(alphabet))]
else:
encrypted_messege += alphabet[position + 10]
encrypted_messege += " "
print(encrypted_messege)
解码后的字符串:
“嘿!这是凯撒密码的一个例子。你能解码吗?我希望如此!给我发一条带有相同偏移量的消息!”
尝试一下!
解决方案 17:
使用循环生成器:
import string
from itertools import cycle
def caesarCipherEncryptor(s, key):
def generate_letters():
yield from cycle(string.ascii_lowercase)
def find_next(v, g, c):
# Eat up characters until we arrive at the plaintext character
while True:
if v == next(g):
break
# Increment the plaintext character by the count using the generator
try:
for _ in range(c):
item = next(g)
return item
except UnboundLocalError:
return v
return "".join([find_next(i, generate_letters(), key) for i in s])
# Outputs
>>> caesarCipherEncryptor("xyz", 3)
>>> 'abc'
解决方案 18:
from string import ascii_lowercase as alphabet
class CaesarCypher:
alpha_len = len(alphabet)
min_guess_rate = 0.2
加密和解密是同一件事。例如,当您想使用移位 10 来解密时,这意味着您可以使用移位 26 - 10 来加密。在这种情况下,循环将重复,如果您要移位整个字母表,结果将是相同的。此外,在这里我已经进行了大写字母和非字符
def __call__(self, text, offset, encrypt=True):
if not encrypt:
offset = self.alpha_len - offset
result = []
for letter in text:
if not letter.isalpha():
result.append(letter)
continue
letter_to_process = letter.lower()
processed_letter = self._encrypt_letter(letter_to_process, offset)
if letter.isupper():
processed_letter = processed_letter.upper()
result.append(processed_letter)
return ''.join(result)
所有加密最多都在这里进行。
def _encrypt_letter(self, letter, offset=0):
position = (alphabet.find(letter) + offset) % self.alpha_len
return alphabet[position]
这部分用于根力和通过字典频率猜测。
@staticmethod
def __how_many_do_i_know(text):
clean_words = filter(lambda x: x.isalpha(), text.split())
clean_words = ['\'{}\''.format(x) for x in clean_words]
cursor = conn.cursor()
query = 'SELECT COUNT(*) FROM mydictionary WHERE word IN ({})'.format(",".join(clean_words))
cursor.execute(query)
response = cursor.fetchone()[0]
return response / len(clean_words)
def guess_encode(self, text):
options = [self(text, offset, encrypt=False) for offset in range(self.alpha_len)]
best_option = [self.__how_many_do_i_know(option) for option in options]
best_key, guess_rate = max(enumerate(best_option), key=lambda x: x[-1])
guess_text = options[best_key]
return best_key, guess_rate, guess_text
解决方案 19:
import string
wrd=raw_input("Enter word").lower()
fwrd=""
for let in wrd:
fwrd+=string.ascii_lowercase[(string.ascii_lowercase).index(let)+3]
print"Original word",wrd
print"New word",fwrd
解决方案 20:
我认为这个答案对你有用:
def casear(a,key):
str=""
if key>26:
key%=26
for i in range(0,len(a)):
if a[i].isalpha():
b=ord(a[i])
b+=key
#if b>90: #if upper case letter ppear in your string
# c=b-90 #if upper case letter ppear in your string
# str+=chr(64+c) #if upper case letter ppear in your string
if b>122:
c=b-122
str+=chr(96+c)
else:
str+=chr(b)
else:
str+=a[i]
print str
a=raw_input()
key=int(input())
casear(a,key)
此功能根据给定的键将所有字母向右移动。
解决方案 21:
为什么不对移位输入使用函数反转,并将 plain_text 与移位连接起来,并将其作为密文输入:
Plain = int(input("enter a number "))
Rev = plain[::-1]
Cipher = " ".join(for cipher_text in Rev)
解决方案 22:
代码很大,但很容易理解。我认为它适合你的情况。
alphabet = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
class CaesarCipher(object):
def __init__(self, shift):
self.shift = shift
def encode(self, str):
encode = ''
str = str.lower()
for i in str:
if i in alphabet:
encode += alphabet[alphabet.index(i) + self.shift]
else:
encode += i
return encode.upper()
def decode(self, str):
decode = ''
str = str.lower()
for i in str:
if i in alphabet:
decode += alphabet[alphabet.index(i) - self.shift]
else:
decode += i
return decode.upper()
解决方案 23:
使用map
:
def caesar(text, key):
return ''.join(map(lambda c:
chr((ord(c.lower()) - ord('a') + key) % 26 + ord('a')) if c.isalpha() else ''
, text))
解决方案 24:
这个解决方案更直观,不需要使用ord
函数:
def caesar_cipher(raw_text, key):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
shifted_alphabet = alphabet[26-key:]+alphabet[0:(26-key)]
cipher_text = ""
for i in range(len(raw_text)):
char = raw_text[i]
idx = alphabet.find(char.upper())
if idx == -1:
cipher_text = cipher_text + char
elif char.islower():
cipher_text = cipher_text + shifted_alphabet[idx].lower()
else:
cipher_text = cipher_text + shifted_alphabet[idx]
return(cipher_text)
举个例子:
plain_text = "The quick brown fox jumps over the lazy dog!"
caesar_cipher(plain_text,3)
我们得到:
'Qeb nrfzh yoltk clu grjmp lsbo qeb ixwv ald!'
如果我们想解密它:
caesar_cipher(caesar_cipher(plain_text,3),26-3)
我们得到:
'The quick brown fox jumps over the lazy dog!'
更多详细信息请访问:https: //predictivehacks.com/caesar-cipher-in-python/
解决方案 25:
凱撒密碼
message = str(input("Enter you message:"))
shift = int(input("Enter a number:"))
# encode
stringValue = [ord(message) - 96 for message in message]
print(stringValue)
encode_msg_val = []
[encode_msg_val.append(int(stringValue[i])+shift) for i in
range(len(stringValue))]
encode_msg_array = []
for i in range(len(encode_msg_val)):
encode_val = encode_msg_val[i] + 96
encode_msg_array.append(chr(encode_val))
print(encode_msg_array)
encode_msg = ''.join(encode_msg_array)
# dedcode
[deocde_msg_val = [ord(encode_msg) - 96 for encode_msg in encode_msg]
decode_val = []
[decode_val.append(deocde_msg_val[i] - shift) for i in
range(len(deocde_msg_val))]
decode_msg_array = []
[decode_msg_array.append(decode_val[i] + 96) for i in range(len(decode_val))]
decode_msg_list = []
[decode_msg_list.append(chr(decode_msg_array[i])) for i in
range(len(decode_msg_array))]
decode_msg = ''.join(decode_msg_list)
print(decode_msg)
解决方案 26:
alph = 'abcdefghijklmnopqrstuvwxyz'
# shift = int(input("Please enter the number of places to shift:"))
shift = 15
text = "python is fun!"
alph_len = len(alph)
if shift >=0 and shift <= alph_len:
# text = input("Please enter a sentence:")
shifted_alph = alph[shift:] + alph[:shift] # rotate
text = text.lower()
crypted_text = ""
for letter in text:
if letter in alph:
ind = alph.index(letter)
crypted_letter = shifted_alph[ind]
else:
crypted_letter = letter
crypted_text += crypted_letter
print(crypted_text)
else:
print(f"You need to enter a number between 0 and {alph_len}!")
# eniwdc xh ujc! # output
解决方案 27:
key = 3
def wub():
def choice():
choice = input("Do you wish to Encrypt of Decrypt?")
choice = choice.lower()
if choice == "e" or "encrypt":
return choice
elif choice == "d" or "decrypt":
return choice
else:
print("Invalid response, please try again.")
choice()
def message():
user = input("Enter your message: ")
return user
def waffle(choice, message, key):
translated = ""
if choice == "e" or "encrypt":
for character in message:
num = ord(character)
num += key
translated += chr(num)
derek = open('Encrypted.txt', 'w')
derek.write(translated)
derek.close()
return translated
else:
for character in message:
num = ord(character)
num -= key
translated += chr(num)
return translated
choice = choice() #Runs function for encrypt/decrypt selection. Saves choice made.
message = message() #Run function for user to enter message. Saves message.
final = waffle(choice, message, key) #Runs function to translate message, using the choice, message and key variables)
print("
Operation complete!")
print(final)
wub()
解决方案 28:
alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
def caesar(original_text, shift_amount, encode_or_decode):
output_text = ""
if encode_or_decode == "decode":
shift_amount *= -1
for letter in original_text:
if letter not in alphabet:
output_text += letter
else:
shifted_position = alphabet.index(letter) + shift_amount
shifted_position %= len(alphabet)
output_text += alphabet[shifted_position]
print(f"Here is the {encode_or_decode}d result: {output_text}")
should_continue = True
while should_continue:
direction = input("Type 'encode' to encrypt, type 'decode' to decrypt:
").lower()
text = input("Type your message:
").lower()
shift = int(input("Type the shift number:
"))
print(f"You have shifted {shift} in {direction}d direction.")
caesar(original_text=text, shift_amount=shift, encode_or_decode=direction)
restart = input("Type 'yes' if you want to go again. Otherwise, type 'no'.
").lower()
if restart == "no":
should_continue = False
print("Thanks for playing!")