C# encryption and decryption IV issue - c#

My code performs encryption but not decryption. I wanted it to generate random IV so made some changes, but now it's not decrypting. I think I am messing up with IV. It doesn't seem that it is able to decrypt properly.
The IV is not getting prefixed to the encrypted file or the decrypt method is unable to find IV. I can't understand how to solve it. The file is produced for example I encrypted a text file which had "hello world", after encryption it produced some gibberish. After decryption it produced a empty text file.
encryption method:
private const ushort ITERATIONS = 1300;
private static readonly byte[] SALT = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c };
private static byte[] CreateKey(string password, int keySize)
{
DeriveBytes derivedKey = new Rfc2898DeriveBytes(password, SALT, ITERATIONS);
return derivedKey.GetBytes(keySize >> 3);
}
public static void EncryptFile(string file, string password)
{
// First we are going to open the file streams
FileStream fsIn = new FileStream(file, FileMode.Open, FileAccess.Read);
FileStream fsOut = new FileStream(file+"enc", FileMode.OpenOrCreate, FileAccess.Write);
// Then we are going to derive a Key and an IV from the
// Password and create an algorithm
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
// passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = AES.LegalKeySizes[0].MaxSize;
AES.BlockSize = AES.LegalBlockSizes[0].MaxSize;
AES.Padding = PaddingMode.Zeros;
AES.GenerateIV();
AES.Key = CreateKey(password, AES.KeySize);
AES.Mode = CipherMode.CBC;
using (MemoryStream memStream = new MemoryStream(file.Length))
memStream.Write(AES.IV, 0, 16);
CryptoStream cs = new CryptoStream(fsOut, AES.CreateEncryptor(), CryptoStreamMode.Write);
int bufferLen = 4096;
byte[] buffer = new byte[bufferLen];
int bytesRead;
do
{
// read a chunk of data from the input file
bytesRead = fsIn.Read(buffer, 0, bufferLen);
// encrypt it
cs.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
// close everything
// this will also close the unrelying fsOut stream
cs.Close();
fsIn.Close();
}
decryption method:
private const ushort ITERATIONS = 1300;
private static readonly byte[] SALT = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c };
private static byte[] CreateKey(string password, int keySize)
{
DeriveBytes derivedKey = new Rfc2898DeriveBytes(password, SALT, ITERATIONS);
return derivedKey.GetBytes(keySize >> 3);
}
public static void DecryptFile(string fileIn, string Password)
{
// First we are going to open the file streams
FileStream fsIn = new FileStream(fileIn,FileMode.Open, FileAccess.Read);
string extension = System.IO.Path.GetExtension(fileIn);
string result = fileIn.Substring(0, fileIn.Length - extension.Length);
FileStream fsOut = new FileStream(result,FileMode.OpenOrCreate, FileAccess.Write);
// passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = AES.LegalKeySizes[0].MaxSize;
AES.BlockSize = AES.LegalBlockSizes[0].MaxSize;
AES.Padding = PaddingMode.Zeros;
byte[] iv = new byte[16];
fsIn.Read(iv, 0, 16);
AES.IV=iv;
AES.Key = CreateKey(Password, AES.KeySize);
AES.Mode = CipherMode.CBC;
// Now create a crypto stream through which we are going
// to be pumping data.
// Our fileOut is going to be receiving the Decrypted bytes.
CryptoStream cs = new CryptoStream(fsOut,
AES.CreateDecryptor(), CryptoStreamMode.Write);
// Now will will initialize a buffer and will be
// processing the input file in chunks.
// This is done to avoid reading the whole file (which can be
// huge) into memory.
int bufferLen = 4096;
byte[] buffer = new byte[bufferLen];
int bytesRead;
do
{
// read a chunk of data from the input file
bytesRead = fsIn.Read(buffer, 0, bufferLen);
// Decrypt it
cs.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
// close everything
cs.Close(); // this will also close the unrelying fsOut stream
fsIn.Close();
}

You must specify a block size of 128-bits (16-bytes) for the encryption to be AES, see options below:
Generally the iv is the same size as the block size. You are supplying a 16-byte iv and the Rijndael maximum block size is 32-bytes so there is a very good chance that the encryption routines are using an additional 16-bytes of junk bytes following the iv.
There are a few problems: The class is Rijndael and AES is a subset of Rijndael so allowable parameters of Rijndael may not be allowable for AES.
LegalBlockSizes[0].MaxSize will return the maximum Rijndael block size of 256-bits but AES has a fixed block size of 128-bits. Thus you are not actually using AES. You must specify a block size of 128-bits (16-bytes).
PaddingMode.Zeros will not work if the last byte of the data to be encrypted is a 0x00 byte. Generally PKCS#7 (archaically PKCS#5) is used, PHP mcrypt excepted. -- Thanks to ArtjomB.
As prompted by ArtjomB.
If I am correct there are two options,choose one of the options:
1: Change the block size to 16-bytes as required by AES:
Change to encryption and decryption:
AES.BlockSize = 128;
2: Use a 32-byte iv (note that this will not produce AES encryption):
Change to encryption:
memStream.Write(AES.IV, 0, 32);
Change to decryption:
byte[] iv = new byte[32];
fsIn.Read(iv, 0, 32

Building on the results of zaph's answer...
You need to write the IV to the file, not to some temporary MemoryStream that you're never using:
fsOut.Write(AES.IV, 0, 32);
And completely remove the line using (MemoryStream memStream = new MemoryStream(file.Length)).
This seems be the issue when reading in the comments:
the file is produced for example I encrypted a text file which had "hello world" , after encryption it produced some gibberish. after decryption it produced a empty text file
This means that the actual ciphertext is empty and there is nothing to decrypt. The happens, because the IV wasn't actually written to the ciphertext file and therefore the decryption method thought that the single block that is present in there is actually the IV.
Don't forget to read the full IV from the ciphertext file during decryption:
byte[] iv = new byte[32];
fsIn.Read(iv, 0, 32)

Related

How implement Php's openssl_encrypt method in c#?

as in the title, I need to implement in my C# code the equivalent of php's openssl_encrypt method, because I need to call a service on a php page, but we work with c#.
The php code is this:
$textToEncrypt = "test";
$algo = "AES256";
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($algo));
$key = "1234567890987654"; //Not this key, but just same length
$parametri_enc = openssl_encrypt($textToEncrypt , $algo, $key, 0, $iv);
$iv = bin2hex($iv);
I tried many thing, actually my code is:
string textToEncrypt = "test";
string secretCode = "1234567890987654"
// Create sha256 hash
SHA256 mySHA256 = SHA256Managed.Create();
byte[] key = mySHA256.ComputeHash(Encoding.ASCII.GetBytes(secretCode));
// Create secret IV
byte[] iv = new byte[16];
RandomNumberGenerator generator = RandomNumberGenerator.Create();
generator.GetBytes(iv);
string encryptedText = EncryptString(textToEncrypt, key, iv);
// And I try to port also the bin2hex method
var sb = new StringBuilder();
foreach (byte b in iv)
{
sb.AppendFormat("{0:x2}", b);
}
var tokenBytesHex = sb.ToString();
And the method EncryptString is
public static string EncryptString(string plainText, byte[] key, byte[] iv)
{
//Instantiate a new Aes object to perform string symmetric encryption
Aes encryptor = Aes.Create();
encryptor.Mode = CipherMode.CBC;
// Set key and IV
byte[] aesKey = new byte[32];
Array.Copy(key, 0, aesKey, 0, 32);
encryptor.Key = aesKey;
encryptor.IV = iv;
// Instantiate a new MemoryStream object to contain the encrypted bytes
MemoryStream memoryStream = new MemoryStream();
// Instantiate a new encryptor from our Aes object
ICryptoTransform aesEncryptor = encryptor.CreateEncryptor();
// Instantiate a new CryptoStream object to process the data and write it to the
// memory stream
CryptoStream cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write);
// Convert the plainText string into a byte array
byte[] plainBytes = Encoding.ASCII.GetBytes(plainText);
// Encrypt the input plaintext string
cryptoStream.Write(plainBytes, 0, plainBytes.Length);
// Complete the encryption process
cryptoStream.FlushFinalBlock();
// Convert the encrypted data from a MemoryStream to a byte array
byte[] cipherBytes = memoryStream.ToArray();
// Close both the MemoryStream and the CryptoStream
memoryStream.Close();
cryptoStream.Close();
// Convert the encrypted byte array to a base64 encoded string
string cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length);
// Return the encrypted data as a string
return cipherText;
}
I tried many variation about this porting (that I've found on internet), but without result. If I use a correct encrypted string from my code, I can call the service, so it is working. I need only to encrypt correctly that string, but until now, I've failed
Ok i solved my own problem. I'll share it so if anyone has the same problem, this could work. Basically I saw a decryption c# code here so I update my code in this way
First, I pass my secretCode in string format instead of byte[]
So i changed my method signature in this way:
public static string EncryptString(string plainText, string secretcode, byte[] iv)
and inside I changed the way I manipulate the secretCode (passphrase in php equivalent method)
// Set key and IV
var aesKey = Encoding.ASCII.GetBytes(secretcode);
//pad key out to 32 bytes (256bits) if its too short
if (aesKey.Length < 32)
{
var paddedkey = new byte[32];
Buffer.BlockCopy(aesKey, 0, paddedkey, 0, aesKey.Length);
aesKey = paddedkey;
}
So it worked! No other change, just this two small change from my previous post
Updated method
public static string EncryptString(string plainText, string secretcode, byte[] iv)
{
// Instantiate a new Aes object to perform string symmetric encryption
Aes encryptor = Aes.Create();
encryptor.Mode = CipherMode.CBC;
// Set key and IV
var aesKey = Encoding.ASCII.GetBytes(secretcode);
//pad key out to 32 bytes (256bits) if its too short
if (aesKey.Length < 32)
{
var paddedkey = new byte[32];
Buffer.BlockCopy(aesKey, 0, paddedkey, 0, aesKey.Length);
aesKey = paddedkey;
}
encryptor.Key = aesKey;
encryptor.IV = iv;
// Instantiate a new MemoryStream object to contain the encrypted bytes
MemoryStream memoryStream = new MemoryStream();
// Instantiate a new encryptor from our Aes object
ICryptoTransform aesEncryptor = encryptor.CreateEncryptor();
// Instantiate a new CryptoStream object to process the data and write it to the
// memory stream
CryptoStream cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write);
// Convert the plainText string into a byte array
byte[] plainBytes = Encoding.ASCII.GetBytes(plainText);
// Encrypt the input plaintext string
cryptoStream.Write(plainBytes, 0, plainBytes.Length);
// Complete the encryption process
cryptoStream.FlushFinalBlock();
// Convert the encrypted data from a MemoryStream to a byte array
byte[] cipherBytes = memoryStream.ToArray();
// Close both the MemoryStream and the CryptoStream
memoryStream.Close();
cryptoStream.Close();
// Convert the encrypted byte array to a base64 encoded string
string cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length);
// Return the encrypted data as a string
return cipherText;
}

IV of first 16 bytes gets remove from decrypted string? C#/Python3

I was wondering why the first 16 bytes of all my strings being encrypted, then when being decrypted are missing and how to fix this if it is possible. I am encrypting like so in c#
public static string EncryptString(string b_key, string plainText)
{
byte[] iv = new byte[16];
byte[] array;
using (Aes aes = Aes.Create())
{
aes.Key = Convert.FromBase64String(b_key);
aes.IV = iv;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream))
{
streamWriter.Write(plainText);
}
array = memoryStream.ToArray();
}
}
}
return Convert.ToBase64String(array);
}
and decrypting in python3 like so
enc = base64.b64decode(self.text)
iv = enc[:16]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
plain_text = cipher.decrypt(enc[16:])
plain_text = self.dePKCS7_padding(plain_text)
return plain_text
Is readding the first 16 bytes possible? or must be used for encryption. I also want it to crypto safe but the first 16 bytes are kind of important is this possible? anyway to get around this in either c# or python3?
Based on the discussion in comments and inputs from #MichaelFehr and #user9014097, I came up with the following code.
In this code the IV of AES will have random value created when AES.Create() is called. And the same will be used in the outcome of the encrypted value.
The decryptString method will capture the iv value from the incoming encrypted string and assign it to AES while decrypting the string.
public static string EncryptString(string b_key, string plainText)
{
byte[] array;
using (Aes aes = Aes.Create())
{
aes.Key = Convert.FromBase64String(b_key);
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream())
{
// Adding aes.IV to the stream's start.
memoryStream.Write(aes.IV);
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter streamWriter = new StreamWriter(cryptoStream))
{
streamWriter.Write(plainText);
}
}
array = memoryStream.ToArray();
}
}
// The final encrypted outcome will be aes.IV+encryptedtext.
return Convert.ToBase64String(array);
}
public static string DecryptString(string key, string cipherText)
{
//input is iv+encrypted text, convert them to byte array.
byte[] buffer = Convert.FromBase64String(cipherText);
// byte array for iv
byte[] iv = new byte[16];
// byte array for rest of the cipher text.
byte[] cipherBuffer = new byte[buffer.Length - 16];
// copy first 16 bytes from the cipher text to iv.
Buffer.BlockCopy(buffer, 0, iv, 0, 16);
// copy rest of the cipher text to the cipher buffer to be decrypted.
Buffer.BlockCopy(buffer, 16, cipherBuffer, 0, buffer.Length - 16);
using (Aes aes = Aes.Create())
{
aes.Key = Convert.FromBase64String(key);
aes.IV = iv;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream(cipherBuffer))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
using (StreamReader streamReader = new StreamReader(cryptoStream))
{
return streamReader.ReadToEnd();
}
}
}
}
}
I have following assumption in writing above code.
Length of IV is 16.
Python code (shared above) does not need split the input text based on some specific character. It takes first 16 bytes as IV value and rest of the bytes as cipher text.
I was able to encrypt and decrypt values successfully in C# using above methods.
I was not able to decrypt the value in python code as I have little to no idea on how to work with python.
You can test the outcome of above encryption in python to decrypt it. Let me know if it doesn't work as expected.
I hope this will help you solve your issue.

AES-ECB block-decryption in C#

I wrote code that decrypts the input string completely. But since this is an ECB mode, I wanted to somehow decrypt not the entire input text, but only a separate block of it.
As far as I understand, ECB AES encrypts in blocks of 8 bytes. How can I add the AES_Decrypt function to it so that it decrypts only the last 8 bytes of the input string, for example.
byte[] bytesToBeDecrypted = new byte[32];
byte[] 8_bytesToBeDecrypted = new byte[8]; // Only 8 bytes of bytesToBeDecrypted
public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
string salt = "12345678";
Encoding unicode = Encoding.Unicode;
byte[] saltBytes = unicode.GetBytes(salt);
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Padding = PaddingMode.Zeros;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 65535);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.ECB;
using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
You can likely just Seek the MemoryStream with a multiple of 16 bytes from the beginning (or apparently even 16 bytes from the last part of the stream) and then connect the CryptoStream to decrypt whatever is left. With CBC that would be a bit more tricky as you would have to set the IV to the previous ciphertext block, but with ECB this should be a breeze.
Notes:
Of course, you don't need to set the IV for the ECB mode, that should not be required.
Rijndael with a block size of 128 is actually AES. C#/.NET only supports a subset of Rijndael by the way: only 64 increments of the block size and key size are supported, if I remember correctly.
I'd still use aes = Aes.Create() rather than aes = new RijndaelManaged() as that leaves the choice of the AES implementation to the system, and it will probably choose the hardware accelerated one over the managed one.

encryption with single key in c#

i have a code in c# that encrypt and decrypt .txt file. but i need to encrypt and decrypt files with any extension like pdf, zip, jpg etc..
i searched ant tried to find stream encryption but i couldnt find any..
i am trying following code from link . i changed file path and put some pdf or ppt. it works correctly but i can not open decrypted file.
using System;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.Text;
namespace CSEncryptDecrypt
{
class Class1
{
// Call this function to remove the key from memory after use for security
[System.Runtime.InteropServices.DllImport("KERNEL32.DLL", EntryPoint="RtlZeroMemory")]
public static extern bool ZeroMemory(IntPtr Destination, int Length);
// Function to Generate a 64 bits Key.
static string GenerateKey()
{
// Create an instance of Symetric Algorithm. Key and IV is generated automatically.
DESCryptoServiceProvider desCrypto =(DESCryptoServiceProvider)DESCryptoServiceProvider.Create();
// Use the Automatically generated key for Encryption.
return ASCIIEncoding.ASCII.GetString(desCrypto.Key);
}
static void EncryptFile(string sInputFilename,
string sOutputFilename,
string sKey)
{
FileStream fsInput = new FileStream(sInputFilename,
FileMode.Open,
FileAccess.Read);
FileStream fsEncrypted = new FileStream(sOutputFilename,
FileMode.Create,
FileAccess.Write);
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
ICryptoTransform desencrypt = DES.CreateEncryptor();
CryptoStream cryptostream = new CryptoStream(fsEncrypted,
desencrypt,
CryptoStreamMode.Write);
byte[] bytearrayinput = new byte[fsInput.Length];
fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Close();
fsInput.Close();
fsEncrypted.Close();
}
static void DecryptFile(string sInputFilename,
string sOutputFilename,
string sKey)
{
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
//A 64 bit key and IV is required for this provider.
//Set secret key For DES algorithm.
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
//Set initialization vector.
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
//Create a file stream to read the encrypted file back.
FileStream fsread = new FileStream(sInputFilename,
FileMode.Open,
FileAccess.Read);
//Create a DES decryptor from the DES instance.
ICryptoTransform desdecrypt = DES.CreateDecryptor();
//Create crypto stream set to read and do a
//DES decryption transform on incoming bytes.
CryptoStream cryptostreamDecr = new CryptoStream(fsread,
desdecrypt,
CryptoStreamMode.Read);
//Print the contents of the decrypted file.
StreamWriter fsDecrypted = new StreamWriter(sOutputFilename);
fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd());
fsDecrypted.Flush();
fsDecrypted.Close();
}
static void Main()
{
// Must be 64 bits, 8 bytes.
// Distribute this key to the user who will decrypt this file.
string sSecretKey;
// Get the Key for the file to Encrypt.
sSecretKey = GenerateKey();
// For additional security Pin the key.
GCHandle gch = GCHandle.Alloc( sSecretKey,GCHandleType.Pinned );
// Encrypt the file.
EncryptFile(#"C:\MyData.txt",
#"C:\Encrypted.txt",
sSecretKey);
// Decrypt the file.
DecryptFile(#"C:\Encrypted.txt",
#"C:\Decrypted.txt",
sSecretKey);
// Remove the Key from memory.
ZeroMemory(gch.AddrOfPinnedObject(), sSecretKey.Length * 2);
gch.Free();
}
}
}
thanks for responses. i found the reason. i should use filestream not the streamwriter in the decryptFile function
following routine I'm using to serialize objects securely.
Maybe it can help you to understand how stream encryption works:
public bool Save(string filename, object toSerialize)
{
byte[] SALT = new byte[]
{0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c};
string EncryptionKey = "MYPASSWORD";
//basic serialization
IFormatter form = new BinaryFormatter();
var stream = new MemoryStream();
form.Serialize(stream, toSerialize);
//cryptography preparation
var alg = new RijndaelManaged();
var pdb = new Rfc2898DeriveBytes(EncryptionKey, SALT);
alg.Key = pdb.GetBytes(32);
alg.IV = pdb.GetBytes(16);
stream.Position = 0;
//cryptorgraphy serialization
var encStream = new MemoryStream();
var cryptoStream = new CryptoStream(encStream, alg.CreateEncryptor(), CryptoStreamMode.Write);
cryptoStream.Write(stream.ToArray(), 0, (int)stream.Length);
cryptoStream.FlushFinalBlock();
var outputFileStream = new FileStream(fileName, FileMode.Create);
outputFileStream.Write(encStream.ToArray(), 0, (int)encStream.Length);
outputFileStream.Close();
return true;
}
I can also put you sources to deserialize encrypted stream.

"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);
}
}

Categories

Resources