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.
Related
static SymmetricAlgorithm encryption;
static string password = "SBC";
static string salt = "ash";
public Decryption()
{
encryption = new RijndaelManaged();
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, Encoding.ASCII.GetBytes(salt));
encryption.Key = key.GetBytes(encryption.KeySize / 8);
encryption.IV = key.GetBytes(encryption.BlockSize / 8);
encryption.Padding = PaddingMode.PKCS7;
}
public void Decrypt(Stream inStream, Stream OutStream)
{
ICryptoTransform encryptor = encryption.CreateDecryptor();
inStream.Position = 0;
CryptoStream encryptStream1 = new CryptoStream(OutStream, encryptor, CryptoStreamMode.Write);
CopyTo(inStream, encryptStream1);
encryptStream1.FlushFinalBlock();
encryptStream1.Close();
inStream.Close();
OutStream.Close();
}
public void CopyTo(Stream input, Stream output)
{
// This method exists only in .NET 4 and higher
byte[] buffer = new byte[4 * 1024];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) != 0)
{
output.Write(buffer, 0, bytesRead);
}
}
In my windows form load i just create a thread and call the function to decrypt file, this is thread function
Thread objthreadhtml = new Thread(new ThreadStart(JsHtmlDecrypt));
objthreadhtml.IsBackground = true;
objthreadhtml.Name = "HtmlJsDecrypt";
objthreadhtml.Priority = ThreadPriority.Highest;
objthreadhtml.Start();
below function is decrypt function
public static void JsHtmlDecrypt()
{
string startPathForHtml = Application.LocalUserAppDataPath.Replace("\\OfflineApplication\\OfflineApplication\\1.0.0.0", "").ToString() + "\\Apps\\Html\\";
var directoryPathForHtml = new DirectoryInfo(startPathForHtml);
foreach (FileInfo fileForHtml in directoryPathForHtml.GetFiles())
{
FileStream inFsForHtml = fileForHtml.OpenRead();
FileInfo inforFHtml = new FileInfo(fileForHtml.FullName.Replace(fileForHtml.Extension, ".html"));
FileStream outFsForHtml = inforFHtml.Create();
UnZipDecryptionEncryption.Decryption m_decryption1 = new Decryption();
m_decryption1.Decrypt(inFsForHtml, outFsForHtml);
inFsForHtml.Close();
outFsForHtml.Close();
UnZipDecryptionEncryption.DeleteZipandFiles m_delete1 = new DeleteZipandFiles();
m_delete1.DeleteFiles(fileForHtml.FullName);
}
}
Here i get the error padding is invalid in the line
encryptStream1.FlushFinalBlock();
Please help me someone how to solve this i am stuck in it.
Your "decrypt" function is trying to do the opposite of what you want: encrypt the data:
CryptoStream encryptStream1 = new CryptoStream(OutStream, encryptor, CryptoStreamMode.Write);
What you want, I assume, is to decrypt it (my code uses byte arrays as input/output, so you may want to modify that):
ICryptoTransform decryptor = encryption.CreateDecryptor();
// byte[] (cipherText) <-- encryted text
MemoryStream memoryStream = new MemoryStream(cipherText);
// here is the most important part: CryptoStreamMode.Read
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherText.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
// my text uses UTF8 encoding, so to get the plain text as string:
string result = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
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);
}
To exchange AES-Encrypted messages, I encode the IV for each message with RSA and send it to the other client. This succeeds the first time I send a message, but then fails when sending the second message. The client fails decrypting the IV for the message with an OAEP-padding error.
This is my code:
writeAes(Encoding.UTF8.GetBytes("12345"), rmAes.Key, RSAprovider.ToXmlString(false)); // These are just some sample messages
writeAes(Encoding.UTF8.GetBytes("67890"), rmAes.Key, RSAprovider.ToXmlString(false));
public void writeAes(TcpClient client, byte[] writeBuffer, int offset, byte[] AESkey, string RSAXml) //Some of these arguments are optional
{
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.KeySize = 128;
rijAlg.Key = AESkey;
rijAlg.GenerateIV();
// Send IV
using (RSACryptoServiceProvider RSAprovider = new RSACryptoServiceProvider(4096))
{
RSAprovider.PersistKeyInCsp = false;
RSAprovider.FromXmlString(RSAXml);
this.write(client, RSAprovider.Encrypt(rijAlg.IV, true));
logger.Trace("Sent AES IV:\n{0}", BitConverter.ToString(rijAlg.IV).Replace("-", ""));
}
// Send Rijndael-encrypted Message
CryptoStream csEncrypt = null;
try
{
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
csEncrypt = new CryptoStream(client.GetStream(), encryptor, CryptoStreamMode.Write);
csEncrypt.Write(writeBuffer, offset, writeBuffer.Length);
csEncrypt.FlushFinalBlock();
encryptor.Dispose();
}
finally
{
/*if (csEncrypt != null)
csEncrypt.Dispose();*/
// TODO: This needs to be disposed somehow but leave the NetworkStream open
}
}
}
And for receiving:
logger.Debug("Got AES-Message:\n" + Encoding.UTF8.GetString(readAes(connectedClient, new byte[5], 0, aesKey, RSAprovider.ToXmlString(true))));
logger.Debug("Got AES-Message:\n" + Encoding.UTF8.GetString(readAes(connectedClient, new byte[5], 0, aesKey, RSAprovider.ToXmlString(true))));
public byte[] readAes(TcpClient client, byte[] readBuffer,int offset, byte[] AESkey, string RSAXml) //Some of these arguments are optional
{
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.KeySize = 128;
rijAlg.Key = AESkey;
using (RSACryptoServiceProvider RSAprovider = new RSACryptoServiceProvider(4096))
{
RSAprovider.PersistKeyInCsp = false;
RSAprovider.FromXmlString(RSAXml);
rijAlg.IV = RSAprovider.Decrypt(this.read(client, new byte[512]), true); //This is where the error occurs on the second message
logger.Trace("Got AES IV:\n{0}", BitConverter.ToString(rijAlg.IV).Replace("-", ""));
}
CryptoStream cryptoStream = null;
try
{
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
cryptoStream = new CryptoStream(client.GetStream(), decryptor, CryptoStreamMode.Read);
int read = 0;
int error = 0;
while (read < readBuffer.Length)
{
int bytesRead = cryptoStream.Read(readBuffer, read, readBuffer.Length - read);
read += bytesRead;
if (bytesRead == 0 && read != error)
{
logger.Debug("Reached end of stream at {0}. Waiting for more data...", read);
error = read;
}
}
decryptor.Dispose();
return readBuffer;
}
finally
{
/*if (cryptoStream != null)
cryptoStream.Dispose();*/
// TODO: This needs to be disposed somehow but leave the NetworkStream open
}
}
}
My guess is that the CryptoStream tries to decrypt more data than is being read, and messes up the IV, but I don't know what I could change to fix this.
I'm using C# .Net 4.0. I generate the key and IV(initialization vector) using the rijindael class. I then write both of them to a file. The IV is always correct when I read the file, but the last byte of the key is always zero. I look at the key before writing to the file and it is fine, reading it back in the last byte is always zero.
I have tried setting the padding mode to the various choices and they don't make a difference.
using (Rijndael myRijndael = Rijndael.Create())
{
//Create keys
try
{
byte[] key;
byte[] iv;
key = new byte[32];
iv = new byte[16];
theKeys.Key = myRijndael.Key;
theKeys.IV = myRijndael.IV;
FileStream fs = File.Create("yyy.txt");
fs.Write(theKeys.Key, 0, theKeys.Key.Length);
fs.Flush();
fs.Close();
FileStream ts = File.Open("yyy.txt", FileMode.Append);
ts.Write(theKeys.IV, 0, theKeys.IV.Length);
ts.Flush();
ts.Close();
FileStream ms = File.Open("yyy.txt", FileMode.Open);
ms.Read(key, 0, 31);
ms.Seek(32, 0);
ms.Read(iv, 0, 16);
ms.Flush();
ms.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
// Save key and IV
using (var rijndael = new RijndaelManaged())
using (var writer = new BinaryWriter(File.Create("yyy.dat")))
{
writer.Write(rijndael.Key, 0, 32);
writer.Write(rijndael.IV, 0, 16);
}
// Restore key and IV
using (var rijndael = new RijndaelManaged())
using (var reader = new BinaryReader(File.OpenRead("yyy.dat")))
{
rijndael.Key = reader.ReadBytes(32);
rijndael.IV = reader.ReadBytes(16);
}
The problem is that you are only asking to read in 31 bytes:
ms.Read(key, 0, 31);
This should be changed to:
ms.Read(key, 0, 32);
Also, this can be much more efficient (leaving out use of theKeys in this example and just using the local vars):
using (Rijndael myRijndael = Rijndael.Create())
{
//Create keys
try
{
byte[] key;
byte[] iv;
key = new byte[32];
iv = new byte[16];
key = myRijndael.Key;
iv = myRijndael.IV;
using (FileStream fs = File.Create("yyy.txt"))
{
fs.Write(key, 0, key.Length);
fs.Write(iv, 0, iv.Length);
}
using (FileStream ms = File.Open("yyy.txt", FileMode.Open))
{
key = new byte[32];
iv = new byte[16];
ms.Read(key, 0, 32);
ms.Read(iv, 0, 16);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
I can encrypt image file. but can not decrypt that file.
while ((readLen = cryptStrm.Read(bs, 0, bs.Length)) > 0)
anyone can guess which part is wrong?
the code i programmed is the following.
when i read encrypted file, i can not read at all.
and the CryptoStream's property called length and position has "NotSupportedException",
when i see cryptstream's property using vss.
I waste many hours to solve this problem.....
Pls help me.....
Encrypt
[Bitmap >> encrypted fie]
Decrypt
[encrypted fie >> file]
Encrypt
public static void EncryptFile(
Bitmap bmp, string destFile, byte[] key, byte[] iv)
{
System.Security.Cryptography.RijndaelManaged rijndael =
new System.Security.Cryptography.RijndaelManaged();
rijndael.Key = key;
rijndael.IV = iv;
System.IO.FileStream outFs = new System.IO.FileStream(
destFile, System.IO.FileMode.Create, System.IO.FileAccess.Write);
System.Security.Cryptography.ICryptoTransform encryptor =
rijndael.CreateEncryptor();
System.Security.Cryptography.CryptoStream cryptStrm =
new System.Security.Cryptography.CryptoStream(
outFs, encryptor,
System.Security.Cryptography.CryptoStreamMode.Write);
MemoryStream ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Jpeg);
byte[] bs = new byte[1024];
int readLen;
while ((readLen = ms.Read(bs, 0, bs.Length)) > 0)
{
cryptStrm.Write(bs, 0, readLen);
}
ms.Close();
cryptStrm.Close();
encryptor.Dispose();
outFs.Close();
}
Decrypt
public static void DecryptFile(
string sourceFile, string destFile, byte[] key, byte[] iv)
{
System.Security.Cryptography.RijndaelManaged rijndael =
new System.Security.Cryptography.RijndaelManaged();
rijndael.Key = key;
rijndael.IV = iv;
System.IO.FileStream inFs = new System.IO.FileStream(
sourceFile, System.IO.FileMode.Open, System.IO.FileAccess.Read);
System.Security.Cryptography.ICryptoTransform decryptor =
rijndael.CreateDecryptor();
System.Security.Cryptography.CryptoStream cryptStrm =
new System.Security.Cryptography.CryptoStream(
inFs, decryptor,
System.Security.Cryptography.CryptoStreamMode.Read);
System.IO.FileStream outFs = new System.IO.FileStream(
destFile, System.IO.FileMode.Create, System.IO.FileAccess.Write);
byte[] bs = new byte[1024];
int readLen;
while ((readLen = cryptStrm.Read(bs, 0, bs.Length)) > 0)
{
outFs.Write(bs, 0, readLen);
}
outFs.Close();
cryptStrm.Close();
decryptor.Dispose();
inFs.Close();
}
Try setting the Mode and Padding members of rijndael.
The default padding mode caused problems when I did a similar implementation.
// It is reasonable to set encryption mode to Cipher Block Chaining
// (CBC). Use default options for other symmetric key parameters.
rijndael.Mode = CipherMode.CBC;
rijndael.Padding = PaddingMode.None;