Función de cifrado César en Python

Estoy tratando de crear una simple función de Cifrado César en Python que desplace las letras en función de la información del usuario y cree una nueva cadena final al final. El único problema es que el texto cifrado final muestra solo el último carácter cambiado, no una cadena completa con todos los caracteres desplazados.

Aquí está mi código:

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) 

Me doy cuenta de que esta respuesta no responde realmente a tu pregunta, pero creo que es útil de todos modos. Aquí hay una forma alternativa de implementar el cifrado César con métodos de cadena:

 def caesar(plaintext, shift): alphabet = string.ascii_lowercase shifted_alphabet = alphabet[shift:] + alphabet[:shift] table = string.maketrans(alphabet, shifted_alphabet) return plaintext.translate(table) 

De hecho, dado que los métodos de cadena se implementan en C, veremos un aumento en el rendimiento con esta versión. Esto es lo que yo consideraría la forma “pythonica” de hacer esto.

cipherText = "" mover cipherText = "" antes del inicio del bucle for. Lo estás reiniciando cada vez a través del bucle.

 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 

Usando algunos trucos de números 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) 

El problema es que establece cipherText en una cadena vacía en cada iteración de ciclo, la línea

 cipherText = "" 

debe ser movido antes del bucle.

Como han señalado otros, estaba restableciendo el texto cifrado en la iteración del bucle for. La colocación de cipherText antes del inicio del bucle for resolverá su problema.

Además, hay un enfoque alternativo para resolver este problema utilizando la biblioteca estándar de Python. La biblioteca estándar de Python define una función maketrans () y un método de traducción que opera en cadenas.

La función maketrans () crea tablas de traducción que se pueden usar con el método de traducción para cambiar un conjunto de caracteres a otro de manera más eficiente. (Citado de la biblioteca estándar de Python por ejemplo).

 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) 

Baterias incluidas

 while 1: phrase = raw_input("Could you please give me a phrase to encrypt?\n") 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

Actualización de Python 3

Los buenos docs dicen

[Ahora el códec rot_13 ] proporciona una transformación de texto: un mapeo str a str . No es compatible con str.encode() (que solo produce salida de bytes).

O, en otras palabras, tiene que importar la encode del módulo de codecs y usarla con la cadena que se codificará como su primer argumento

 from codecs import decode ... print(encode(phrase, 'rot13')) 

Como lo dijo @ I82, necesitas tomar cipherText = "" fuera de tu bucle for. Colóquelo al comienzo de la función. Además, su progtwig tiene un error que hará que genere errores de cifrado cuando reciba letras mayúsculas como entrada. Tratar:

  if ch.isalpha(): finalLetter = chr((ord(ch.lower()) - 97 + shift) % 26 + 97) 

Aquí, una forma más funcional: (si usa Shift i para codificar, luego use -i para decodificar)

 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 ]) 
 >>> 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!' 
 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() 

Esta es una versión mejorada del código en la respuesta de @amillerrhodes que funciona con diferentes alfabetos, no solo en minúsculas:

 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) 

Ejemplo de uso:

 >>> import string >>> alphabets = (string.ascii_lowercase, string.ascii_uppercase, string.digits) >>> caesar('Abc-xyZ.012:789?жñç', step=4, alphabets=alphabets) 'Efg-bcD.456:123?жñç' 

Referencias:
Docs en str.maketrans .
Docs en str.translate .
Documentos en la biblioteca de string

 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) 

Como otra cosa, si ch.isalpha() puede poner finalLetter=ch .

Debes eliminar la línea: cipherText = ""

Aclamaciones.

 from string import ascii_lowercase as alphabet class CaesarCypher: alpha_len = len(alphabet) min_guess_rate = 0.2 

Cifrado y descifrado es una misma cosa. cuando quiere descifrar, por ejemplo, con el cambio 10, eso significa que puede cifrarlo con los cambios 26 – 10. En este caso, el ciclo se repetirá si va a cambiar todo el alfabeto, será el mismo. También aquí he procedido en mayúsculas y sin caracteres.

  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) 

todo el cifrado va aquí a lo sumo.

  def _encrypt_letter(self, letter, offset=0): position = (alphabet.find(letter) + offset) % self.alpha_len return alphabet[position] 

esta parte es para la fuerza de broot y adivinar a través de la frecuencia del diccionario.

  @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 
 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 

Según yo esta respuesta te es útil:

 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) 

Esta función desplaza todas las letras a la derecha de acuerdo con la clave dada.

Me cuesta mucho recordar las conversiones de char a int para que esto pueda optimizarse

 def decryptCaesar(encrypted, shift): minRange = ord('a') decrypted = "" for char in encrypted: decrypted += chr(((ord(char) - minRange + shift) % 26) + minRange) return decrypted 

¿Por qué no usar la función reversa en la entrada del cambio, y unir el texto llano con el cambio, e ingresarlo como el texto cifrado?

 Plain = int(input("enter a number ")) Rev = plain[::-1] Cipher = " ".join(for cipher_text in Rev) 
 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 !@#$%^&*()_+- 
 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("\n Operation complete!") print(final) wub()