C# Rijndael encryption puts extra bytes in front of the decrypted files - c#

I'm trying to encrypt image files using Rijndael encryption and I must be doing something wrong because the decrypted files are coming out with extra data at the front of the file any maybe a little extra at the end. I'm fairly new to this encryption algorithm so I'm pretty sure I'm just missing something simple.
Examples using text files
Input file
"the quick brown fox jumped over the lazy yellow dog"
Output file when I try to put a generated IV at the front of the file(\0=null)
"ÚñjÐæƒÊW®ï¡_Ü&ßthe\0 quick brown fox jumped over the lazy yellow dog"
Output file when I try to put an IV that is equal to my Key at front
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0the\0\0\0\0\0\0 quick brown fox jumped over the lazy yellow dog"
Output file when I use an IV that is equal to my Key and put nothing at front of file
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0the\0\0\0\0\0\0 quick brown fox jumped over the lazy yellow dog"
CODE
private RijndaelManaged GetCipher(byte[] key, bool forEncrypt)
{
RijndaelManaged rijndaelCipher;
rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
rijndaelCipher.Key = key;
/* if (forEncrypt)
rijndaelCipher.GenerateIV();
else
rijndaelCipher.IV = new byte[16];*/
rijndaelCipher.IV = _imageKey;
return rijndaelCipher;
}
public void DecryptStamp(Stamp stampToDecrypt, string decrpytedStampFilePath)
{
RijndaelManaged rijndaelCipher;
FileStream inputStream = null;
FileStream outputStream = null;
CryptoStream encryptSteam = null;
byte[] block;
int numberRead;
ICryptoTransform transform;
if (!File.Exists(stampToDecrypt.Path))
throw new FileNotFoundException(stampToDecrypt.Path + " does not exist");
rijndaelCipher = this.GetCipher(_imageKey, false);
block = new byte[16];
try
{
inputStream = File.Open(stampToDecrypt.Path, FileMode.Open, FileAccess.Read);
outputStream = File.Open(decrpytedStampFilePath, FileMode.Create, FileAccess.Write);
//inputStream.Read(rijndaelCipher.IV, 0, rijndaelCipher.IV.Length);
transform = rijndaelCipher.CreateDecryptor();
encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
{
Console.WriteLine(numberRead.ToString());
encryptSteam.Write(block, 0, numberRead);
}
}
finally
{
rijndaelCipher.Clear();
rijndaelCipher.Dispose();
if (encryptSteam != null)
encryptSteam.Dispose();
if (outputStream != null)
outputStream.Dispose();
if (inputStream != null)
inputStream.Dispose();
}
}
public Stamp EncryptStampToStampFolder(string stampFileToEncrpyt)
{
Configuration config;
Stamp stampToEncrypt;
RijndaelManaged rijndaelCipher;
string encryptedFilePath;
if (!File.Exists(stampFileToEncrpyt))
throw new FileNotFoundException(stampFileToEncrpyt + " does not exist");
config = Configuration.GetProgramInstance();
encryptedFilePath = Path.Combine(config.StampFolder, Path.GetFileNameWithoutExtension(stampFileToEncrpyt) + ".stmp");
stampToEncrypt = new Stamp(Path.GetFileNameWithoutExtension(stampFileToEncrpyt), encryptedFilePath);
rijndaelCipher = this.GetCipher(_imageKey, true);
ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
FileStream inputStream = null;
FileStream outputStream = null;
CryptoStream encryptSteam = null;
byte[] block = new byte[16];
int numberRead;
try
{
inputStream = File.Open(stampFileToEncrpyt, FileMode.Open, FileAccess.Read);
outputStream = File.Open(encryptedFilePath, FileMode.Create, FileAccess.Write);
//outputStream.Write(rijndaelCipher.IV, 0, 16);
encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
encryptSteam.Write(block, 0, block.Length);
while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
{
encryptSteam.Write(block, 0, numberRead);
}
}
finally
{
rijndaelCipher.Clear();
rijndaelCipher.Dispose();
if (encryptSteam != null)
encryptSteam.Dispose();
if (outputStream != null)
outputStream.Dispose();
if (inputStream != null)
inputStream.Dispose();
}
return stampToEncrypt;
}
public struct Stamp
{
public string Name,
Path;
public Stamp(string StampName, string StampPath)
{
Name = StampName;
Path = StampPath;
}
}
CODE post fix
private RijndaelManaged GetCipher(byte[] key, bool forEncrypt)
{
RijndaelManaged rijndaelCipher;
rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
rijndaelCipher.Key = key;
if (forEncrypt)
rijndaelCipher.GenerateIV();
else
rijndaelCipher.IV = new byte[16];
//rijndaelCipher.IV = _imageKey;
return rijndaelCipher;
}
public void DecryptStamp(Stamp stampToDecrypt, string decrpytedStampFilePath)
{
RijndaelManaged rijndaelCipher;
FileStream inputStream = null;
FileStream outputStream = null;
CryptoStream encryptSteam = null;
byte[] block;
int numberRead;
ICryptoTransform transform;
if (!File.Exists(stampToDecrypt.Path))
throw new FileNotFoundException(stampToDecrypt.Path + " does not exist");
rijndaelCipher = this.GetCipher(_imageKey, false);
block = new byte[16];
try
{
inputStream = File.Open(stampToDecrypt.Path, FileMode.Open, FileAccess.Read);
outputStream = File.Open(decrpytedStampFilePath, FileMode.Create, FileAccess.Write);
inputStream.Read(rijndaelCipher.IV, 0, rijndaelCipher.IV.Length);
transform = rijndaelCipher.CreateDecryptor();
encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
{
encryptSteam.Write(block, 0, numberRead);
}
}
finally
{
rijndaelCipher.Clear();
rijndaelCipher.Dispose();
if (encryptSteam != null)
encryptSteam.Dispose();
if (outputStream != null)
outputStream.Dispose();
if (inputStream != null)
inputStream.Dispose();
}
}
public Stamp EncryptStampToStampFolder(string stampFileToEncrpyt)
{
Configuration config;
Stamp stampToEncrypt;
RijndaelManaged rijndaelCipher;
string encryptedFilePath;
if (!File.Exists(stampFileToEncrpyt))
throw new FileNotFoundException(stampFileToEncrpyt + " does not exist");
config = Configuration.GetProgramInstance();
encryptedFilePath = Path.Combine(config.StampFolder, Path.GetFileNameWithoutExtension(stampFileToEncrpyt) + ".stmp");
stampToEncrypt = new Stamp(Path.GetFileNameWithoutExtension(stampFileToEncrpyt), encryptedFilePath);
rijndaelCipher = this.GetCipher(_imageKey, true);
ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
FileStream inputStream = null;
FileStream outputStream = null;
CryptoStream encryptSteam = null;
byte[] block = new byte[16];
int numberRead;
try
{
inputStream = File.Open(stampFileToEncrpyt, FileMode.Open, FileAccess.Read);
outputStream = File.Open(encryptedFilePath, FileMode.Create, FileAccess.Write);
outputStream.Write(rijndaelCipher.IV, 0, 16);
encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
//encryptSteam.Write(block, 0, block.Length); this line was the problem in the orginal code
while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
{
encryptSteam.Write(block, 0, numberRead);
}
}
finally
{
rijndaelCipher.Clear();
rijndaelCipher.Dispose();
if (encryptSteam != null)
encryptSteam.Dispose();
if (outputStream != null)
outputStream.Dispose();
if (inputStream != null)
inputStream.Dispose();
}
return stampToEncrypt;
}
public struct Stamp
{
public string Name,
Path;
public Stamp(string StampName, string StampPath)
{
Name = StampName;
Path = StampPath;
}
}
New Code's output
"7p¶¼oò¾½G€¢9±hfox\0\0 jumped over the lazy yellow dog"

The problem was three fold.
1)Extra data being written during encryption
2)The IV at the beginning of the file was being overwritten
3)The IV was not being read properly on decryption
CODE Fixed
private RijndaelManaged GetCipher(byte[] key, bool forEncrypt)
{
RijndaelManaged rijndaelCipher;
rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
rijndaelCipher.Key = key;
if (forEncrypt)
rijndaelCipher.GenerateIV();
else
rijndaelCipher.IV = new byte[16];
//rijndaelCipher.IV = _imageKey;
return rijndaelCipher;
}
public void DecryptStamp(Stamp stampToDecrypt, string decrpytedStampFilePath)
{
RijndaelManaged rijndaelCipher;
FileStream inputStream = null;
FileStream outputStream = null;
CryptoStream encryptSteam = null;
byte[] block;
int numberRead;
ICryptoTransform transform;
if (!File.Exists(stampToDecrypt.Path))
throw new FileNotFoundException(stampToDecrypt.Path + " does not exist");
rijndaelCipher = this.GetCipher(_imageKey, false);
block = new byte[16];
try
{
inputStream = File.Open(stampToDecrypt.Path, FileMode.Open, FileAccess.Read);
outputStream = File.Open(decrpytedStampFilePath, FileMode.Create, FileAccess.Write);
//This line was wrong because rijndaelCipher.IV never filled
//inputStream.Read(rijndaelCipher.IV, 0, rijndaelCipher.IV.Length);
inputStream.Read(block, 0, block.Length);
rijndaelCipher.IV = block;
block = new byte[16];
transform = rijndaelCipher.CreateDecryptor();
encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
{
encryptSteam.Write(block, 0, numberRead);
}
}
finally
{
rijndaelCipher.Clear();
rijndaelCipher.Dispose();
if (encryptSteam != null)
encryptSteam.Dispose();
if (outputStream != null)
outputStream.Dispose();
if (inputStream != null)
inputStream.Dispose();
}
}
public Stamp EncryptStampToStampFolder(string stampFileToEncrpyt)
{
Configuration config;
Stamp stampToEncrypt;
RijndaelManaged rijndaelCipher;
string encryptedFilePath;
if (!File.Exists(stampFileToEncrpyt))
throw new FileNotFoundException(stampFileToEncrpyt + " does not exist");
config = Configuration.GetProgramInstance();
encryptedFilePath = Path.Combine(config.StampFolder, Path.GetFileNameWithoutExtension(stampFileToEncrpyt) + ".stmp");
stampToEncrypt = new Stamp(Path.GetFileNameWithoutExtension(stampFileToEncrpyt), encryptedFilePath);
rijndaelCipher = this.GetCipher(_imageKey, true);
ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
FileStream inputStream = null;
FileStream outputStream = null;
CryptoStream encryptSteam = null;
byte[] block = new byte[16];
int numberRead;
try
{
inputStream = File.Open(stampFileToEncrpyt, FileMode.Open, FileAccess.Read);
outputStream = File.Open(encryptedFilePath, FileMode.Create, FileAccess.Write);
outputStream.Write(rijndaelCipher.IV, 0, IV.Length);
//This had to be changed so that the IV was not overwitten
//encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
encryptSteam = new CryptoStream(inputStream, transform, CryptoStreamMode.Read);
//this line was a problem in the orginal code that caused extra data to be added to the encrypted file
//encryptSteam.Write(block, 0, block.Length);
while ((numberRead = encryptSteam.Read(block, 0, block.Length)) > 0)
{
outputStream.Write(block, 0, numberRead);
}
}
finally
{
rijndaelCipher.Clear();
rijndaelCipher.Dispose();
if (encryptSteam != null)
encryptSteam.Dispose();
if (outputStream != null)
outputStream.Dispose();
if (inputStream != null)
inputStream.Dispose();
}
return stampToEncrypt;
}
public struct Stamp
{
public string Name,
Path;
public Stamp(string StampName, string StampPath)
{
Name = StampName;
Path = StampPath;
}
}

Here's what I do to decrypt:
private RijndaelManaged GetAesProvider(Stream stm, bool isEncryption)
{
byte[] finalKey = GetFinalKey();
// GetIV either gets salt on encryption and writes it into stm
// or reads it from stm if it's decryption
byte[] iv = GetIV(stm, isEncryption);
RijndaelManaged aes = new RijndaelManaged();
aes.BlockSize = kAesBlockSizeInBytes * 8;
aes.IV = iv;
aes.Key = finalKey;
aes.Mode = CipherMode.CBC;
return aes;
}
public override Stream GetDecryptionStream(Stream source)
{
if (source.Length <= kIVSize)
{
return new EmptyStream();
}
RijndaelManaged aes = GetAesProvider(source, false);
ICryptoTransform xform = aes.CreateDecryptor(aes.Key, aes.IV);
return new CryptoStream(source, xform, CryptoStreamMode.Read);
}

Related

Parallel + Stream + Encryption ... c# supposed to work

Something very weird occur in my code.
If i create a simple for without parallel my code working fine.
But when I add Parallel.For it's no more working.
The problem is when it's rebuild the binary are not the same with the Parallel For but it's the same with the normal For ...
I create a sample for the example.
Essentially, the code only read a file, save it in chunck.
After "Simulate upload", just rebuild the file with the same Key and IV.
Like i said in the normal For everything working fine.
// Decryption
public static byte[] DecryptBinaryFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream())
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write))
{
csDecrypt.Write(cipherText, 0, cipherText.Length);
csDecrypt.Close();
}
return msDecrypt.ToArray();
}
}
}
// Encryption
public static byte[] EncryptBinary(byte[] binary, byte[] Key, byte[] IV)
{
// Check arguments.
if (binary == null || binary.Length <= 0)
throw new ArgumentNullException("Binary");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (BinaryWriter swEncrypt = new BinaryWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(binary);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
// Rebuild the file
static void RebuildFile(string directory, string file, int totalParts)
{
string finalName = string.Concat(directory, file);
using (FileStream fs = new FileStream(finalName, FileMode.Append))
{
for (int i = 0; i < totalParts; i++)
{
string fileName = $"{i.ToString("00000")}-{file}";
string path = Path.Combine(directory, fileName);
byte[] binary = DecryptBinaryFromBytes(File.ReadAllBytes(path), key, iv);
fs.Write(binary, 0, binary.Length);
}
fs.Close();
}
}
// Simulate upload
static void SimulateUpload(string filePath, byte[] binary)
{
binary = EncryptBinary(binary,key, iv);
using (FileStream fs = new FileStream(filePath, FileMode.Append))
{
fs.Write(binary, 0, binary.Length);
}
}
// variable declaration
static byte[] key;
static byte[] iv;
// The main method
static void Main(string[] args)
{
key = Guid.NewGuid().ToByteArray().Concat(Guid.NewGuid().ToByteArray()).ToArray();
iv = Guid.NewGuid().ToByteArray();
string inputFile = #"C:\temp\Fonctionnement-FR.docx";
string directory = #"C:\temp\uploads\";
const long BUFFER_SIZE = 524288;
byte[] buffer = new byte[BUFFER_SIZE];
FileInfo fInfo = new FileInfo(inputFile);
long totalBytes = fInfo.Length;
double estimateTotalChuck = Math.Ceiling((totalBytes / BUFFER_SIZE) + 0.5);
int totalParts = (int)estimateTotalChuck;
string fileName = Path.GetFileName(inputFile);
string fileExtension = Path.GetExtension(inputFile);
// This one is Working
for (int idx=0;idx<totalParts; idx++)
{
using (Stream input = new FileStream(inputFile, FileMode.Open, FileAccess.Read))
{
using (MemoryStream output = new MemoryStream())
{
long startPosition = (idx * BUFFER_SIZE);
long maxPosition = startPosition + BUFFER_SIZE;
int maxBufferRead = (int)BUFFER_SIZE;
input.Seek(startPosition, SeekOrigin.Begin);
if (maxPosition > totalBytes)
{
maxBufferRead = (int)(totalBytes - startPosition);
}
input.Read(buffer, 0, maxBufferRead);
output.Write(buffer, 0, maxBufferRead);
SimulateUpload(string.Concat(directory, $"{idx.ToString("00000")}-{fileName}"), output.ToArray());
// upFile = UploadSingleFile(endPoint, new FileArgs(output.ToArray(), fileName, fileExtension, idx, totalParts), handShake, chunkSize, idx, totalParts, fileIdentifier);
}
}
}
// This one is not working
Parallel.For(0, (int)estimateTotalChuck, new ParallelOptions { MaxDegreeOfParallelism = 5 }, idx =>
{
using (Stream input = new FileStream(inputFile, FileMode.Open, FileAccess.Read))
{
using (MemoryStream output = new MemoryStream())
{
long startPosition = (idx * BUFFER_SIZE);
long maxPosition = startPosition + BUFFER_SIZE;
int maxBufferRead = (int)BUFFER_SIZE;
input.Seek(startPosition, SeekOrigin.Begin);
if (maxPosition > totalBytes)
{
maxBufferRead = (int)(totalBytes - startPosition);
}
input.Read(buffer, 0, maxBufferRead);
output.Write(buffer, 0, maxBufferRead);
SimulateUpload(string.Concat(directory, $"{idx.ToString("00000")}-{fileName}"), output.ToArray());
// upFile = UploadSingleFile(endPoint, new FileArgs(output.ToArray(), fileName, fileExtension, idx, totalParts), handShake, chunkSize, idx, totalParts, fileIdentifier);
}
}
});
RebuildFile(directory, fileName, totalParts);
}
When you switch to parallel code, you need to be acutely aware of where all locals are declared; anything declared outside the parallel region will be shared by all the parallel threads. In this case, it looks like buffer is a key contender, and since that is the primary data exchange mechanism, it would be entirely expected that if multiple threads are reading and writing to buffer concurrently, that they're all virtually guaranteed to trip over each-other.
But: check all the other locals too! If in doubt: move the code that runs in parallel to a separate method. It is hard to trip over shared locals in that scenario. Note that for ref-type parameters (such as byte[]), you'd also need to ensure that the objects are separate - separate locals to the same object has the same problem.

Encode CryptoStream to Base64 String in Chunks in C#

There is a method (Version1) that encodes an input stream and there is a function Decrypt() that successfully decodes encoded data. But when the input data is large there could be an error OutOfMemory (on the line "string textEncrypted = Convert.ToBase64String (ms.ToArray())").
Version1
private static Stream EncryptRijndael1(byte[] key, byte[] iv, Stream plainText)
{
if (plainText == null)
return null;
byte[] bytesEncrypted;
RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
byte[] buffer = new byte[16 * 1024];
int readed;
while ((readed = (plainText.Read(buffer, 0, buffer.Length))) > 0)
{
cs.Write(buffer, 0, readed);
}
}
string textEncrypted = Convert.ToBase64String(ms.ToArray());
bytesEncrypted = Encoding.ASCII.GetBytes(textEncrypted);
}
return new MemoryStream(bytesEncrypted);
}
So I modified the method to process an array part by part (chunks).
Here is Version2. It causes an error "offset and length must refer to a position in the string" in the line Convert.ToBase64String (ms.ToArray(), offset, read).
Version2
private static Stream EncryptRijndael2(byte[] key, byte[] iv, Stream plainText)
{
if (plainText == null)
return null;
byte[] bytesEncrypted;
RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv);
string textEncrypted = String.Empty;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
byte[] buffer = new byte[16 * 1024];
int readed;
int offset = 0;
while ((readed = (plainText.Read(buffer, 0, buffer.Length))) > 0)
{
cs.Write(buffer, 0, readed);
textEncrypted += Convert.ToBase64String(ms.ToArray(), offset, readed);
offset += readed;
}
}
bytesEncrypted = Encoding.ASCII.GetBytes(textEncrypted);
}
return new MemoryStream(bytesEncrypted);
}
Then I made Version3. It works without errors but the output data length now is bigger than in Version1 having the same input data.
Decryt() function throws an error "The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters."
Version3
private static Stream EncryptRijndael3(byte[] key, byte[] iv, Stream plainText)
{
if (plainText == null)
return null;
byte[] bytesEncrypted;
RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv);
using (MemoryStream ms = new MemoryStream())
{
string textEncrypted = String.Empty;
using (CryptoStream cs = new CryptoStream(ms, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
byte[] buffer = new byte[16*1024];
int readed;
while ((readed = (plainText.Read(buffer, 0, buffer.Length))) > 0)
{
cs.Write(buffer, 0, readed);
}
}
byte[] buffer1 = new byte[16*1024];
int readed1;
using (MemoryStream ms1 = new MemoryStream(ms.ToArray()))
{
while ((readed1 = (ms1.Read(buffer1, 0, buffer1.Length))) > 0)
{
if (readed1 < buffer1.Length)
{
var lastBuf = new List<Byte>();
for (int i = 0; i < readed1; i++)
{
lastBuf.Add(buffer1[i]);
}
textEncrypted += Convert.ToBase64String(lastBuf.ToArray());
continue;
}
textEncrypted += Convert.ToBase64String(buffer1);
}
}
bytesEncrypted = Encoding.ASCII.GetBytes(textEncrypted);
}
return new MemoryStream(bytesEncrypted);
}
My RijndaelManaged
private static RijndaelManaged RijndaelManagedWithConfig(byte[] key, byte[] iv)
{
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 128;
rjndl.Key = key;
rjndl.IV = iv;
rjndl.Mode = CipherMode.CBC;
rjndl.Padding = PaddingMode.PKCS7;
return rjndl;
}
Please help me to get rid of the errors or tell me how to make the Version1 process Convert.ToBase64String data partially.
I have achieved the decision
private static Stream EncryptRijndael(byte[] key, byte[] iv, Stream plainText)
{
if (plainText == null)
return null;
byte[] buffer = new byte[5120 * 1024];
RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv);
using (var memoryStream = new MemoryStream())
{
int readedBytes;
using (var cs = new CryptoStream(memoryStream, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
while ((readedBytes = (plainText.Read(buffer, 0, buffer.Length))) > 0)
{
cs.Write(buffer, 0, readedBytes);
}
}
using (var cryptoMemoryStream = new MemoryStream(memoryStream.ToArray()))
{
using (var base64MemoryStream = new MemoryStream())
{
using (ICryptoTransform transform = new ToBase64Transform())
{
using (var cryptStream = new CryptoStream(base64MemoryStream, transform, CryptoStreamMode.Write))
{
while ((readedBytes = cryptoMemoryStream.Read(buffer, 0, buffer.Length)) > 0)
{
cryptStream.Write(buffer, 0, readedBytes);
}
cryptStream.FlushFinalBlock();
}
return new MemoryStream(base64MemoryStream.ToArray());
}
}
}
}
}

Cant access the file because its being used in another process do I multi-thread?

I have this applcation where it makes it easier for me when I screenshot and I need to send the screenshot to a friend/family and I wanted to take it to the next level where I encrypt the image before it saves.
The issue is that when I try it this way, it cuts the stream because it says that its being used in another process.
Did I make it flow the wrong way? Do I need to multi-thread?
Which method would be best for this, Await & Async?
public string generateKey()
{
DESCryptoServiceProvider desCrypto = (DESCryptoServiceProvider)DESCryptoServiceProvider.Create();
return ASCIIEncoding.ASCII.GetString(desCrypto.Key);
}
private void saveScreenshot()
{
string path;
path = "%AppData%\\Image.png"; // collection of paths
path = Environment.ExpandEnvironmentVariables(path);
if (Clipboard.ContainsImage() == true)
{
Image image = (Image)Clipboard.GetDataObject().GetData(DataFormats.Bitmap);
image.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);
}
else
{
}
}
private void encryptImage()
{
try
{
string path;
path = "%AppData%\\Image.png"; // collection of paths
path = Environment.ExpandEnvironmentVariables(path);
encrypt(path, path, key);
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
//--------------------File Encryptor--------------------
private void encrypt(string input, string output, string strhash)
{
FileStream inFs, outFs;
CryptoStream cs;
TripleDESCryptoServiceProvider TDC = new TripleDESCryptoServiceProvider();
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] byteHash, byteTexto;
inFs = new FileStream(input, FileMode.Open, FileAccess.Read);
outFs = new FileStream(output, FileMode.OpenOrCreate, FileAccess.Write);
byteHash = md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(strhash));
byteTexto = File.ReadAllBytes(input);
md5.Clear();
TDC.Key = byteHash;
TDC.Mode = CipherMode.ECB;
cs = new CryptoStream(outFs, TDC.CreateEncryptor(), CryptoStreamMode.Write);
int byteRead;
long length, position = 0;
length = inFs.Length;
while (position < length)
{
byteRead = inFs.Read(byteTexto, 0, byteTexto.Length);
position += byteRead;
cs.Write(byteTexto, 0, byteRead);
}
inFs.Close();
outFs.Close();
}
//--------------------File Encryptor--------------------
private void screenshot()
{
System.Windows.Forms.SendKeys.SendWait("{PRTSC}");
}

reading / writing encrypted xml

I can read an write my serialized class fine until I try to encrypt / decrypt... here is a snippet of my code:
public class ShelfCache
{
public Shelf Data;
public ShelfCache()
{
Data = new Shelf();
}
public void Write(string Filename)
{
XmlSerializer xsl = new XmlSerializer(typeof(Shelf));
TextWriter xslWriter = new StreamWriter(Filename);
xsl.Serialize(xslWriter, Data);
xslWriter.Flush();
xslWriter.Close();
}
public void Read(string Filename)
{
Data = new Shelf();
XmlSerializer xsl = new XmlSerializer(typeof(Shelf));
TextReader xslReader = new StreamReader(Filename);
Data = (Shelf)xsl.Deserialize(xslReader);
xslReader.Close();
}
public void WriteEncrypted(string Filename, string EncryptionKey = "")
{
string _Key = EncryptionKey + Environment.ExpandEnvironmentVariables("%USERNAME%%COMPUTERNAME%123456789ABCDEF0123456789abcdef").Substring(0, 32);
string _IV = Environment.ExpandEnvironmentVariables("%COMPUTERNAME%123456789abcdef").Substring(0, 16);
byte[] Key = Encoding.UTF8.GetBytes(_Key);
byte[] IV = Encoding.UTF8.GetBytes(_IV);
FileStream CacheStream = new FileStream(Filename, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
RijndaelManaged CryptoProvider = new RijndaelManaged();
ICryptoTransform CacheTransform = CryptoProvider.CreateEncryptor(Key, IV);
CryptoStream EncryptionStream = new CryptoStream(CacheStream, CacheTransform, CryptoStreamMode.Write);
XmlSerializer xsl = new XmlSerializer(typeof(Shelf));
xsl.Serialize(EncryptionStream, Data);
EncryptionStream.Flush();
CacheStream.Close();
}
public void ReadEncrypted(string Filename, string EncryptionKey = "")
{
string _Key = EncryptionKey + Environment.ExpandEnvironmentVariables("%USERNAME%%COMPUTERNAME%123456789ABCDEF0123456789abcdef").Substring(0, 32);
string _IV = Environment.ExpandEnvironmentVariables("%COMPUTERNAME%123456789abcdef").Substring(0, 16);
byte[] Key = Encoding.UTF8.GetBytes(_Key);
byte[] IV = Encoding.UTF8.GetBytes(_IV);
FileStream CacheStream = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
RijndaelManaged CryptoProvider = new RijndaelManaged();
ICryptoTransform CacheTransform = CryptoProvider.CreateEncryptor(Key, IV);
CryptoStream DecryptionStream = new CryptoStream(CacheStream, CacheTransform, CryptoStreamMode.Read);
XmlSerializer xsl = new XmlSerializer(typeof(Shelf));
Data = (Shelf)xsl.Deserialize(DecryptionStream);
CacheStream.Close();
}
}
I get the exception "There is an error in XML document (1 1)." with an inner exception "Data at the root level is invalid. Line 1, position 1." on the line:
Data = (Shelf)xsl.Deserialize(DecryptionStream);
This is what I ended up doing (I don't like the solution, but it works)...
public class ShelfCache
{
public Shelf Data;
public ShelfCache()
{
Data = new Shelf();
}
public void Write(string Filename)
{
XmlSerializer CacheSerializer = new XmlSerializer(typeof(Shelf));
TextWriter CacheWriter = new StreamWriter(Filename);
CacheSerializer.Serialize(CacheWriter, Data);
CacheWriter.Flush();
CacheWriter.Close();
}
public void Read(string Filename)
{
Data = new Shelf();
XmlSerializer CacheSerializer = new XmlSerializer(typeof(Shelf));
TextReader CacheReader = new StreamReader(Filename);
Data = (Shelf)CacheSerializer.Deserialize(CacheReader);
CacheReader.Close();
}
public void WriteEncrypted(string Filename, string EncryptionKey = "")
{
string TempFile = System.IO.Path.GetTempFileName();
Write(TempFile);
EncryptFile(TempFile, Filename, EncryptionKey);
File.Delete(TempFile);
}
public void ReadEncrypted(string Filename, string EncryptionKey = "")
{
string TempFile = System.IO.Path.GetTempFileName();
DecryptFile(Filename, TempFile, EncryptionKey);
Read(TempFile);
File.Delete(TempFile);
}
private RijndaelManaged GetEncryptor(string Key = "", string Salt = "")
{
Key += Environment.ExpandEnvironmentVariables("%USERNAME%");
Salt += Environment.ExpandEnvironmentVariables("%COMPUTERNAME%");
Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(Key, Encoding.Unicode.GetBytes(Salt));
RijndaelManaged rijndaelCSP = new RijndaelManaged();
rijndaelCSP.Key = derivedKey.GetBytes(rijndaelCSP.KeySize / 8);
rijndaelCSP.IV = derivedKey.GetBytes(rijndaelCSP.BlockSize / 8);
return rijndaelCSP;
}
private void EncryptFile(string Source, string Target, string EncryptionKey)
{
RijndaelManaged EncryptionProvider = GetEncryptor(EncryptionKey);
ICryptoTransform Encryptor = EncryptionProvider.CreateEncryptor();
FileStream SourceStream = new FileStream(Source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
byte[] SourceBytes = new byte[(int)SourceStream.Length];
SourceStream.Read(SourceBytes, 0, (int)SourceStream.Length);
FileStream TargetStream = new FileStream(Target, FileMode.Create, FileAccess.Write);
CryptoStream EncryptionStream = new CryptoStream(TargetStream, Encryptor, CryptoStreamMode.Write);
EncryptionStream.Write(SourceBytes, 0, (int)SourceStream.Length);
EncryptionStream.FlushFinalBlock();
EncryptionProvider.Clear();
EncryptionStream.Close();
SourceStream.Close();
TargetStream.Close();
}
private void DecryptFile(string Source, string Target, string EncryptionKey)
{
RijndaelManaged EncryptionProvider = GetEncryptor(EncryptionKey);
ICryptoTransform Decryptor = EncryptionProvider.CreateDecryptor();
FileStream SourceStream = new FileStream(Source, FileMode.Open, FileAccess.Read);
CryptoStream DecryptionStream = new CryptoStream(SourceStream, Decryptor, CryptoStreamMode.Read);
byte[] SourceBytes = new byte[(int)SourceStream.Length];
int DecryptionLength = DecryptionStream.Read(SourceBytes, 0, (int)SourceStream.Length);
FileStream TargetStream = new FileStream(Target, FileMode.Create, FileAccess.Write);
TargetStream.Write(SourceBytes, 0, DecryptionLength);
TargetStream.Flush();
EncryptionProvider.Clear();
DecryptionStream.Close();
SourceStream.Close();
TargetStream.Close();
}
}

cannot enter wrong but same digit of password to decrpyt C#

Currently my program can encrypt and decrypt however when ever i key in wrong but same digits of password the program will hang. was wondering how to i solve it?
Eg. correct password is 12345678 but i key in 12341234 which is same 8 digit but wrong key the decrpytion will hang
//Encrypt Method
public bool DESEncrypt(String input, String output, String key)
{
bool success = false;
try
{
int requiredLength = 8;
FileStream fsInput = new FileStream(input, FileMode.Open, FileAccess.Read);
FileStream fsEncrypted = new FileStream(output, FileMode.Create, FileAccess.Write);
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Padding = PaddingMode.PKCS7;
if (key.Length < requiredLength)
{
key = key.PadRight(requiredLength);
}
else if (key.Length > requiredLength)
{
key = key.Substring(0, requiredLength);
}
DES.Key = ASCIIEncoding.ASCII.GetBytes(key);
DES.IV = ASCIIEncoding.ASCII.GetBytes(key);
ICryptoTransform desEncrypt = DES.CreateEncryptor();
CryptoStream cryptoStream = new CryptoStream(fsEncrypted, desEncrypt, CryptoStreamMode.Write);
byte[] byteInput = new byte[fsInput.Length];
fsInput.Read(byteInput, 0, byteInput.Length);
cryptoStream.Write(byteInput, 0, byteInput.Length);
cryptoStream.Flush();
cryptoStream.Close();
fsInput.Close();
fsEncrypted.Close();
success = true;
MessageBox.Show("Lock Success!");
}
catch (Exception ex)
{
success = false;
MessageBox.Show("Encryption Unsuccessful!" + ex);
//To Be Continue.....
//File being processed error
//try .Dispose()?
}
return success;
}
//Decrypt method
public bool Decrypt(String input, String output, String key)
{
bool success = false;
try
{
int requiredLength = 8;
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Padding = PaddingMode.PKCS7;
if (key.Length < requiredLength)
{
key = key.PadRight(requiredLength);
}
else if (key.Length > requiredLength)
{
key = key.Substring(0, requiredLength);
}
//Set secret key For DES algorithm.
DES.Key = ASCIIEncoding.ASCII.GetBytes(key);
//Set initialization vector.
DES.IV = ASCIIEncoding.ASCII.GetBytes(key);
//Create a file stream to read the encrypted file back.
FileStream fsInput = new FileStream(input, 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(fsInput, desDecrypt, CryptoStreamMode.Read);
//Print the contents of the decrypted file.
BinaryWriter bw = new BinaryWriter(new FileStream(output, FileMode.Create, FileAccess.Write));
byte[] buffer = new byte[500];
int bytesRead = -1;
while (true)
{
bytesRead = cryptostreamDecr.Read(buffer, 0, 500);
if (bytesRead == 0)
{
break;
}
bw.Write(buffer, 0, bytesRead);
}
//StreamWriter fsDecrypted = new StreamWriter(output);
//fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd());
bw.Flush();
fsInput.Close();
cryptostreamDecr.Close();
bw.Close();
success = true;
MessageBox.Show("Unlock Success!");
}
catch (Exception ex)
{
success = false;
MessageBox.Show("Decryption Unsuccessful!" + ex);
//Try memory stream
}
return success;
}
}
}
As I said in the comment I don't think the problem is going to be with the decryption but with how you process the output.
However, the problem you have is that you need to be able to identify when an incorrect key has been used. The simplest way to do this is to include a fixed known value at the beginning of whatever you are encrypting before you encrypt it. Then, when you decrypt, you can check to see if the plain text begins with the known value and then discard the known value if it does and raise an error if it doesn't.

Categories