¿Cómo cifrar correctamente un canal de comunicación entre un cliente y un servidor (sin SSL)?

6

Tengo un escaso conocimiento del mundo de la criptografía, estoy empezando a aprenderlo, así que soy un novato :)

Como proyecto para ingresar al campo de la criptografía, quiero escribir un programa cliente \ servidor que pueda enviar y recibir datos de manera segura ( es decir, encriptado).

Digamos que quiero cifrar el tráfico entre un cliente y un servidor o entre dos clientes. El servicio que estoy ejecutando solo puede hablar con el servidor u otro cliente (que también actúa como servidor) en un puerto conocido, el servidor básicamente busca una conexión en un lado en un puerto predeterminado.

Quiero que esos servicios puedan comunicarse entre sí sin la posibilidad de que un tercero que esté escuchando en la red pueda descifrar el contenido de la conversación o intente hacerse pasar por un servicio.

No estoy buscando una nueva forma de intercambiar claves (¿o debería hacerlo?), puedo hacer que las claves se guarden de forma segura en los servicios para que cuando x envíe un mensaje a y , y de vuelta, serán los únicos que podrán descifrar el contenido y la respuesta (fuera del curso, solo a un servicio verificado ).

  • nota al margen, la clave se puede guardar en el programa - codificada o puede generarse a partir de una combinación de cosas (por ejemplo, IP, nombre de computadora, nombre de usuario o cualquier otra combinación de constantes) que se puede pasar a la para que el cliente pueda generar la clave (digamos que estoy pasando la IP, el nombre de la computadora y una semilla aleatoria, habrá una fórmula conocida para crear la clave a partir de esos valores).

Necesito usar una clave simétrica para el cifrado, pero tal vez pueda intentar usar dos claves generadas previamente como SSL.

Sé que si estoy usando la misma clave una y otra vez, un tercero puede oler el tráfico y obtener la clave (matemática, ¿cómo se hace?), cuantos más datos recopile, más más fácil se pone (?).

Entonces, ¿qué debo hacer para prometer que nadie podrá obtener la clave de cifrado (finalmente leyendo los datos)? ¿Qué cifrado debo usar? ¿Qué más necesito saber antes de comenzar mi viaje?

    
pregunta YSY 21.09.2011 - 21:47
fuente

7 respuestas

8

Esto es en realidad más simple de lo que otros han sugerido, creo. Esto es lo que propongo:

  1. Genere un par de claves públicas / privadas usando RSA. Puedes hacer esto en cualquier máquina Unix usando openssl: openssl genrsa -out rsa.private 2048
  2. Distribuya la clave pública como codificada en su cliente.
  3. Cuando el cliente inicia sesión, el cliente genera una clave compartida privada (que también utiliza openssl u otra biblioteca de cifrado conocida) y la cifra mediante la clave pública.
  4. todos los datos entre el cliente y el servidor deben cifrarse con la nueva clave compartida durante la sesión.

Hay muchas otras cosas que puede hacer para fortalecerlo, como limitar la duración de la sesión a una o unas horas antes de volver a generar las claves, hacer que el servidor firme los resúmenes de mensajes, etc. Una comprensión completa del cifrado ayudará a entiende qué son y por qué, pero para una implementación básica (para datos de valor medio a bajo) esto debería ser suficiente.

    
respondido por el Charlie B 22.09.2011 - 04:46
fuente
2

Antes de codificar, lee esto: enlace

Esta pregunta es demasiado amplia como para caber en StackExchange desafortunadamente. La extensión y amplitud de la criptografía rara vez es atravesada por un solo individuo con algún grado de éxito sin educación formal en matemáticas, informática y un poco de ingeniería.

Este libro te ayudará a aprender conceptos comunes, errores comunes, fark-ups para aprender y ejemplos a seguir.

    
respondido por el MToecker 21.09.2011 - 23:15
fuente
1

Básicamente, quieres el tipo de túnel que proporciona SSL. Estas cosas son realmente difíciles de hacer bien.

SSL es un conjunto de varias cosas. Ahí está el túnel: una vez que hay un secreto compartido (lo que se llama el "secreto pre-maestro" en la especificación TLS ), y el cliente y el servidor acuerdan qué algoritmos usar, entonces los registros de datos individuales pueden cifrarse, como se describe en la sección 6 de la especificación. Para llegar a ese punto, SSL primero realiza el handshake en el que se produce la criptografía asimétrica. Si controlas tanto al cliente como al servidor, y ellos ya "inherentemente" comparten un secreto, puedes omitir el saludo.

Durante el protocolo de enlace, el servidor envía un blob opaco (el "certificado") que el cliente puede usar para obtener la clave pública del servidor. Si el cliente tiene un conocimiento inherente de la clave pública del servidor, entonces puede ignorar totalmente lo que el servidor envió y simplemente usar la clave pública conocida. La validación de certificados (que es un código bastante complejo) se usa solo cuando el cliente quiere descubrir dinámicamente la clave pública del servidor, eso es lo que ocurre en la Web. Pero, dependiendo de su situación, esto no es necesariamente necesario.

Ahora tenemos en este mismo sitio una pregunta sobre cómo funciona SSL con muy Respuestas descriptivas (si son largas).

Si SSL no te inspira, echa un vistazo a SSH. Mismos conceptos, distinto protocolo. SSH se describe sobre varios documentos; Comience con RFC 4251 .

    
respondido por el Thomas Pornin 05.10.2012 - 03:18
fuente
0

No se puede hacer sin un canal de distribución independiente para transferir una clave del servidor al cliente. Para SSL, eso es todo el proceso de firma de certificado y las claves públicas para los certificados raíz de la autoridad de certificación que se incluyen en los navegadores web. Entonces, su primer problema es averiguar cómo obtener una clave del servidor al cliente de una manera que no pueda ser interceptada por un ataque de intermediario (es decir, no a través de la red).

    
respondido por el Mike Scott 21.09.2011 - 22:00
fuente
0

Si desea crear un canal seguro sin SSL / TLS, lo que debe hacer es volver a implementar SSL / TLS, pieza por pieza. No hay mucho (si es que hay algo) que puedas dejar de lado y aún así quedarte con una conexión segura: todo lo que ves es el resultado de aproximadamente 20 años de uso, revisión y análisis.

Esta es una parte bastante significativa de la razón por la que siempre escuchas que no debes intentar rodar tu propio cifrado. Así que en lugar de comenzar de cero y hacer su propio camino, es mejor que se siente con las especificaciones y aprenda cómo funcionan las implementaciones existentes.

    
respondido por el tylerl 05.10.2012 - 10:32
fuente
0

Me doy cuenta de que este es un post antiguo, y espero que no me esté desviando mucho del tema, sino algunos pensamientos.

Primero, en términos de la configuración previa de las claves, es una mala práctica (especialmente si está utilizando un algoritmo de cifrado más antiguo como DES, donde es bastante sencillo recuperar la clave). Desea poder rotar las teclas periódicamente, no solo usarlas a perpetuidad; en principio, al menos, cuanto más tiempo use una clave, menos seguro se volverá (porque si alguien tuviera la oportunidad de descifrarla, podría descifrar todas las comunicaciones que usaban esa clave).

En la práctica, los algoritmos de cifrado modernos y correctamente aplicados son muy difíciles de descifrar y, en general, son bastante resistentes a los ataques de texto sin formato conocido y de texto sin formato elegido, pero a menudo hay otras formas de obtener una clave, como piratear - u obtener acceso físico al servidor o computadora cliente; Esto le ha pasado a muchas compañías recientemente (la más notoriamente Target). Esto es particularmente un problema si lo está almacenando en el servidor en texto plano. (Hay una gran cantidad de documentación sobre cómo almacenar cosas como esta correctamente. Nunca he intentado esto con una clave, pero imagino que querría seguir procedimientos similares a cómo asegurar una contraseña).

El problema de la rotación de claves no sería un problema si tiene acceso físico continuo tanto al cliente como al servidor, en cuyo caso podría actualizar las claves manualmente periódicamente (siempre y cuando no las haya olvidado). (Aún así, querrá almacenarlos de forma segura tanto en el cliente como en el servidor en caso de que alguien piratee el servidor o el cliente o tenga acceso físico a él).

Como regla general, tenga en cuenta que la seguridad siempre es relativa, por lo que cuando dice que quiere que esté segura, la pregunta siempre es "¿qué tan segura es?" Por ejemplo, tuve un proyecto en el que estábamos usando cifrados afines para cifrar ciertos valores de la base de datos; son fáciles de descifrar, pero nuestro propósito al usarlo fue evitar el acceso de observadores informales, no la malicia deliberada, por lo que fue suficiente. En la práctica, la mayoría de los algoritmos más antiguos como este ya están muy dañados y, en consecuencia, ofrecen muy poca protección contra un atacante suficientemente motivado con los recursos adecuados. Por ejemplo, DES (Estándar de cifrado de datos) es vulnerable a los ataques de "fuerza bruta" debido a que sus claves son demasiado cortas (incluso a finales de los años 90 fue posible forzar una clave en menos de 24 horas) pero aún así ofrece al menos alguna protección contra atacantes desmotivados.

Además, probablemente esto no sea exactamente lo que quisiste decir en tu publicación original, pero no hay algoritmos prácticos donde sea literalmente imposible que un atacante no descifre tu mensaje; para los algoritmos modernos como AES es poco práctico (pero no, en principio, imposible) por ahora. (Frase clave: "Por ahora". El DES estaba seguro cuando se desarrolló por primera vez, pero se rompió públicamente 20 años más tarde y es probable que los gobiernos lo hicieran mucho antes). Hay algunos algoritmos que tienen "seguridad perfecta", como el pad de una sola vez (donde tienes una clave completamente aleatoria que es tan larga como el mensaje que solo usas una vez); para estos, no es posible descubrir más sobre el mensaje que su longitud sin la clave. Sin embargo, este algoritmo no es práctico debido al problema de intercambio de claves; es tan difícil intercambiar la clave de forma segura como intercambiar el mensaje de forma segura.

    
respondido por el EJoshuaS 17.03.2016 - 18:39
fuente
0

En el pasado, enfrenté una situación similar y la resolví utilizando las solicitudes GET y POST a través de HTTPS. En Android, el código es bastante simple y el cliente HTTP incluido se encarga de todo lo relacionado con la criptografía, por lo que puede tener una solución fácil y evitar el "riesgo" de elaborar su propia criptografía

    
respondido por el Caterpillaraoz 12.07.2017 - 10:19
fuente

Lea otras preguntas en las etiquetas