Aquí está la pregunta:

En criptografía, un cifrado de sustitución simple es un método de encriptación en el que cada letra de una frase se reemplaza por una letra o secuencia de letras diferente. La frase se puede descifrar realizando el inverso de la sustitución.

En esta pregunta, implementaremos un cifrado de sustitución simple en el que un carácter (letra, número o símbolo especial) se sustituye por un número de dos dígitos entre 00 y 99 (inclusive). Por ejemplo, la letra ‘a 'podría cifrarse para convertirse en el número‘ 06', o el símbolo especial ‘! ' podría convertirse en el número ‘57 '.

Usaremos un diccionario para almacenar el mapeo entre cada carácter y su correspondiente forma encriptada. Es decir, las claves del diccionario serán los caracteres regulares (letras, números y símbolos especiales), y los valores serán las formas cifradas de los caracteres (los números de dos dígitos entre 00 y {{X1} }).

Su código debe implementar las siguientes cinco funciones para esta pregunta.

  • Nombre: crear un diccionario cifrado

    • Parámetros: Sin parámetros.
    • Valor de retorno: Un diccionario donde cada clave es un carácter regular y cada valor es un número aleatorio de dos dígitos entre 00 y 99, inclusive.
    • Lo que debe hacer: en la parte superior del código que se le proporcionó, se define la cadena LETTERS. Esta cadena contiene todas las letras, números y símbolos especiales que deberían ser claves en el diccionario. Tendrá que recorrer esta cadena y generar un número aleatorio de dos dígitos entre 00 y 99 para cada carácter. Los números de dos dígitos serán los valores en el diccionario; cada carácter (clave) tendrá un número (valor) de dos dígitos.
    • Tenga en cuenta que los números 0, 1, 2, ..., 9 no deben ser valores; en su lugar, deberían ser los números 00, 01, 02, ..., 09. Además, tenga en cuenta que cada personaje debe tener un número aleatorio único. Es decir, si el carácter ‘a 'se asigna al valor‘ 57', ningún otro personaje debe asignarse al valor ‘57 '. (Deberá usar algún tipo de bucle para seguir generando nuevos números aleatorios hasta que se encuentre uno único).
  • Nombre: cifrar

    • Parámetros: una cadena s.
    • Valor de retorno: la versión encriptada de la cadena s. Cada carácter de la cadena original s debe reemplazarse por su correspondiente número de dos dígitos en el diccionario cifrado.
  • Nombre: descifrar

    • Parámetros: una cadena s. Valor de retorno: la versión descifrada de la cadena s. Cada número de dos dígitos de las cadenas encriptadas debe reemplazarse por su carácter correspondiente en el diccionario cifrado. Tenga en cuenta que aquí, tenemos la forma encriptada (valor en el diccionario), y estamos buscando encontrar el carácter regular (clave 7 en el diccionario). Para hacer esto, necesitaremos usar la función de búsqueda inversa como se ve en la clase. Esta función se le ha proporcionado en el archivo cifrado.py incluido.

Escribiremos otras dos funciones para aumentar la fuerza de nuestro cifrado. Una función encriptará repetidamente la cadena varias veces. La otra función intentará descifrar la cadena, sin saber la cantidad de veces que se cifró (lo que anula el punto del cifrado más fuerte).

  • Nombre: cifrar varias veces

    • Parámetros: una cadena s y un valor entero n para la cantidad de veces que se encriptará la cadena.
    • Valor de retorno: la cadena s cifrada n veces. Es decir, la cadena se cifrará por primera vez, con cada carácter convertido en su representación de dos dígitos. Luego, la cadena encriptada se volverá a encriptar, con cada dígito convertido en su representación de dos dígitos. (Por lo tanto, la longitud de la cadena se duplicará después de cada cifrado). (Sugerencia: deberá llamar a su función de cifrado varias veces).
  • Nombre: descifrar varias veces

    • Parámetros: una cadena s.
    • Valor de retorno: la versión descifrada de la cadena s. Como no sabemos cuántas veces descifrar la cadena, seguiremos llamando a descifrar en la cadena hasta que la cadena contenga una palabra común en el idioma inglés. Se le ha proporcionado una lista de palabras comunes, PALABRAS COMUNES, en el archivo encryption.py. Si, después de descifrar una vez, la cadena contiene alguna palabra en esta lista, debe devolver inmediatamente la cadena descifrada. De lo contrario, continúe llamando descifrar en la cadena hasta que contenga una de las palabras comunes. (Asumiremos que la cadena completamente descifrada siempre contendrá al menos una palabra común).

Finalmente, al final del archivo encryption.py, notará algún código ya escrito para usted. Este código le pide al usuario que ingrese una cadena, luego llama a las diversas funciones e imprime lo que devuelve (para producir los ejemplos que se muestran a continuación). Debe modificar este código para que si el usuario ingresa una cadena que no contiene ninguna de las palabras en la lista de PALABRAS COMUNES, entonces el programa debería mostrar "Entrada inválida". y no ejecutar el resto del código. De lo contrario, el programa debería continuar con el resto del código. (Sugerencia: piense en la Tarea 1 y si / si no se ramifica).

Esto es lo que probé como entrada:

def reverse_lookup(d,v):
    for key in d:
        if d[key]==v:
            return key
    return None

LETTERS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()`~-=_+[]{}|;\':",./<>? '
def create_cypher_dictionary():
    random.seed(1337)
    cypher={}

    ar=[0]*100
    for c in LETTERS:
        n=random.randrange(0, 100, 1)
        while ar[n]!=0:
            n=random.randrange(0, 100, 1)
        ar[n]=1
        if n<10:
            cypher[c]=str('0')+str(n)
        else:
            cypher[c]=str(n)

    return cypher

def encrypt(s):
    cypher=create_cypher_dictionary()

    new_s=''
    for c in s:
        new_s=new_s+cypher[c]

    return new_s

def decrypt(s):
    cypher=create_cypher_dictionary()

    new_s=''
    for i in range(len(s)-1):
        c=s[i]+s[i+1]
        for cc in cypher:
            if cypher[cc]==c:
                new_s=new_s+cc

    return new_s

def encrypt_multiple_times(s,n):

    for i in range(n):
        s=encrypt(s)
    return s


COMMON_WORDS= ['the','be','to','of','and','a','in','that','have','I','it','for','not','on','with','he','as','you','do','at']

def check_common_words(s):
    for word in COMMON_WORDS:
        if word in s:
            return False
    return True

def decrypt_multiple_times(s):

    cypher=create_cypher_dictionary()
    while check_common_words(s):
        s=decrypt(s)

    return s


s=input('Enter text to encrypt:')

if check_common_words(s)==False:

    print("Encrypted string:", encrypt(s))
    print("Decrypted string:", decrypt(encrypt(s)))

    salted_s = encrypt_multiple_times(s, 2)

    print("Encrypted x2 string:", salted_s)
    print("Decrypted x2 string:", decrypt_multiple_times(salted_s))

else:
    print('Invalid input.')

Y aquí está el resultado que produjo:

Enter text to encrypt:The quick brown fox jumps over the lazy dog
Encrypted string:   36217337975199904937688489645037748985374251392613378908738437542173378179944437468993
Decrypted string: T0h-eK aq?u(iic,kg CbIr~o@wBn8 Jf~o>x[ fjLusm3p=sK Yocv<e/r" ?tjh-eK Yl-aizyy" fdboig
Encrypted x2 string: 9223712963929263666327296666666282669263230303820366238227629263638203660327926382712729926671232992926303666203639203829263278271296392926303296366668282829263822303666692
Decrypted x2 string: 36 21@7m313p7T997#5W1@9999990+4p9!3p7#6'8'8/4_8T906/45C013p7T7/4_8T9]8#5a3p7/4525W1i3p9N26#1i313p7'8T990_8T7m3_8/413p7#5Y4521@7m313p7'8#1@7T999b4+4+413p7/46'8T999!3

Sin embargo, se suponía que debía generar:

Enter text to encrypt: The quick brown fox jumps over the lazy dog.
Encrypted string: 0766546138001892056159999714256163973761640073940161973354996169665461919809956156975155
Decrypted string: The quick brown fox jumps over the lazy dog.
Encrypted x2 string: 3417626247536227487834342778713634476227477171717117275336 4762276248711748176227625334341748715334276227711748484753717162276271626247536227712771783471714762274762711747274747
Decrypted x2 string: The quick brown fox jumps over the lazy dog.

Estoy realmente sin ideas, si alguien puede ayudar, sería muy apreciado.

-2
Alex.G 19 feb. 2020 a las 04:22

2 respuestas

La mejor respuesta

Está convirtiendo el ASCII incorrectamente tomando solo un dígito a la vez, cuando debería tomar dos dígitos. Simplemente cambie el paso del bucle for en su función de descifrado:

def decrypt(s):
    cypher=create_cypher_dictionary()

    new_s=''
    for i in range(0,len(s)-1,2): # Make the for loop step 2 instead of 1 (default)
        c=s[i]+s[i+1]
        for cc in cypher:
            if cypher[cc]==c:
                new_s=new_s+cc

    return new_s
0
Thomas Reynolds 19 feb. 2020 a las 01:49

Puedes probar esto:

LETTERS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()`~-=_+[]{}|;\':",./<>? '

def create_cypher_dictionary():
    numbers = [ '%02d' % i for i in range(100) ]
    random.shuffle( numbers )
    return { a : b for a,b in zip( LETTERS, numbers ) }

def encrypt( cypher, string ) :
    return ''.join( cypher[ch] for ch in string )

def decrypt( cypher, string ) :
    inverse_cypher = { b : a for a,b in cypher.items() }
    return ''.join( inverse_cypher[a+b] for a,b in zip(*[iter(string)]*2) )

Comprobación:

>>> cypher = create_cypher_dictionary()
>>> encoded = encrypt( cypher, 'The quick brown fox jumps over the lazy dog' )
>>> encoded
'93684236886025540636378012826636001276363960074903361250428036306842367064856536261211'
>>> decrypt( cypher, encoded )
'The quick brown fox jumps over the lazy dog'
>>> 

Y sí, no puedes crear cypher cada vez, tienes que hacer uno y reutilizarlo, de lo contrario tus resultados serán algo aleatorios =)

0
lenik 19 feb. 2020 a las 01:50