none
cifrar texto System.security y Windows.security RRS feed

  • Pregunta

  • Buenas tardes,

    estoy incrementando la seguridad en las comunicaciones que realiza la App universal y me he propuesto utilizar cifrado simétrico. Tiene que descargar un xml del servidor el cual quiero tenerlo previamente cifrado con una mini aplicación de consola que lo cifre.  He estado revisando las APIs disponibles y me he encontrado que en las Apps universales tengo que utilizar la API Windows.Security.Cryptography y En la aplicación de consola tengo disponible System.Security.Cryptography. He estado mirando ejemplos pero no me he aclarado para realizar el cifrador en la consola y el descifrador en la App. ¿me podéis orientar un poco para comprender como configurar en ambas APIs la misma configuración? Los ejemplos que había encontrado son con AES CBC pero si es con otro algoritmo no me importa. Os adjunto los códigos por si se me podeis orientar en como adaptarlos.

    Muchas gracias

    Código App

    public static string Decrypt(byte[] encryptedData, string pw, string salt)
            {
                IBuffer pwBuffer = CryptographicBuffer.ConvertStringToBinary(pw, BinaryStringEncoding.Utf8);
                IBuffer saltBuffer = CryptographicBuffer.ConvertStringToBinary(salt, BinaryStringEncoding.Utf8);
                IBuffer cipherBuffer = CryptographicBuffer.CreateFromByteArray(encryptedData);
    
                // Derive key material for password size 32 bytes for AES256 algorithm
                KeyDerivationAlgorithmProvider keyDerivationProvider = Windows.Security.Cryptography.Core.KeyDerivationAlgorithmProvider.OpenAlgorithm("PBKDF2_SHA1");
                // using salt and 1000 iterations
                KeyDerivationParameters pbkdf2Parms = KeyDerivationParameters.BuildForPbkdf2(saltBuffer, 1000);
    
                // create a key based on original key and derivation parmaters
                CryptographicKey keyOriginal = keyDerivationProvider.CreateKey(pwBuffer);
                IBuffer keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, pbkdf2Parms, 32);
                CryptographicKey derivedPwKey = keyDerivationProvider.CreateKey(pwBuffer);
    
                // derive buffer to be used for encryption salt from derived password key 
                IBuffer saltMaterial = CryptographicEngine.DeriveKeyMaterial(derivedPwKey, pbkdf2Parms, 16);
    
                // display the keys – because KeyDerivationProvider always gets cleared after each use, they are very similar unforunately
                string keyMaterialString = CryptographicBuffer.EncodeToBase64String(keyMaterial);
                string saltMaterialString = CryptographicBuffer.EncodeToBase64String(saltMaterial);
    
                SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
                // create symmetric key from derived password material
                CryptographicKey symmKey = symProvider.CreateSymmetricKey(keyMaterial);
    
                // encrypt data buffer using symmetric key and derived salt material
                IBuffer resultBuffer = CryptographicEngine.Decrypt(symmKey, cipherBuffer, saltMaterial);
                string result = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, resultBuffer);
                return result;
            }

    Código Consola

    public byte[] encryptdata(byte[] bytearraytoencrypt, string key, string iv)  
            {  
                AesCryptoServiceProvider dataencrypt = new AesCryptoServiceProvider();  
                //Block size : Gets or sets the block size, in bits, of the cryptographic operation.  
                dataencrypt.BlockSize = 128;  
                //KeySize: Gets or sets the size, in bits, of the secret key  
                dataencrypt.KeySize = 32;  
                //Key: Gets or sets the symmetric key that is used for encryption and decryption.  
                dataencrypt.Key = System.Text.Encoding.UTF8.GetBytes(key);  
                //IV : Gets or sets the initialization vector (IV) for the symmetric algorithm  
                dataencrypt.IV = System.Text.Encoding.UTF8.GetBytes(iv);  
                //Padding: Gets or sets the padding mode used in the symmetric algorithm  
                dataencrypt.Padding = PaddingMode.PKCS7;  
                //Mode: Gets or sets the mode for operation of the symmetric algorithm  
                dataencrypt.Mode = CipherMode.CBC;  
                //Creates a symmetric AES encryptor object using the current key and initialization vector (IV).  
                ICryptoTransform crypto1 = dataencrypt.CreateEncryptor(dataencrypt.Key, dataencrypt.IV);  
                //TransformFinalBlock is a special function for transforming the last block or a partial block in the stream.   
                //It returns a new array that contains the remaining transformed bytes. A new array is returned, because the amount of   
                //information returned at the end might be larger than a single block when padding is added.  
                byte[] encrypteddata = crypto1.TransformFinalBlock(bytearraytoencrypt, 0, bytearraytoencrypt.Length);  
                crypto1.Dispose();  
                //return the encrypted data  
                return encrypteddata;  
            }

    viernes, 19 de junio de 2015 14:42

Todas las respuestas

  • Buenas tardes,

    He estado buscando mas información, y encontré teóricamente un ejemplo pero lo compile y tampoco funcionaba. Como nadie me ha dado ninguna sugerencia, idea de como realizarlo, os cuento el contexto para que resulte mas claro lo que quiero hacer.

    Tengo una App universal y tengo datos en el servidor que necesita la App como mínimo una vez al día. Desarrolladores ajenos, o personas con malas intenciones han estado atacando los servidores para conseguir los datos y usarlos sin consentimiento. Emplear conexiones SSL no puedo ya que se sale del presupuesto. Únicamente puedo utilizar http sobre php. Los datos que descarga la App del servidor no requiere de cuenta, por lo que no tengo identificado a los usuarios, así que lo único que se me ocurre es que el contenido vaya cifrado. De forma que si acceden a algún contenido, necesiten la contraseña correspondiente para descifrarlo y usarlo.

    Me imagino que lo primero que seria fácil de pensar sería que el servidor cifre el contenido el fichero, pero el contenido es estático, son ficheros Png, XML, Json que necesita. Y dada la cantidad de usuarios que pueden llegar a usar la App en el día, tengo el contenido replicado en diferentes servidores. Que ocurre? No todos disponen de mcrypt, y dado que el contenido es estático--> creo que es mejor que el contenido lo suba ya cifrado.

    Si lo subo cifrado, necesito hacer una aplicación de escritorio (mismamente de consola, sin interfaz) que me lo cifre.

    Ya que otras ideas, un parámetro en la cabecera? Al ser http, lo pueden capturar y utilizar. No sirve. Un Zip cifrado? Tiene que descomprimir, y leer posteriormente el fichero. Muy lento. Además, existen herramientas que con Nvidia rompen el cifrado rápido. Http basic/Digest? Ídem, pueden capturarlo y utilizar sin problemas después.

    Por lo que únicamente se me ocurre es cifrar el contenido que intercambia el servidor. Cuando llegue el momento y tenga que forzar a tener cuenta ya podre utilizar Tokens pero mientras no sea necesario tener cuenta... Los usuarios mas contentos.

    Muchas gracias

    jueves, 2 de julio de 2015 14:04