c# encryption windows-phone-8.1 windows-8.1 bouncycastle

c# - Encriptar cadena con Bouncy Castle AES/CBC/PKCS7



encryption windows-phone-8.1 (1)

He estado buscando un código de ejemplo sobre cómo encriptar una cadena simple con el cifrado en el título usando el Bouncy Castle Framework.

Este código se ejecutará en un proyecto de Windows Universal. Mis intentos previos de encriptar utilizando la compilación en la API no se pudieron descifrar en el servidor.

Intenté esto: que me da una secuencia como:

4pQUfomwVVsl68oQqWoWYNRmRM + Cp + vNFXBNdkN6dZPQ34VZ35vsKn9Q7QGTDVOj + w5mqVYHnGuAOFOgdgl8kA ==

s = String.Format("{0}_{1}", s, DateTime.Now.ToString("ddMMyyyyHmmss")); SymmetricKeyAlgorithmProvider algorithm = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7); IBuffer keymaterial = CryptographicBuffer.ConvertStringToBinary("[Key]", BinaryStringEncoding.Utf8); CryptographicKey KEY = algorithm.CreateSymmetricKey(keymaterial); IBuffer IV = CryptographicBuffer.ConvertStringToBinary("[IV]", BinaryStringEncoding.Utf8); IBuffer data = CryptographicBuffer.ConvertStringToBinary(s, BinaryStringEncoding.Utf8); IBuffer output = CryptographicEngine.Encrypt(KEY, data, IV); return CryptographicBuffer.EncodeToBase64String(output);

El servidor realiza cifrado / descifrado con

public static string Encrypt(string text, byte[] key, byte[] iv, int keysize = 128, int blocksize = 128, CipherMode cipher = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7) { AesCryptoServiceProvider aes = new AesCryptoServiceProvider(); aes.BlockSize = blocksize; aes.KeySize = keysize; aes.Mode = cipher; aes.Padding = padding; byte[] src = Encoding.UTF8.GetBytes(text); using (ICryptoTransform encrypt = aes.CreateEncryptor(key, iv)) { byte[] dest = encrypt.TransformFinalBlock(src, 0, src.Length); encrypt.Dispose(); return Convert.ToBase64String(dest); } } public static string Decrypt(string text, byte[] key, byte[] iv, int keysize = 128, int blocksize = 128, CipherMode cipher = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7) { AesCryptoServiceProvider aes = new AesCryptoServiceProvider(); aes.BlockSize = blocksize; aes.KeySize = keysize; aes.Mode = cipher; aes.Padding = padding; byte[] src = Convert.FromBase64String(text); using (ICryptoTransform decrypt = aes.CreateDecryptor(key, iv)) { byte[] dest = decrypt.TransformFinalBlock(src, 0, src.Length); decrypt.Dispose(); return Encoding.UTF8.GetString(dest); //Padding is invalid and cannot be removed. } }

Pero falla porque:

El relleno no es válido y no se puede eliminar.

Es por eso que quiero probar Bouncy Castle, pero no puedo encontrar ningún código de ejemplo adecuado.

EDITAR

Intenté usar Bouncy Castle con el código provisto en la respuesta. Ahora estoy obteniendo el error:

el vector de inicialización debe tener la misma longitud que el tamaño del bloque

byte[] inputBytes = Encoding.UTF8.GetBytes(s); byte[] IV = Encoding.UTF8.GetBytes("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); byte[] key = Encoding.UTF8.GetBytes("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); //Set up AesEngine engine = new AesEngine(); CbcBlockCipher blockCipher = new CbcBlockCipher(engine); PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher, new Pkcs7Padding()); Debug.WriteLine(IV.Length); //32 Debug.WriteLine(cipher.GetBlockSize()); //16 KeyParameter keyParam = new KeyParameter(key); ParametersWithIV keyParamWithIv = new ParametersWithIV(keyParam, IV); cipher.Init(true, keyParamWithIv); //Error Message thrown byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)]; //cip int length = cipher.ProcessBytes(inputBytes, outputBytes, 0); cipher.DoFinal(outputBytes, length); //Do the final block string encryptedInput = Convert.ToBase64String(outputBytes);

La longitud en el servidor es 128. ¿Cómo puedo forzar que sea igual y la misma longitud?


Aquí hay fragmentos que uso. Utiliza el System.Security.Cryptography incorporado predeterminado. No es necesario que sea BC

/// <summary> /// Encrypt a byte array using AES 128 /// </summary> /// <param name="key">128 bit key</param> /// <param name="secret">byte array that need to be encrypted</param> /// <returns>Encrypted array</returns> public static byte[] EncryptByteArray(byte[] key, byte[] secret) { using (MemoryStream ms = new MemoryStream()) { using (AesManaged cryptor = new AesManaged()) { cryptor.Mode = CipherMode.CBC; cryptor.Padding = PaddingMode.PKCS7; cryptor.KeySize = 128; cryptor.BlockSize = 128; //We use the random generated iv created by AesManaged byte[] iv = cryptor.IV; using (CryptoStream cs = new CryptoStream(ms, cryptor.CreateEncryptor(key, iv), CryptoStreamMode.Write)) { cs.Write(secret, 0, secret.Length); } byte[] encryptedContent = ms.ToArray(); //Create new byte array that should contain both unencrypted iv and encrypted data byte[] result = new byte[iv.Length + encryptedContent.Length]; //copy our 2 array into one System.Buffer.BlockCopy(iv, 0, result, 0, iv.Length); System.Buffer.BlockCopy(encryptedContent, 0, result, iv.Length, encryptedContent.Length); return result; } } } /// <summary> /// Decrypt a byte array using AES 128 /// </summary> /// <param name="key">key in bytes</param> /// <param name="secret">the encrypted bytes</param> /// <returns>decrypted bytes</returns> public static byte[] DecryptByteArray(byte[] key, byte[] secret) { byte[] iv = new byte[16]; //initial vector is 16 bytes byte[] encryptedContent = new byte[secret.Length - 16]; //the rest should be encryptedcontent //Copy data to byte array System.Buffer.BlockCopy(secret, 0, iv, 0, iv.Length); System.Buffer.BlockCopy(secret, iv.Length, encryptedContent, 0, encryptedContent.Length); using (MemoryStream ms = new MemoryStream()) { using (AesManaged cryptor = new AesManaged()) { cryptor.Mode = CipherMode.CBC; cryptor.Padding = PaddingMode.PKCS7; cryptor.KeySize = 128; cryptor.BlockSize = 128; using (CryptoStream cs = new CryptoStream(ms, cryptor.CreateDecryptor(key, iv), CryptoStreamMode.Write)) { cs.Write(encryptedContent, 0, encryptedContent.Length); } return ms.ToArray(); } } }

Si realmente necesita BC, aquí hay una prueba rápida que logro escribir en base al traje de prueba de https://github.com/bcgit/bc-csharp/blob/master/crypto/test/src/crypto/test/AESFastTest.cs Puede personalizarlo para su necesidad

private static void TestBC() { //Demo params string keyString = "jDxESdRrcYKmSZi7IOW4lw=="; string input = "abc"; byte[] inputBytes = Encoding.UTF8.GetBytes(input); byte[] iv = new byte[16]; //for the sake of demo //Set up AesEngine engine = new AesEngine(); CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher); //Default scheme is PKCS5/PKCS7 KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyString)); ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16); // Encrypt cipher.Init(true, keyParamWithIV); byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)]; int length = cipher.ProcessBytes(inputBytes, outputBytes, 0); cipher.DoFinal(outputBytes, length); //Do the final block string encryptedInput = Convert.ToBase64String(outputBytes); Console.WriteLine("Encrypted string: {0}", encryptedInput); //Decrypt cipher.Init(false, keyParamWithIV); byte[] comparisonBytes = new byte[cipher.GetOutputSize(outputBytes.Length)]; length = cipher.ProcessBytes(outputBytes, comparisonBytes, 0); cipher.DoFinal(comparisonBytes, length); //Do the final block Console.WriteLine("Decrypted string: {0}",Encoding.UTF8.GetString(comparisonBytes)); //Should be abc }