加密字符串充气城堡AES / CBC / PKCS7 [英] Encrypt string with Bouncy Castle AES/CBC/PKCS7
问题描述
我一直在到处找关于如何加密一个简单的字符串,在使用充气城堡框架标题加密一些示例代码。
这代码运行在Windows通用项目。
我以前尝试使用无法解密在服务器上的API生成加密
我试过这样:它给了我一个字符串,如:
4pQUfomwVVsl68oQqWoWYNRmRM + CP + vNFXBNdkN6dZPQ34VZ35vsKn9Q7QGTDVOj + w5mqVYHnGuAOFOgdgl8kA ==
块引用>
S =的String.Format({0} _ {1},S,DateTime.Now.ToString(ddMMyyyyHmmss));
SymmetricKeyAlgorithmProvider算法= SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
IBuffer keymaterial = CryptographicBuffer.ConvertStringToBinary([关键],BinaryStringEncoding.Utf8);
CryptographicKey KEY = algorithm.CreateSymmetricKey(keymaterial);
IBuffer IV = CryptographicBuffer.ConvertStringToBinary([IV],BinaryStringEncoding.Utf8);
IBuffer数据= CryptographicBuffer.ConvertStringToBinary(S,BinaryStringEncoding.Utf8);
IBuffer输出= CryptographicEngine.Encrypt(KEY,数据,IV);
返回CryptographicBuffer.EncodeToBase64String(输出);
服务器执行加密/解密以
公共静态字符串加密(字符串文本,字节[]键,字节[]四,INT密钥大小= 128,INT块大小= 128,CipherMode密码= CipherMode.CBC,PaddingMode填充= PaddingMode。 PKCS7)
{
AesCryptoServiceProvider AES =新AesCryptoServiceProvider();
aes.BlockSize =块大小;
aes.KeySize =密钥长度;
aes.Mode =密码;
aes.Padding =填充;
字节[] SRC = Encoding.UTF8.GetBytes(文本);
使用(ICryptoTransform的加密= aes.CreateEncryptor(键,IV))
{
字节[] = DEST encrypt.TransformFinalBlock(SRC,0,src.Length);
encrypt.Dispose();
返回Convert.ToBase64String(DEST);
}
}
公共静态字符串解密(字符串文本,字节[]键,字节[]四,INT密钥大小= 128,INT块大小= 128,CipherMode密码= CipherMode .CBC,PaddingMode填充= PaddingMode.PKCS7)
{
AesCryptoServiceProvider AES =新AesCryptoServiceProvider();
aes.BlockSize =块大小;
aes.KeySize =密钥长度;
aes.Mode =密码;
aes.Padding =填充;
字节[] SRC = Convert.FromBase64String(文本);使用(ICryptoTransform的解密= aes.CreateDecryptor(键,IV))
{
字节
[] = DEST decrypt.TransformFinalBlock(SRC,0,src.Length);
decrypt.Dispose();
返回Encoding.UTF8.GetString(DEST); //填充是无效的,不能删除。
}
}
但它没有becasue:
填充是无效的,不能删除。
块引用>
这就是为什么我想尝试充气城堡,但我找不到任何合适的示例代码。
修改
我试着用充气城堡与答案提供的代码。
现在我得到的错误:
初始向量必须是相同长度的块大小
块引用>
字节[] = inputBytes Encoding.UTF8.GetBytes(S);
的byte [] IV = Encoding.UTF8.GetBytes(XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX);
的byte []键= Encoding.UTF8.GetBytes(XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX);
//设置
AesEngine发动机=新AesEngine();
函数CBCBlockCipher分组密码=新的函数CBCBlockCipher(发动机);
PaddedBufferedBlockCipher密码=新PaddedBufferedBlockCipher(分组密码,新Pkcs7Padding());
的Debug.WriteLine(IV.Length); // 32
的Debug.WriteLine(cipher.GetBlockSize()); // 16
KeyParameter的keyParam =新KeyParameter的(密钥);
ParametersWithIV keyParamWithIv =新ParametersWithIV(keyParam,IV);
cipher.Init(真,keyParamWithIv); //错误消息抛出
字节[] = outputBytes新的字节[cipher.GetOutputSize(inputBytes.Length)]; // CIP
INT长度= cipher.ProcessBytes(inputBytes,outputBytes,0);
cipher.DoFinal(outputBytes,长度); //做最后的块
串encryptedInput = Convert.ToBase64String(outputBytes);
在服务器上的长度为128我怎样才能迫使它是平等的,相同的长度<? / p>
解决方案下面是我使用的片段。它采用内置System.Security.Cryptography默认。它并不需要是BC
///<总结>
///使用AES 128
///<加密的字节数组; /总结>
///< PARAM NAME =键> 128位的密钥和LT; /参数>
///< PARAM NAME =秘密>字节数组需要加密< /参数>
///<退货和GT;加密阵列< /回报>
公共静态的byte [] EncryptByteArray(字节[]键,字节[]秘密)使用
{
(MemoryStream的毫秒=新的MemoryStream())
{
使用(AesManaged cryptor =新AesManaged())
{
cryptor.Mode = CipherMode.CBC;
cryptor.Padding = PaddingMode.PKCS7;
cryptor.KeySize = 128;
cryptor.BlockSize = 128;
//我们使用AesManaged
字节创建随机生成IV [] IV = cryptor.IV;使用(CryptoStream的CS =新的CryptoStream(MS,cryptor.CreateEncryptor(键,IV),CryptoStreamMode.Write))
{
cs.Write(秘密,0,秘密
。长度);
}
字节[] = encryptedContent ms.ToArray();
//创建新的字节数组应包含未加密的IV和加密数据
的byte []结果=新的字节[iv.Length + encryptedContent.Length];
//我们的2阵列复制到一个
System.Buffer.BlockCopy(四,0,结果0,iv.Length);
System.Buffer.BlockCopy(encryptedContent,0,因此,iv.Length,encryptedContent.Length);
返回结果;
}
}
}
///<总结>
///使用AES 128
///<解密的字节数组; /总结>
///&下; PARAM NAME =钥匙>在字节&所述键/参数>
///< PARAM NAME =秘密>在加密的字节< /参数>
///<退货和GT;解密字节< /回报>
公共静态的byte [] DecryptByteArray(字节[]键,字节[]秘密)
{
的byte [] IV =新的字节[16]; //初始向量是16个字节
字节[] = encryptedContent新的字节[secret.Length - 16]。 //剩下的应该是encryptedcontent
//将数据复制到字节数组
System.Buffer.BlockCopy(秘密,0,四,0,iv.Length);
System.Buffer.BlockCopy(秘密,iv.Length,encryptedContent,0,encryptedContent.Length);使用
(MemoryStream的毫秒=新的MemoryStream())
{
使用(AesManaged cryptor =新AesManaged())
{
cryptor.Mode = CipherMode.CBC;
cryptor.Padding = PaddingMode.PKCS7;
cryptor.KeySize = 128;
cryptor.BlockSize = 128;使用(CryptoStream的CS =新的CryptoStream(MS,cryptor.CreateDecryptor(键,IV),CryptoStreamMode.Write))
{
cs.Write(encryptedContent,0,encryptedContent
。长度);
}
返回ms.ToArray();
}
}
}
如果你真的需要BC,这里是一个快速测试,我管理的基础上,从的 https://github.com/bcgit/bc-csharp/blob/master/crypto/test/src/crypto/test/AESFastTest.cs
你可以定制它为您的需要。私有静态无效TestBC()
{
//演示PARAMS
KeyString中字符串=jDxESdRrcYKmSZi7IOW4lw ==;
列输入=ABC;
字节[] = inputBytes Encoding.UTF8.GetBytes(输入);
的byte [] IV =新的字节[16]; //为演示
着想//设置
AesEngine发动机=新AesEngine();
函数CBCBlockCipher分组密码=新的函数CBCBlockCipher(发动机); // CBC
PaddedBufferedBlockCipher密码=新PaddedBufferedBlockCipher(分组密码); //默认方案是PKCS5 / PKCS7
KeyParameter的keyParam =新KeyParameter的(Convert.FromBase64String(KeyString中));
ParametersWithIV keyParamWithIV =新ParametersWithIV(keyParam,四,0,16);
//加密
cipher.Init(真,keyParamWithIV);
字节[] = outputBytes新的字节[cipher.GetOutputSize(inputBytes.Length)];
INT长度= cipher.ProcessBytes(inputBytes,outputBytes,0);
cipher.DoFinal(outputBytes,长度); //做最后的块
串encryptedInput = Convert.ToBase64String(outputBytes);
Console.WriteLine(加密字符串:{0},encryptedInput);
//解密
cipher.Init(假,keyParamWithIV);
字节[] = comparisonBytes新的字节[cipher.GetOutputSize(outputBytes.Length)];
长度= cipher.ProcessBytes(outputBytes,comparisonBytes,0);
cipher.DoFinal(comparisonBytes,长度); //做最后的块
Console.WriteLine(解密的字符串:{0},Encoding.UTF8.GetString(comparisonBytes)); //应该是ABC
}
I have been looking everywhere for some sample code on how to encrypt a simple string with the encryption in the title using the Bouncy Castle Framework.
This code will run on a Windows Universal project. My previous attempts to encrypt using the build in API's failed to decrypt on the server.
I tried this: which gives me a string like:
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);
The server does encryption/decryption with
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. } }
But it fails becasue:
Padding is invalid and cannot be removed.
That's why I want to try Bouncy Castle, but I can't find any suitable example code.
EDIT
I tried using Bouncy Castle with the code provided in the answer. Now I'm getting the error:
initialisation vector must be the same length as block size
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);
The length on the server is 128. How can I force it to be equal and same length?
解决方案Here are snippets I use. It uses the default built-in System.Security.Cryptography. It doesn't need to be 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(); } } }
If you really need BC, here is a quick test I manage to write based on the test suit from https://github.com/bcgit/bc-csharp/blob/master/crypto/test/src/crypto/test/AESFastTest.cs You can tailor it for your need
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 }
这篇关于加密字符串充气城堡AES / CBC / PKCS7的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!