2012-06-10 29 views
7

Solo tengo conocimientos teóricos muy básicos sobre RSA.intercambio de clave pública/privada en PKCS n. ° 1 OAEP cifrado/descifrado

Al leer diferentes fuentes sobre cómo usarlo en la práctica, parecía que PKCS # 1 OAEP sería una buena cosa.

Para una implementación de prueba, utilizo Python con PyCrypto. P.ej. this es un ejemplo que usa PKCS # 1 OAEP.

Encriptar usando la clave pública y luego descifrar usando la clave privada funciona bien. P.ej. el público puede enviar algunos datos a la persona X con la clave privada.

Desde mi comprensión básica de cómo funciona RSA, pensé que solo puedo intercambiar la clave pública/privada, es decir, puedo usar la clave pública para encriptar y la clave privada para descifrar. P.ej. la persona X puede encriptar algunos datos con su propia clave privada y el público puede descifrarlos usando la clave pública. Si el descifrado funciona bien, esto proporciona algún tipo de prueba de que los datos provienen de la persona X.

PyCrypto se queja cuando trato de descifrar usando la clave pública.

De la lectura del código fuente PyCrypto, en la función _RSAKey._decrypt (here), parece que el propio objeto clave sabe si se trata de la clave privada o pública y la diferencia entre ellos (para mi sorpresa, de nuevo basado en mi muy básico Comprensión de RSA).

A partir de ahí, parece que podría hackear la función de descifrado para que use la clave pública. O algo diferente: podría simplemente intercambiar el exponente público e y el exponente privado d en los objetos clave.

Pero todo esto parece que no está destinado a ser utilizado/pirateado de esta manera. Así que quería preguntar aquí sobre mis malentendidos.

Además, sólo por curiosidad, me genera algunas teclas (RSA.generate(2048)) y se veía en n, e y d. En todos los casos, n y d fue muy grande, mientras que e fue en todos los casos constante (65537) (no me esperaba).

Supongo que de todo esto que realmente no debería simplemente intercambiar e y d.

Así que supongo que debería usar algún otro método para la firma como PKCS1_PSS.


algo de código para el cifrado/descifrado, si alguien está interesado: (. binstruct es un pequeño módulo que puede codificar/estructuras de datos de árboles decodificar - similar a JSON/BSON)

def randomString(l): 
    import random 
    return ''.join(chr(random.randint(0, 0xFF)) for i in range(l)) 

def genkeypair(): 
    from Crypto.PublicKey import RSA 
    key = RSA.generate(2048) 
    pubkey = key.publickey().exportKey("DER") 
    privkey = key.exportKey("DER") 
    return (pubkey,privkey) 

def encrypt(v, rsapubkey): 
    from Crypto.PublicKey import RSA 
    rsakey = RSA.importKey(rsapubkey) 
    from Crypto.Cipher import PKCS1_OAEP 
    rsa = PKCS1_OAEP.new(rsakey) 
    import binstruct 
    from array import array 
    aeskey = randomString(32) 
    iv = randomString(16) 
    from Crypto.Cipher import AES 
    aes = AES.new(aeskey, AES.MODE_CBC, iv) 
    data = binstruct.varEncode(v) 
    data += array("B", (0,) * (-len(data) % 16)) 
    out = binstruct.strEncode(rsa.encrypt(aeskey + iv)) 
    out += array("B", aes.encrypt(data)) 
    return out 

def decrypt(stream, rsaprivkey): 
    from array import array 
    from StringIO import StringIO 
    if isinstance(stream, array): stream = stream.tostring() 
    if isinstance(stream, str): stream = StringIO(stream) 
    from Crypto.PublicKey import RSA 
    rsakey = RSA.importKey(rsaprivkey) 
    from Crypto.Cipher import PKCS1_OAEP 
    rsa = PKCS1_OAEP.new(rsakey) 
    import binstruct 
    aesdata = binstruct.strDecode(stream) 
    aesdata = rsa.decrypt(aesdata) 
    aeskey = aesdata[0:32] 
    iv = aesdata[32:] 
    from Crypto.Cipher import AES 
    aes = AES.new(aeskey, AES.MODE_CBC, iv) 
    class Stream: 
     buffer = [] 
     def read1(self): 
      if len(self.buffer) == 0: 
       nextIn = stream.read(16) 
       self.buffer += list(aes.decrypt(nextIn)) 
      return self.buffer.pop(0) 
     def read(self, n): 
      return "".join([self.read1() for i in range(n)]) 
    v = binstruct.varDecode(Stream()) 
    return v 

Ahí es donde pensé que también podría usar encrypt con la clave privada yy decrypt con la clave pública.


La aplicación final con (esperemos) correcta firma/autenticación se puede encontrar here in binstruct.

+0

"PyCrypto se queja cuando trato de descifrar usando la clave pública". Por favor, sea más específico y muestre su código. –

+0

@GregS: Se levanta 'TypeError (" Sin clave privada ")' en '_RSAKey._decrypt'. Como puede ver en el código vinculado. Eso es lo que dije. Parece que necesita la clave privada para descifrar. – Albert

+0

Si solo tiene un conocimiento rudimentario de la criptografía, no sirve usar la API de forma que no se suponga que deba usarse. Tengo 10 años de experiencia e incluso soy bastante cuidadoso cuando uso bibliotecas criptográficas de una manera que se supone que no debo hacerlo, e intento evitar hacerlo siempre que sea posible. –

Respuesta

15

Su comprensión general sobre el intercambio de las funciones de clave pública y privada es correcta. Al final, RSA se basa en el hecho de que

m^(ed) congruent m (mod n) 

lo que normalmente se titula cifrado RSA es normalmente la operación

m^e mod n, 

elevar el mensaje a la fuente de e-XX donde e es la clave pública .

descifrado es entonces

(m^e)^d mod n, 

elevar el mensaje cifrado a la potencia d-ésimo siendo d la clave privada. Ahora, debido a las reglas de la potenciación y el hecho de que la multiplicación es conmutativa (éstos todavía mantienen en aritmética modular) tenemos que

m congruent (m^e)^d congruent m^(ed) congruent m^(de) congruent (m^d)^e, 

y por lo tanto se obtiene el mismo resultado si se aplican las operaciones en el orden inverso.

Tiene razón al suponer que la inversión lleva a las firmas digitales, porque todos pueden verificar ("descifrar") la firma con la clave pública e, por lo que el mensaje era auténtico solo si estaba "encriptado" (firmado) usando la clave privada correspondiente d.

Como resultado, PyCrypto solamente está tratando de evitar que confundir uno para el otro aquí, OpenSSL OpenSSL o Ruby le permiten for example a hacer las dos cosas: public_encrypt/public_decrypt y private_encrypt/private_decrypt.

Tanto para la teoría, ahora para por qué hay una buena razón para no permitirles usar indistintamente. Lo que acabo de describir a menudo se conoce como "libro de texto RSA" y todavía está lejos de ser seguro. Se deben tener en cuenta otras cosas para que el resultado se pueda utilizar en la práctica. Y es por eso que hay un signature package dedicado en PyCrypto; esto efectivamente hace lo que usted describió, pero también se ocupa de las cosas que mencioné. Si bien es bueno para nuestro entendimiento saber cómo funcionan estas cosas, siempre debemos usar dichos paquetes en la práctica porque ya se han hecho y se han corregido los errores que probablemente introduciríamos al hacer los nuestros.

En cuanto a por qué e es siempre 65537. Realmente no tiene que ser un valor fijo, pero comúnmente se elige como un número muy pequeño con tan pocos 1 en su representación binaria como sea posible (65537 es 10001) . En el pasado, e = 3 oe = 17 también se eligieron, pero se consideró que no eran seguros en la práctica porque podían atacarse simplemente tomando la tercera o la decimoséptima raíz del texto cifrado. Si e = 3 y m = 3, entonces 3^3 es 27, y no hace falta ser genio para darse cuenta de que m es 3 dado que el texto cifrado es 27, independientemente del módulo n (que suele ser mucho más grande). Entonces, el peligro reside en el hecho de que el texto cifrado, incluso después de la exponenciación, no cruza "el límite del módulo" y, por lo tanto, nos permite simplemente tomar la raíz e-ésima para llegar al mensaje original. Con módulos típicos de 1024 - 4096 bits, esto ya no es un problema con e = 65537.

Pocos 1 en la representación binaria también son buenos para el cálculo rápido. La exponenciación modular a menudo se implementa usando un algoritmo Multiply and Square, y el rendimiento es mejor para e pequeñas con pocos 1. ¿Por qué se elige de esta manera y no al revés, por ejemplo, tener una d pequeña con pocos 1? Bueno, para empezar, sería más fácil adivinar de esa manera. Una segunda ventaja es que con las firmas digitales, normalmente firmas un documento una vez pero lo verificas a menudo. Esto significa que m^d se realiza una vez, pero a menudo, de modo que la tarea común tiene un mejor rendimiento mientras que a la rara tarea se le permite realizar un trabajo deficiente.

Editar:

Usted preguntó si podía explicar con más detalle lo que esquemas como RSA-PSS hacen con el fin de ser seguro.

Al comparar lo que OAEP hace para el cifrado y lo que hace PSS para las firmas, los dos se ven bastante similares. Y de hecho lo son, ambos introducen la aleatorización en el proceso, lo que permite la seguridad demostrable de OAEP y PSS bajo ciertas suposiciones. También encontré esto paper para ser útil. La seguridad comprobable es una gran ventaja sobre el cifrado y firmas PKCS 1.5 de la vieja escuela, que se puede demostrar que no es segura de forma segura bajo los mismos supuestos (punto clave: ningún esquema determinista puede ser, la aleatorización es esencial). Una diferencia obvia entre la firma propuesta y los esquemas de encriptación es que los esquemas de firma siempre ordenan que el mensaje a ser firmado sea procesado primero. Esto tiene sentido no solo con respecto a la eficiencia, sino que también previene algunos ataques que de otro modo serían posibles. Y creo que eso lleva a la esencia de por qué siempre debemos usar esquemas de firmas para firmas y esquemas de encriptación para encriptación: los esquemas propuestos vienen con pruebas de seguridad adjuntas, nuestros esquemas hechos a mano no.

Los criptógrafos inventan esos esquemas para hacer que las vidas de nosotros simples mortales sean más fáciles: nos dan herramientas que idealmente no permiten ningún abuso o mal uso al reducir al mínimo el número de opciones. Por ejemplo, incluso si lograra obtener un buen esquema de firma utilizando RSA-OAEP, alguien que lo use podría no saber por qué deberían usar sus mensajes antes de aplicar la firma. Ese tipo de mal uso ni siquiera es una posibilidad con RSA-PSS.

También ha preguntado acerca de un buen material de lectura. Aunque este es un tema muy subjetivo, me gustó mucho siguientes:

El lado práctico:

  • Applied Cryptography - sigue siendo un clásico y vale la pena leer. Algunas personas de seguridad dicen que es peligroso porque lleva a las personas a creer que saben lo suficiente como para escribir su propia criptografía. Pero supongo que todos somos adultos, ¿verdad? Todavía es genial tener una idea sobre "lo que hay afuera"

  • - Tiene algunos buenos consejos prácticos y también menciona las advertencias al implementar el código de criptografía.

  • Handbook of Applied Cryptography - Es gratis y todavía tiene muchos buenos consejos, especialmente con respecto a las implementaciones.

La parte teórica:

  • Modern Cryptography - Es un híbrido entre la teoría y la práctica y tiene una gran cantidad de conocimiento de cómo las cosas pueden ir mal en la práctica.

  • Cryptography - Theory and Practice - esto fue un cambio de juego para mí, I amor este libro. Si solo lee un libro, que sea éste :)

  • Introduction to Modern Cryptography - hace un gran trabajo explicando "el enfoque moderno" y cómo funcionan realmente las pruebas de seguridad y bajo qué suposiciones.

  • Foundations of Cryptography I&II - si después del libro anterior aún no puede obtener suficiente de la teoría de las funciones de un solo sentido y amigos, este es su libro. Muy técnico

seguridad no es solamente la criptografía:

  • Security engineering - tiene numerosos ejemplos de cómo los principios de sonido pueden salir mal en la práctica

  • Information Security - Similar a la Ingeniería de Seguridad, lo que demuestra la seguridad en un ámbito más amplio que solo la criptografía.

Aparte de eso, trato de estar al día mediante la lectura de artículos recientes sobre las nuevas tecnologías de ataques, etc. he encontrado r/netsec interesante material muy útil, así como después de los investigadores y profesionales en Twitter, que publican regularmente .

Finalmente, si tiene tiempo, ¡tome los cursos de Criptografía en Coursera y Udacity! Creo que comenzarán de nuevo en las próximas semanas, son geniales, estoy seguro de que no te arrepentirás. Tenían muchos ejercicios prácticos que son muy divertidos e ilustran muy bien diversas formas de atacar las implementaciones de criptografía.

+1

¡Gracias, muy útiles! - "Hay que ocuparse de cosas adicionales [...]. [El paquete de firmas] también se encarga de las cosas que mencioné". Creo que no mencionaste esas cosas explícitamente o no las obtuve. ¿Qué cosas adicionales? Esp., ¿Por qué usar RSASSA-PSS y no RSAES-OAEP (encriptación con la clave privada) para la firma? - ¿Puede recomendar otras fuentes de lectura sobre cómo obtener algunos conocimientos teóricos de RSA sobre el uso práctico? (Porque incluso para la mayoría de las bibliotecas, la mayoría de las veces solo veo ejemplos triviales.) – Albert

+0

@Albert Actualicé mi respuesta, espero que ayude? – emboss

Cuestiones relacionadas