C# 输入数据不是一个完整的块

C# 输入数据不是一个完整的块,c#,encryption-symmetric,C#,Encryption Symmetric,场景:一个对称密钥,每个用户都有自己的IV,文档存储在NVARCHAR(MAX)字段中。当我试图解密文件时,我得到: 输入数据不是一个完整的块。 // Create symmetric key public static byte[] CreateKey() { AesCryptoServiceProvider aesCrypto = (AesCryptoServiceProvider)AesCryptoServiceProvider.Create(); byte[] key =

场景:一个对称密钥,每个用户都有自己的IV,文档存储在NVARCHAR(MAX)字段中。当我试图解密文件时,我得到:
输入数据不是一个完整的块。

// 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,我粘贴了您的代码,并且加密与新旧代码一起工作。然而,无论是我发布的代码还是你修改过的代码,解密都不起作用。