Cifrado en aplicacion cliente-servidor

Iniciado por XKC, 1 Enero 2017, 19:57 PM

0 Miembros y 2 Visitantes están viendo este tema.

XKC

Hola a todos y feliz año lo primero.
Queria comentaros que esto haciendo una aplicacion que permite a clientes guardar archivos en un servidor remoto.Para ello utilizo C# en el cliente y PHP en el servidor. La cosa en que cuando envio los archivos los cifro con AES 256 y luego envio un nombre de usuario junto con la clave simetrica anterior al servidor, todo ello cifrado con una clave publica y que el programa cliente se descarga y lee (formato .pem).
Las dudas son las siguientes:
1.Me da problemas el cifrar con RSA en el cliente utilizando CryptoServiceProvider y a dscifrando con openssl en el servidor. ¿Esto debe dar problemas¿, ¿se puede hacer asi?
2.Otra duda es el vector de inicializacion del AES, es necesario que lo envie al servidor(osea, ¿es necesario para descifrar o solo para cifrar?), y supongo que si es asi ¿deberia ir cifrado con RSA?.
Perdonar mi ignorancia, es que estoy empezando con esto y llevo como todas las navidades buscando la solución y no la encuentro.
Muchas gracias por vuestra atención.
Saludos.
Para poder atacar y vencer con seguridad, ataca donde ellos no puedan defenderse.
Para defenderte y resistir firme, defiéndete en donde ellos no atacarán.

kub0x

Buenas XKC vamos por partes,

Citarcuando envio los archivos los cifro con AES 256 y luego envio un nombre de usuario junto con la clave simetrica anterior al servidor, todo ello cifrado con una clave publica y que el programa cliente se descarga y lee (formato .pem).

Cifras el archivo con AES-256, la key AES la cifras con la pública del servidor y el nombre del usuario con la AES. Pero no veo que se haga ninguna firma digital sobre el mismo, por lo tanto cualquiera que esté escuchando puede alterar la conexión ya que tu mecanismo no provee de autenticación. Un atacante sería capaz de sustituir ese archivo cifrado por otro distinto con otra AES distinta y aun así el servidor lo almacenaría.

De alguna forma cada usuario tiene que tener un par de claves privada/pública siendo la pública almacenada en el server para que valide las firmas digitales. El atacante para impersonar al usuario ahora tendría que tener la privada del usuario.

CitarMe da problemas el cifrar con RSA en el cliente utilizando CryptoServiceProvider y a dscifrando con openssl en el servidor. ¿Esto debe dar problemas¿, ¿se puede hacer asi?
Puede dar problemas, sí. Tendrás que asegurarte leyendo la documentación de ambas APIs de que utilizan el mismo estándar y parametrización para que ambas sean comunes.

Citar2.Otra duda es el vector de inicializacion del AES, es necesario que lo envie al servidor(osea, ¿es necesario para descifrar o solo para cifrar?), y supongo que si es asi ¿deberia ir cifrado con RSA?.

El IV (initialization vector) se utiliza para que dos plaintexts bajo la misma clave den dos ciphertexts distintos. Por eso es importante usar IVs distintos si se reutiliza la misma clave simétrica varias veces. El IV se suele enviar concatenado al ciphertext en su inicio es decir IV || Ciphertext y debe viajar en plano ya que es un valor trivial, no deberías cifrarlo aunque si así lo deseas eres libre de hacerlo. Sin el IV te quedará un bloque sin poder descifrar lo que se traduce en 128 bits perdidos.

Saludos!
Viejos siempre viejos,
Ellos tienen el poder,
Y la juventud,
¡En el ataúd! Criaturas Al poder.

Visita mi perfil en ResearchGate


XKC

Cita de: kub0x en  1 Enero 2017, 20:54 PM
Buenas XKC vamos por partes,

Cifras el archivo con AES-256, la key AES la cifras con la pública del servidor y el nombre del usuario con la AES. Pero no veo que se haga ninguna firma digital sobre el mismo, por lo tanto cualquiera que esté escuchando puede alterar la conexión ya que tu mecanismo no provee de autenticación. Un atacante sería capaz de sustituir ese archivo cifrado por otro distinto con otra AES distinta y aun así el servidor lo almacenaría.

De alguna forma cada usuario tiene que tener un par de claves privada/pública siendo la pública almacenada en el server para que valide las firmas digitales. El atacante para impersonar al usuario ahora tendría que tener la privada del usuario.
Puede dar problemas, sí. Tendrás que asegurarte leyendo la documentación de ambas APIs de que utilizan el mismo estándar y parametrización para que ambas sean comunes.

El IV (initialization vector) se utiliza para que dos plaintexts bajo la misma clave den dos ciphertexts distintos. Por eso es importante usar IVs distintos si se reutiliza la misma clave simétrica varias veces. El IV se suele enviar concatenado al ciphertext en su inicio es decir IV || Ciphertext y debe viajar en plano ya que es un valor trivial, no deberías cifrarlo aunque si así lo deseas eres libre de hacerlo. Sin el IV te quedará un bloque sin poder descifrar lo que se traduce en 128 bits perdidos.

Saludos!
Muchisimas gracias, ahora me quedan las cosas mas claras.
Osea que si no tengo el IV el archivo quedaria inutilizado porque no podria descrifralo completo al faltarme el ultimo bloque, ¿no es asi?.
Y lo de las claves no lo habia ni pensado, asi que por cada cliente generare su propio par.
Gracias por la velocidad, asi da gusto jejeje.
Saludos.
Para poder atacar y vencer con seguridad, ataca donde ellos no puedan defenderse.
Para defenderte y resistir firme, defiéndete en donde ellos no atacarán.

kub0x

CitarOsea que si no tengo el IV el archivo quedaria inutilizado porque no podria descrifralo completo al faltarme el ultimo bloque, ¿no es asi?.

Así es, pero es el primer bloque no el último. Acabarías descifrarando el documento casi en su totalidad, pero perderías información. Lo mismo sucede si se utiliza un IV distinto al original. Si te interesa aprender lo básico sobre cifrado por bloque -> https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation

Cualquier duda adicional que te surja posteala por aquí y veremos en que podemos ayudarte.

Saludos!
Viejos siempre viejos,
Ellos tienen el poder,
Y la juventud,
¡En el ataúd! Criaturas Al poder.

Visita mi perfil en ResearchGate


XKC

#4
Hola de nuevo y lo siento por volver a molestar.
Lo primero mil gracias a kub0x porque no sabes lo que me has ayudado.
Tengo la aplicacion casi terminada, ya funciona AES(cifra y descifra perfectamente).
Solo una cosa mas(lo siento por ser tan pesado), ahora tengo una clase MyRSA que se encarga de descargar la clave privada del servidor y cifrar con RSA.

La clase RSA del cliente(C#):

using System;
using System.Text;
using System.Security.Cryptography;


namespace myApp
{
    class MyRSA
    {
        public static MyRSA getMyRSA()
        {
            if (_Instance == null)
            {
                _Instance = new MyRSA();
            }
            return _Instance;
        }
        public Boolean setPubKey(string url)
        {
            System.Net.WebClient wc = new System.Net.WebClient();
            try
            {
                publicKey = wc.DownloadString(url);
            }
            catch(Exception e)
            {
                return false;
            }
            return true;

        }
        public string crypt(string text)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            RSAParameters rsaParam = rsa.ExportParameters(false);
            rsaParam.Modulus = Convert.FromBase64String(publicKey.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", ""));
            rsa.ImportParameters(rsaParam);
            byte[] encValue = rsa.Encrypt(Encoding.UTF8.GetBytes(text), false);

            return Convert.ToBase64String(encValue);
        }


        private static MyRSA _Instance;
        private static string publicKey;

        private MyRSA() {}
    }
}


Desde cualquier otra clase del cliente:

MyRSA rsa = MyRSA.getMyRSA();
rsa.setPubKey(site+"key.public.pem");
sendData(rsa.crypt(user));

Ahora en el servidor hago esto(PHP):

function RSADecryption($text) {
    //re() reads a document an return it as string
    openssl_private_decrypt(base64_decode($text), $decrypted,re("key.pem"));
    return $decrypted;
}

Pero parece ser que no funciona bien y no se el porque(Esta ultima funcion de php no devuelve nada)
Ejemplo de ejecución:
Clave AES generada aleatoriamente-->

cA?uW=kImEYGsgu

Clave publica usada-->

-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApxjhdfvCuafPZmE//cOM OVxBZvMXjwlcyaCfnTuVdbewQ5ITu6hlJ3vX/oTMbik7DprsWoc2tGk3Rx7RdAPd n3VnPm62QjaKtETWJ8/5Nzf+MxlVD0t5tzqzhniZ5BKZTtvCI6STbrFYnKcJwTyI eaEDNtre5EaqEBbrYhlGTRxNmz2SdRi9Im9iCSw9pjDVDDJdzmhENhASmFQMeo7N IS8AY3zJSjOQPKFymZrSa8hxWp88K1/igxs12IhhpqNjMiUi29gH2T+QLPTDzwEq EHTY1K6B0zlNuyp8HR5pNOqYymdnoSpCV3z0deTobAF7KiFYp2pXvoNo8Pc19Yl0 mQIDAQAB -----END PUBLIC KEY-----

Texto cifrado obtenido-->

CgG33ytbS3CuK+rOpJRamQ6e8xCj7Q35m6YxWXc44r/D03VubXZO1f5/zF7Zsc42UOOwqbYahApXBXL6o3J5MVu0cDkjstVoUnFJiPRHWmwq9AA0uvLC55gou+VzvmvRzFO38LMZ2BpsQLOjfv16LGWx7MLfKSVFGC8YVHgv6QlEbDFdd/HJDbqAKOoyQWlKXfVeMKmd8ORnq3+B3Tmk57O3BHDVOlmezSgf+YN828u4ChZ08JzjgBo7MP2xCl6pLEeZxiFGjRwrTgRfLXQ7aMB/RyeMMHwInJiTS3/M2Mez8C3/+Za/DIfrLDA9LVdRYdy2n4AxbtyrLTun4mjDO+pYS3HqZlGn2MW5Orc9VH+1CPn2omLVj/qqa6tIoFuJOdpxn/y9

Si alguien pudiera decirme en que falla o pasarme un ejemplo en el que hagan algo parecido a esto le estaria muy agradecido.
He estado mirando mil ejemplos pero no consigo hacer que funcione
Muchisimas gracias a todos por vuestra atencion.
Saludos.
Para poder atacar y vencer con seguridad, ataca donde ellos no puedan defenderse.
Para defenderte y resistir firme, defiéndete en donde ellos no atacarán.