加密和解密时出错。无法找到异常的原因
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了加密和解密时出错。无法找到异常的原因相关的知识,希望对你有一定的参考价值。
我有以下两种方法。
第一种方法
//SymmetricEncryting
private byte[] SymmetricEncrypt()
{
try
{
//Get Byte Value
byte[] x= Encoding.Default.GetBytes("Test");
byte [] y;
//Create Symmetric Key Encription
RijndaelManaged rijndaelManaged = new RijndaelManaged();
//GetSymmetricPublicKey
_symmetricPublicKey = rijndaelManaged.Key;
//Get Symmetric Public IV
_symmetricPublicIv = rijndaelManaged.IV;
using (MemoryStream memoryStream = new MemoryStream(x))
{
//Start EncriptionProcess
var cryptoStream = new CryptoStream(memoryStream,
rijndaelManaged.CreateEncryptor
(_symmetricPublicKey,
_symmetricPublicIv),
CryptoStreamMode.Write);
cryptoStream.Write(x, 0, x.Length);
// Complete the encryption process
//cryptoStream.FlushFinalBlock();
y= memoryStream.ToArray();
}
return y;
}
catch (Exception)
{
throw;
}
}
第二种方法
private string Decrypt(
byte[] y,
byte[] symmetricPublicKey,
byte[] symmtricPublicIv)
{
try
{
//Create the Key Container
CspParameters cspParameters = new CspParameters();
//Get the AsyPrivate and Public key from the Container
cspParameters.KeyContainerName = "Keys";
var rsaCryptoServiceProvider = new RSACryptoServiceProvider(cspParameters);
//Decrypt and get the Symmetric Public key
var decryptedSymmetricPubk = rsaCryptoServiceProvider.Decrypt(symmetricPublicKey, false);
//Decrypt and get the Symmetric Public IV
var decryptedSymmetricPubIv = rsaCryptoServiceProvider.Decrypt(symmtricPublicIv, false);
//Create RijndaelManaged object to do the Symmtric dycrption
RijndaelManaged rijndaelManaged = new RijndaelManaged();
//Create cryptostream using decrypted symmetric Public Key and IV
ICryptoTransform iCryptoTransform = rijndaelManaged.CreateDecryptor(decryptedSymmetricPubk,
decryptedSymmetricPubIv);
//Create a memory stream
using (MemoryStream memoryStream = new MemoryStream(y))
{
var cryptoStream = new CryptoStream(memoryStream, iCryptoTransform, CryptoStreamMode.Read);
byte[] z= new byte[y.Length];
cryptoStream.Read(z, 0, z.Length);
//cryptoStream.FlushFinalBlock();
//Convert byte array to string
var x= System.Text.Encoding.Default.GetString(z);
return x;
}
}
catch (Exception)
{
throw;
}
正如您在代码中看到的那样,我正在尝试使用对称加密来加密字符串。我使用我已经创建的非对称公钥来加密对称公钥和Iv。然后我尝试解密加密的字符串。
问题1在加密和解密上使用cryptoStream.FlushFinalBlock();
的目的是什么。我从msdn那里了解到它将结束在cyptostream上运行的进程
问题2如果我取消注释行cryptoStream.FlushFinalBlock();
它会引发异常"Memory stream is not expandable."
。但是,如果我对该行进行注释,它将正常工作并返回一个字节数组。
问题3然而第二种方法在执行行cryptoStream.Read(z,0,z.Length)时抛出异常"system.security.cryptography.cryptographicexception length of the data to decrypt is invalid
;
我在调试时找不到这些错误的实际原因。我也在Google上进行了一些搜索。但遗憾的是我找不到任何解决方案。任何人都可以解释一下答案吗?
您正在使用PKCS填充进行加密(这是默认设置)。 AES / Rijndael是一个块密码,这意味着它一次只能加密16个字节的块。为了允许块密码加密任意大小的数据,我们使用填充算法。 PKCS填充的工作原理是在加密时加入1-16个字节,并在解密时删除它们。填充的长度在填充本身中编码。
加密时需要FlushFinalBlock
让CryptoStream知道没有更多的传入数据,它应该添加填充。在Read-mode中使用CryptoStream时,没有必要也不应该使用它。
第一个例外是因为您使用明文数组作为MemoryStream的后备存储。由于填充,加密将大于明文。
第二个例外是因为您删除了FlushFinalBlock
语句,并且因为不允许MemoryStream调整大小以使数组具有正确的长度。加密数据应始终是16个字节的倍数,但由于MemoryStream将重用x
,因此y
将具有与x
相同的长度,FlushFinalBlock
并不总是有效长度。
解决方案是:
- 在SymmetricEncrypt中使用
using (MemoryStream memoryStream = new MemoryStream(x))
。 - 用
using (MemoryStream memoryStream = new MemoryStream(y))
替换using (MemoryStream memoryStream = new MemoryStream())
和MemoryStream
。这将允许var decryptMemoryStream = new MemoryStream(); var decryptStream = new CryptoStream(decryptMemoryStream, iCryptoTransform , CryptoStreamMode.Write); //write the unencrypted data array to the stream decryptStream.Write(y, 0, y.Length); decryptStream.Flush(); decryptStream.Close(); var decryptedData = decryptMemoryStream.ToArray();
s自由调整大小。
奇怪的是,在解密时我只能进行写操作。就像是:
cryptoStream.FlushFinalBlock()
问题1:这是您的代码,因此您应该知道为什么要编写代码(或者您可以提供从中获取代码的链接)。绝对不清楚为什么在读取数据时需要刷新流。
问题2:在字节数组上创建MemoryStream时,流不可调整大小是合理的。在这种情况下,流不能改变其大小(通常用于读取,如您的情况)。正如我在问题1中所说,目前尚不清楚为什么你会在阅读时做Flush。
问题3:您缺少在CryptoStream周围使用,因此很可能不会存储最后一部分数据。在MemoryStream.ToArray()
调用之前写入部分期间调用using
是一个选项,但qazxswpoi将生成更清晰的代码。
以上是关于加密和解密时出错。无法找到异常的原因的主要内容,如果未能解决你的问题,请参考以下文章
Spring SAML:解密加密密钥时出错,没有安装的提供程序支持此密钥