2010-12-15 10 views
7

Última edición: He averiguado cuál era el problema (ver mi propia respuesta a continuación) pero no puedo marcar la pregunta como respondida, parecería. Si alguien puede responder las preguntas que tengo en mi respuesta a continuación, es decir, si esto es un error en Cython o es el comportamiento previsto de este Cython, marcaré que responda como aceptado, porque esa sería la lección más útil para obtener de este , EN MI HUMILDE OPINIÓN.Corrupción de datos: ¿Dónde está la falla?


En primer lugar, tengo que empezar diciendo que he estado tratando de resolver esto durante tres días, y sólo estoy golpeando mi cabeza contra la pared. Lo mejor que puedo decir de la documentación es que estoy haciendo las cosas correctamente. Obviamente, no puedo estar haciendo las cosas correctamente, porque si lo fuera, no tendría ningún problema (¿verdad?).

En cualquier caso, estoy trabajando en un enlace para mcrypt a Python. Debería funcionar tanto con Python 2 como con Python 3 (aunque no se ha probado para Python 2). Está disponible on my site, vinculado porque es demasiado grande para incluirlo en la publicación, y dado que no sé que estoy haciendo mal, ni siquiera puedo aislar cuál podría ser el código del problema. El script que muestra el problema es also on my site. La secuencia de comandos solo alimenta 100 bloques de nada más que la letra "a" (en cualquier tamaño de bloque que utilice el algoritmo de encriptación/modo de encriptación) y, por supuesto, debe obtener un bloque de "a" como resultado de la ida y vuelta. Pero no lo hace (siempre). Aquí se emite desde una única prueba de ello:

Wed Dec 15 10:35:44 EST 2010 
test.py:5: McryptSecurityWarning: get_key() is not recommended 
    return ''.join(['{:02x}'.format(x) for x in o.get_key()]) 

key: b'\x01ez\xd5\xa9\xf9\x1f)\xa0G\xd2\xf2Z\xfc{\x7fn\x02?,\x08\x1c\xc8\x03\x061X\xb5\xc9\x99\xd0\xca' 
key: b'\x01ez\xd5\xa9\xf9\x1f)\xa0G\xd2\xf2Z\xfc{\x7fn\x02?,\x08\x1c\xc8\x03\x061X\xb5\xc9\x99\xd0\xca' 
16 
self test result: 0 
enc parameters: {'salt': '6162636465666768', 'mode': 'cbc', 'algorithm': 'rijndael-128', 'iv': '61626364616263646162636461626364'} 
dec parameters: {'salt': '6162636465666768', 'mode': 'cbc', 'algorithm': 'rijndael-128', 'iv': '61626364616263646162636461626364'} 
enc key: 01657ad5a9f91f29a047d2f25afc7b7f6e023f2c081cc803063158b5c999d0ca 
dec key: 01657ad5a9f91f29a047d2f25afc7b7f6e023f2c081cc803063158b5c999d0ca 
Stats: 88/100 good packets (88.0%) 

#5: b'aaaaaaaaaaaaaaaa' != b'\xa6\xb8\xf9\td\x8db\xf6\x00Y"ST\xc6\x9b\xe7' 
#6: b'aaaaaaaaaaaaaaaa' != b'aaaaaaa1\[email protected]\x8d\xff\xf9\xafpy' 
#13: b'aaaaaaaaaaaaaaaa' != b'\xb9\xc8\xaf\x1f\xb8\x8c\x0b_\x15s\x9d\xecN,*w' 
#14: b'aaaaaaaaaaaaaaaa' != b'aaaaaaaaaaaaa\xeb?\x13' 
#49: b'aaaaaaaaaaaaaaaa' != b'_C\xf2\x15\xd5k\xe1XKIF5k\x82\xa4\xec' 
#50: b'aaaaaaaaaaaaaaaa' != b'aaaaaaaaaaa+\xdf>\x01\xee' 
#74: b'aaaaaaaaaaaaaaaa' != b'\x1c\xdf0\x05\xc7\x0b\xe9\x93H\xc5B\xd7\xcfj+\x03' 
#75: b'aaaaaaaaaaaaaaaa' != b'aaaaaaaaaaaaw+\xed\x0f' 
#79: b'aaaaaaaaaaaaaaaa' != b"\xf2\x89\x1ct\xe1\xeeBWo\xb4-\xb9\x085'\xef" 
#80: b'aaaaaaaaaaaaaaaa' != b'aaaaaaaaaaa\xcc\x01n\xf0<' 
#91: b'aaaaaaaaaaaaaaaa' != b'g\x02\x08\xbf\xa5\xd7\x90\xc1\x84D\xf3\x9d$a)\x06' 
#92: b'aaaaaaaaaaaaaaaa' != b'aaaaaaaaaaaaaaa\x01' 

La parte extraña es que es exactamente lo mismo para un (algoritmo, modo) par dado. Puedo cambiar el algoritmo y dará como resultado diferentes viajes de ida y vuelta, pero siempre igual para cada carrera cuando no cambio el algoritmo. Estoy absolutamente perplejo. Además, siempre hay dos bloques en una fila que están corruptos, como se puede ver en el resultado anterior: bloques 5 y 6, 13 y 14, etc. Entonces, hay un patrón, pero yo soy, por alguna razón, incapaz de entender a qué apunta exactamente ese patrón.

Me doy cuenta de que probablemente estoy preguntando mucho aquí: no puedo aislar un pequeño fragmento de código, y probablemente sea necesario familiarizarse con mcrypt y Python. Por desgracia, después de tres días de darme un golpe en la cabeza con esto, necesito alejarme del problema un poco, así que estoy publicando esto aquí con la esperanza de que, tal vez mientras estoy tomando un descanso de este problema, ya sea (a) alguien veré dónde introduje un error, (b) Podré ver mi error cuando vuelva al problema más tarde, o (c) alguien o yo mismo podamos encontrar el problema que tal vez no sea un error en mi código, pero un error en el proceso de enlace o la biblioteca en sí.

Una cosa que no he hecho es intentar usar otra versión de la biblioteca mcrypt. Estoy haciendo mi trabajo con Cython 0.13, Python 3.1 y mcrypt 2.5.8, todos distribuidos por Ubuntu en Ubuntu 10.10 (excepto Cython, que obtuve de PyPi). Pero administro sistemas con aplicaciones PHP que funcionan bien y uso mcrypt en Ubuntu 10.10 sin corrupción de datos, así que no tengo razones para creer que es la compilación de mcrypt, así que eso deja ... bueno, algo equivocado de mi parte en algún lado , Creo.

En cualquier caso, doy gracias a todos los que pueden ayudar. Estoy empezando a sentir que me estoy volviendo loco porque he estado trabajando en este problema casi sin parar durante días y tengo la sensación de que la solución probablemente esté justo frente a mí, pero no puedo verlo.

Editar: Alguien señaló que debería estar utilizando memcpy en lugar de strncpy. Lo hice, pero ahora, el script de prueba muestra que cada bloque es incorrecto. Colorearme aún más confundido que antes ...aquí está la nueva salida on pastebin.

Edit 2: He vuelto a la computadora y la he estado viendo de nuevo, y solo estoy agregando declaraciones impresas en todas partes para encontrar dónde podrían estar yendo las cosas mal. El código siguiente en la función raw_encrypt.step (entrada):.

cdef char* buffer = <char*>malloc(in_len) 
    print in_bin[:in_len] 
    memcpy(buffer, <const_void *>in_bin, in_len) 
    print "Before/after encryption" 
    print buffer[:in_len] 
    success = cmc.mcrypt_generic(self._mcStream, <void*>buffer, in_len) 
    print buffer[:in_len] 

La primera sentencia print muestra lo esperado, el texto plano que se pasa Sin embargo, el segundo muestra algo completamente diferente, que debe ser idéntico. Parece que está pasando algo con Cython que no entiendo completamente.

+3

Parece que ya hay enlaces a 'mcrypt' para Python: http://labix.org/python-mcrypt – katrielalex

+5

Virtual +1 para interrobang, real +1 para la pregunta. – delnan

+1

@katrielalex Sí, pero no están en Cython y no funcionan en Python 3, que es mi entorno de destino. Mi objetivo es reemplazar esas vinculaciones con un conjunto de enlaces Pythonic y mantenibles que funcione tanto para Python 2 como para Python 3. –

Respuesta

2

Oy, odio hacer esto (responda mi propia pregunta), pero encontré la respuesta: Es un capricho de Cython que voy a tener que investigar (no sé si es una intención) peculiaridad, o si es un error).

El problema viene con la línea memcpy. Eché el segundo parámetro a < const_void * >, que coincide con la definición de Cython en el archivo pxd, pero aparentemente hace que Cython compile el código de manera diferente que usando < char * >, lo que obliga a Cython a pasar un puntero a los bytes reales de (¿supongo?) un puntero al objeto/variable de Python en sí.

Así, en lugar de esto:

cdef char* buffer = <char*>malloc(in_len) 
memcpy(buffer, <const_void *>in_bin, in_len) 
success = cmc.mcrypt_generic(self._mcStream, <void*>buffer, in_len) 

Tiene que ser esta:

cdef char* buffer = <char*>malloc(in_len) 
memcpy(buffer, <char *>in_bin, in_len) 
success = cmc.mcrypt_generic(self._mcStream, <void*>buffer, in_len) 

Qué extraña peculiaridad. Sinceramente, esperaría que cualquier elenco apuntara a la misma ubicación, pero parece que el elenco también puede afectar el comportamiento.

0

He encontrado resultados similares a esto cuando sucedió algo gracioso con una combinación del uso del Vector de inicialización incorrecto (es decir, utilizando un IV diferente para el cifrado que para el descifrado) y la opción Ciphermode. Como un control de cordura, intente cambiar de CBC a ECB.

Otra posibilidad es que una de las variables se aleatorice (con una nueva semilla basada en el tiempo) cuando no debería ser. En ese caso, puede causar daños a los datos con mayor frecuencia al poner un retraso entre el paso de cifrado y descifrado.

+0

Curiosamente, obtengo los mismos bytes erróneos exactos que cuando uso el modo ECB. También la misma salida con retardos de tiempo (dormir aleatoriamente) entre los pasos de cifrado y descifrado ...buenas ideas, sin embargo. Gracias por las sugerencias. –

+0

Retiro esto: aún obtengo datos erróneos, pero no son idénticos a los bytes del modo CBC; son todos iguales para una sola ejecución, pero son diferentes de una ejecución en modo CBC. Todavía un montón de corruptos gobbledygook. –

Cuestiones relacionadas