使用Bouncy Castle AES / CBC / PKCS7加密字符串
我一直在寻找一些关于如何使用Bouncy Castle Framework加密标题中加密的简单字符串的示例代码。
此代码将在Windows Universal项目上运行。 我之前尝试使用内置API加密的尝试无法在服务器上解密。
我试过这个:这给了我一个字符串:
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);
服务器使用加密/解密
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. } }
但它失败了因为:
填充无效,无法删除。
这就是为什么我想尝试Bouncy Castle,但我找不到任何合适的示例代码。
编辑
我尝试使用Bouncy Castle和答案中提供的代码。 现在我收到了错误:
初始化向量必须与块大小相同
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);
服务器上的长度是128.如何强制它等于相同的长度?
这是我使用的片段。 它使用默认的内置System.Security.Cryptography。 它不需要是BC
/// /// Encrypt a byte array using AES 128 /// /// 128 bit key /// byte array that need to be encrypted /// Encrypted array 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; } } } /// /// Decrypt a byte array using AES 128 /// /// key in bytes /// the encrypted bytes /// decrypted bytes 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(); } } }
如果你真的需要BC,这是一个快速测试,我设法根据https://github.com/bcgit/bc-csharp/blob/master/crypto/test/src/crypto/test/AESFastTest的测试套装编写.cs您可以根据需要定制
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 }
- BouncyCastle在C#threadsafe中的SecureRandom?
- 跨平台上的AES cbc填充加密/解密(.net c#和代号为一个充气城堡)
- 转换椭圆曲线参数(BC到MS)
- Bouncycastle PGP解密期间的PartialInputStream
- 加密BouncyCastle RSA密钥对并存储在SQL2008数据库中
- 使用C#,BouncyCastle和导入的RSA密钥进行RSA签名和validation – 内部使用Python示例和非工作C#代码示例
- RSA Public exponent默认为65537.该值应该是多少? 我的选择有什么影响?
- 在C#中使用BouncyCastle构建证书链
- 使用BouncyCastle PGP解密文件的例外情况