简体   繁体   中英

“Specified initialization vector (IV) does not match the block size for this algorithm” using an CryptoStream

I've had troubles using an CryptoStream for my file encryption..

Code:

public static void EncryptFile(string inputFile, string outputFile)
    {
        int num;
        string s = "PUPlr";
        byte[] bytes = new UnicodeEncoding().GetBytes(s);
        string path = outputFile;
        FileStream stream = new FileStream(path, FileMode.Create);
        RijndaelManaged managed = new RijndaelManaged();
        CryptoStream crpytStream = new CryptoStream(stream, managed.CreateEncryptor(bytes, bytes), CryptoStreamMode.Write);
        FileStream stream2 = new FileStream(inputFile, FileMode.Open);
        while ((num = stream2.ReadByte()) != -1)
        {
            crpytStream.WriteByte((byte)num);
        }
        stream2.Close();
        crpytStream.Close();
        stream.Close();
    }

Trying "managed.BlockSize = 16;" or "= 128;" doesn't seem to work, so how could I fix my error?

Block cyphers like Rijndael require keys and IVs of length equal to the block size, typically 256 bits.

In addition, the IV must be unique for each message, or your data will not be secure.

The error is:

managed.CreateEncryptor(bytes, bytes)

where the bytes needs to be either 128 bits (16 bytes), 192 bits (24 bytes) or 256 bits (32 bytes) for the first (Key) and second parameter.

Notes:

  • for AES interoperability you should use Rijndael with a BlockSize of 128 bits (16 bytes).

  • UnicodeEncoding will (often) give you weak password. Look at using PKCS#5 to create a strong key (and IV) from a password. For .NET look at RFC2898DeriveBytes ;

  • avoid using the same data for both the key and IV;

This line here:

managed.CreateEncryptor(bytes, bytes)

Doesn't work. The first parameter is a key, and the second parameter is an initialization vector. If your intention was to use the string s as a "password" or key, try using Rfc2898DeriveBytes to generate a key from a password.

public static void EncryptFile(string input, string output)
{
    string theKey = "urKey";
    byte[] salt = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c };
    Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(theKey, salt);
    RijndaelManaged RMCrypto = new RijndaelManaged();
    using (var inputStream=new FileStream(input))
        using (var outputStream = new FileStream(output))
            using (CryptoStream cs = new CryptoStream(inputStream, RMCrypto.CreateEncryptor(pdb.GetBytes(32), pdb.GetBytes(16)), CryptoStreamMode.Read))
            {
                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                do
                {
                    bytesRead = cs.Read(buffer, 0, buffer.Length);
                    outputStream.Write(buffer, 0, bytesRead);
                } while (bytesRead > 0);
            }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM