C# 输入数据不是一个完整的块
场景:一个对称密钥,每个用户都有自己的IV,文档存储在NVARCHAR(MAX)字段中。当我试图解密文件时,我得到:C# 输入数据不是一个完整的块,c#,encryption-symmetric,C#,Encryption Symmetric,场景:一个对称密钥,每个用户都有自己的IV,文档存储在NVARCHAR(MAX)字段中。当我试图解密文件时,我得到: 输入数据不是一个完整的块。 // Create symmetric key public static byte[] CreateKey() { AesCryptoServiceProvider aesCrypto = (AesCryptoServiceProvider)AesCryptoServiceProvider.Create(); byte[] key =
输入数据不是一个完整的块。
// Create symmetric key
public static byte[] CreateKey()
{
AesCryptoServiceProvider aesCrypto = (AesCryptoServiceProvider)AesCryptoServiceProvider.Create();
byte[] key = aesCrypto.Key;
return key;
}
//Get key (stored in a database)
public static Byte[] GetAppKey()
{
return db.Encryptors.Where(x => x.EncryptorID == 1).Single().EncryptionKey.ToArray();
}
// Get application IV (stored in database)
public static Byte[] GetAppIV()
{
return db.Encryptors.Where(x => x.EncryptorID == 1).Single().IV.ToArray();
}
// Encrypt document (this will be stored in a VARBINARY(MAX) field
public static byte[] EncryptBinaryToBytes(Binary document, byte[] iv)
{
byte[] key = GetAppKey();
byte[] encrypted;
using (AesCryptoServiceProvider aesCsp = new AesCryptoServiceProvider())
{
aesCsp.Key = key;
aesCsp.IV = iv;
ICryptoTransform encryptor = aesCsp.CreateEncryptor(aesCsp.Key, aesCsp.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(document);
}
encrypted = msEncrypt.ToArray();
}
}
}
// return the encrypted document
return encrypted;
}
// Decrypt document
public static byte[] DecryptBytesToBytes(byte[] document, byte[] iv)
{
byte[] key = GetAppKey();
using (AesCryptoServiceProvider aesCsp = new AesCryptoServiceProvider())
{
aesCsp.Key = key;
aesCsp.IV = iv;
ICryptoTransform decryptor = aesCsp.CreateDecryptor(aesCsp.Key, aesCsp.IV);
using (MemoryStream msDecrypt = new MemoryStream())
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write))
{
using (StreamWriter swDecrypt = new StreamWriter(csDecrypt))
{
swDecrypt.Write(document);
}
byte[] decrypted = msDecrypt.ToArray();
// return the unencrypted document
return decrypted;
}
}
}
}
提前谢谢
存储文档的步骤
byte[] fileByte = fluUploadFile.FileBytes;
Binary document = new Binary(fileByte);
byte[] appIv = AES.GetAppIV();
byte[] encryptedDocument = AES.EncryptBinaryToBytes(document, appIv);
byte[] decryptedDocument = AES.DecryptBytesToBytes(encryptedDocument, appIv);
Document d = new Document()
{
OriginalName = originalName,
DocSize = fileSize,
BinaryDocument = encryptedDocument,
UploadedName = uploadedFileName,
MimeType = MIMEType,
DocExtension = extension
};
db.Documents.InsertOnSubmit(d);
db.SubmitChanges();
将数据库字段的数据类型更改为
VARBINARY(MAX)
,这一点非常重要,这样可以避免无法解释为合法字符的字符编码和字节组合问题
另外,我认为问题在于,在加密和解密例程中调用MemoryStream
上的ToArray()
方法之前,没有关闭流。在CryptoStream
中调用Close()
非常重要,以便调用FlushFinalBlock()
,加密过程将最后一个块写入流
尝试将对MemoryStream.ToArray()
的调用移动到使用块的外部,即使用加密流的块的外部,以便在加密流上调用Dispose()
,并在此之前调用MemoryStream.Close()
代码的另一个问题是使用StreamWriter
包装CryptoStream
,它将传递的对象的文本表示形式写入Write
方法。您应该直接写入加密流
,以避免任何字节到字符串的转换。如何将二进制数据存储在文本字段中并再次转换回?我只想使用varbinary并完成它。NVARCHAR是否在填充您的字节?我添加了注释以显示文件是如何加载到数据库中的。XintO,我粘贴了您的代码,并且加密与新旧代码一起工作。然而,无论是我发布的代码还是你修改过的代码,解密都不起作用。