加密和解密文件 - 导致“错误数据”

时间:2015-03-07 21:17:47

标签: c# encryption des

我目前正在处理一个小对象,它将帮助我加密文件然后对其进行解密,并将其作为MemoryStream返回。但是,当我正在解密时,我不断收到“错误数据”。

"ExceptionMessage": "Bad Data.\ \ ",
"ExceptionType": "System.Security.Cryptography.CryptographicException",

课程如下

public class SignatureService {
    private readonly DESCryptoServiceProvider _desCryptoServiceProvider;
    private static byte[] _key = { 5, 6, 7, 2, 3, 4, 8, 1 };
    private static byte[] _iv = { 5, 2, 3, 4, 1, 7, 4, 2 };

    public SignatureService () {
        _desCryptoServiceProvider = new DESCryptoServiceProvider();
    }

    public void SaveSignatureOnDisk ( Stream stream ) {
        using ( var fs = new FileStream( "filepath", FileMode.Create, FileAccess.Write ) ) {
            var cryptoStream = new CryptoStream( fs, _desCryptoServiceProvider.CreateEncryptor( _key, _iv ), CryptoStreamMode.Write );
            var bytearrayinput = new byte[ stream.Length - 1 ];
            stream.Read( bytearrayinput, 0, bytearrayinput.Length );
            cryptoStream.Write( bytearrayinput, 0, bytearrayinput.Length );
        }
 }

    public Stream ReadSignatureOnDisk () {
        Stream returnedStream;
        using ( var fs = new FileStream( "filepath", FileMode.Open, FileAccess.Read ) ) {
            var cryptoStream = new CryptoStream( fs, _desCryptoServiceProvider.CreateDecryptor( _key, _iv ), CryptoStreamMode.Read );

            string contents = new StreamReader( cryptoStream ).ReadToEnd();
            byte[] unicodes = Encoding.Unicode.GetBytes( contents );
            returnedStream = new MemoryStream( unicodes );
        }

        return returnedStream;
    }
}

1 个答案:

答案 0 :(得分:1)

你犯了一些错误,应该处理来自CreateDecryptorCreateEncryptor的CryptoStream和ICryptoTransform。此外,stream.Read不可靠,不保证读取实际读取您要求的所有字节。您必须循环直到Read返回0,或者如果您使用的是具有它的.NET版本,则必须使用.CopyTo(

public void SaveSignatureOnDisk ( Stream stream ) 
{
    using (var fs = new FileStream("filepath", FileMode.Create, FileAccess.Write))
    using (var encryptor = _desCryptoServiceProvider.CreateEncryptor( _key, _iv))
    using (var cryptoStream = new CryptoStream(fs, encryptor, CryptoStreamMode.Write))
    {
        stream.CopyTo(cryptoStream);
    }
}

您的ReadSignatureOnDisk也有同样的错误,需要同样修复。

public Stream ReadSignatureOnDisk ()
{
    Stream returnedStream = new MemoryStream();
    using (var fs = new FileStream("filepath", FileMode.Open, FileAccess.Read))
    using (var decryptor = _desCryptoServiceProvider.CreateDecryptor(_key, _iv))
    using (var cryptoStream = new CryptoStream(fs, decryptor, CryptoStreamMode.Read);
    {
        cryptoStream.CopyTo(returnedStream);
    }

    returnedStream.Position = 0
    return returnedStream;
}

如果你想要,你可以使用我的ReturnableCryptoStream类I wrote for another answer,它允许你返回原始的加密流,并让调用者处理它。

/// <summary>
/// Creates a class that creates a <see cref="CryptoStream"/> and wraps the disposing action of all the associated objects 
/// </summary>
class ReturnableCryptoStream : CryptoStream
{
    private readonly ICryptoTransform _transform;
    private readonly IDisposable _algorithom;

    public ReturnableCryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode, IDisposable algorithom) 
        : base(stream, transform, mode)
    {
        _transform = transform;
        _algorithom = algorithom;
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        if (disposing)
        {
            if (_transform != null)
                _transform.Dispose();

            if (_algorithom != null)
                _algorithom.Dispose();
        }
    }
}

一样使用
public Stream ReadSignatureOnDisk ()
{
    var fs = new FileStream("filepath", FileMode.Open, FileAccess.Read);
    var serviceProvider = new DESCryptoServiceProvider()
    var decryptor = serviceProvider.CreateDecryptor(_key, _iv);
    var cryptoStream = new ReturnableCryptoStream(fs, 
             decryptor, 
             CryptoStreamMode.Read, 
             serviceProvider); 
    //note that I now make my own local copy of the service provider, you could use your 
    //existing one and pass in null to the ReturnableCryptoStream.

    return cryptoStream ;
}