The input data is not a complete block - c#

Scenario: One symmetric key, each user has his own IV, the documents are stored in a NVARCHAR(MAX) field. When I try to to decrypt the file, I get:
The input data is not a complete block.
// Create symmetric key
public static byte[] CreateKey()
{
AesCryptoServiceProvider aesCrypto = (AesCryptoServiceProvider)AesCryptoServiceProvider.Create();
byte[] key = aesCrypto.Key;
return key;
}
//Get key (stored in a database)
public static Byte[] GetAppKey()
{
return db.Encryptors.Where(x => x.EncryptorID == 1).Single().EncryptionKey.ToArray();
}
// Get application IV (stored in database)
public static Byte[] GetAppIV()
{
return db.Encryptors.Where(x => x.EncryptorID == 1).Single().IV.ToArray();
}
// Encrypt document (this will be stored in a VARBINARY(MAX) field
public static byte[] EncryptBinaryToBytes(Binary document, byte[] iv)
{
byte[] key = GetAppKey();
byte[] encrypted;
using (AesCryptoServiceProvider aesCsp = new AesCryptoServiceProvider())
{
aesCsp.Key = key;
aesCsp.IV = iv;
ICryptoTransform encryptor = aesCsp.CreateEncryptor(aesCsp.Key, aesCsp.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(document);
}
encrypted = msEncrypt.ToArray();
}
}
}
// return the encrypted document
return encrypted;
}
// Decrypt document
public static byte[] DecryptBytesToBytes(byte[] document, byte[] iv)
{
byte[] key = GetAppKey();
using (AesCryptoServiceProvider aesCsp = new AesCryptoServiceProvider())
{
aesCsp.Key = key;
aesCsp.IV = iv;
ICryptoTransform decryptor = aesCsp.CreateDecryptor(aesCsp.Key, aesCsp.IV);
using (MemoryStream msDecrypt = new MemoryStream())
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write))
{
using (StreamWriter swDecrypt = new StreamWriter(csDecrypt))
{
swDecrypt.Write(document);
}
byte[] decrypted = msDecrypt.ToArray();
// return the unencrypted document
return decrypted;
}
}
}
}
Thanks in advance.
To store the document
byte[] fileByte = fluUploadFile.FileBytes;
Binary document = new Binary(fileByte);
byte[] appIv = AES.GetAppIV();
byte[] encryptedDocument = AES.EncryptBinaryToBytes(document, appIv);
byte[] decryptedDocument = AES.DecryptBytesToBytes(encryptedDocument, appIv);
Document d = new Document()
{
OriginalName = originalName,
DocSize = fileSize,
BinaryDocument = encryptedDocument,
UploadedName = uploadedFileName,
MimeType = MIMEType,
DocExtension = extension
};
db.Documents.InsertOnSubmit(d);
db.SubmitChanges();

It's really important that you change the data type of the database field to VARBINARY(MAX), that way you avoid issues with character encodings and byte combinations that cannot be interpreted as legal characters.
Also, I think the problem is that you are not closing the streams before calling ToArray() method on the MemoryStream in both encrypt and decrypt routines. It's very important to call Close() in the CryptoStream so that FlushFinalBlock() is called and the encryption process writes the final block to the stream.
Try moving the call to MemoryStream.ToArray() to the outer using block, that is, outside the using block of CryptoStream, so that Dispose() is called on the CryptoStream and call MemoryStream.Close() before that.
Another problem with your code is that you are wrapping the CryptoStream with a StreamWriter, which writes the text representation of the object you pass into the Write method. You should instead write directly to the CryptoStream to avoid any byte to string conversions.

Related

Parsing Json failure

I have problem with reading from encrypted files. have 2 sources of files, one is Rapsberry PI (Java), the second is desktop appliaction (.Net 4.6.1).
When I'm creating a encrypted file on my device and then want to read it in my desktop app, there is no problem with decrypting and encoding to string.
In the same app I create the same file, adding next element to list in the file on each 5s. When I read the file in my app, I got Unexpected end when reading json. path error.
I have checked models and they are both the same and valid.
For encryption/decryption I'm using AES algorithm.
There is my code from my desktop app:
Writing data:
Aes myAes = Aes.Create();
myAes.Key = Encoding.ASCII.GetBytes("abcde");
byte[] roundtrip = EncryptStringToBytes_Aes(output, myAes.Key, myAes.IV);
DirectoryInfo info = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
string pathSave =info + "\\test.plkx";
using (FileStream sourceStream = new FileStream (pathSave , FileMode.Append))
{
sourceStream.Write(roundtrip, 0, roundtrip.Length);
};
The method byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
aesAlg.Mode = CipherMode.ECB;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
There is my reader:
byte[] data = null;
data = new byte[fileStream.Length];
fileStream.Position = 0;
fileStream.Read(data, 0, (int)fileStream.Length);
Aes myAes = Aes.Create();
myAes.Key = Encoding.ASCII.GetBytes("abcde");
byte[] roundtrip = DecryptStringFromBytes_Aes(data, myAes.Key, myAes.IV);
return new MemoryStream(roundtrip);
And byte[] DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV) method:
byte[] plaintext = null;
using (Aes aesAlg = Aes.Create())
{
aesAlg.Mode = CipherMode.ECB;
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msDecrypt = new MemoryStream())
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write))
{
csDecrypt.Write(cipherText, 0, cipherText.Length);
}
plaintext = msDecrypt.ToArray();
var ads = ASCIIEncoding.ASCII.GetString(plaintext);
//There I got exception
var ab = DeserializeStream(new MemoryStream(plaintext));
}
}
return plaintext;
DeserializeStream method:
public RecorderValueTest DeserializeStream(MemoryStream stream)
{
RecorderValueTest r = new RecorderValueTest();
using (BsonDataReader reader = new BsonDataReader(stream))
{
JsonSerializer serializer = new JsonSerializer();
r = serializer.Deserialize<RecorderValueTest>(reader);
}
return r;
}
edit
I have tried this:
xxx = new xxx
{
data = listRecord,
};
string output = JsonConvert.SerializeObject(plkx);
      
try
{
using (BsonDataReader reader = new BsonDataReader(new MemoryStream(Encoding.UTF8.GetBytes(output))))
{
JsonSerializer serializer = new JsonSerializer();
var r = serializer.Deserialize<xxx>(reader);
}
} catch (Exception exc)
{ }
and still get the same error while deserialization. JsonConvert.DeserializeObject<xxx>(plkx); also didn't work.

C# CryptographicException length of the data to decrypt is invalid

I have this code which is meant to decrypt a file, but if I run it, it throws a CryptographicException (length of the data to decrypt is invalid) at the end of the using statement using (CryptoStream ...) { ... }
public static void DecryptFile(string path, string key, string saltkey, string ivkey)
{
try
{
byte[] cipherTextBytes;
using (StreamReader reader = new StreamReader(path)) cipherTextBytes = Encoding.UTF8.GetBytes(reader.ReadToEnd());
byte[] keyBytes = new Rfc2898DeriveBytes(key, Encoding.ASCII.GetBytes(saltkey)).GetBytes(256 / 8);
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.None };
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.ASCII.GetBytes(ivkey));
byte[] plainTextBytes;
using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
plainTextBytes = new byte[Encoding.UTF8.GetByteCount((new StreamReader(cryptoStream)).ReadToEnd())];
cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
//plainTextBytes = memoryStream.ToArray();
cryptoStream.FlushFinalBlock();
}
}
string result = Encoding.ASCII.GetString(plainTextBytes, 0, plainTextBytes.Length).TrimEnd("\0".ToCharArray());
using (FileStream writer = new FileStream(path, FileMode.Create)) writer.Write(Encoding.ASCII.GetBytes(result), 0, Encoding.ASCII.GetBytes(result).Length);
MessageBox.Show("Decrypt succesfull");
}
catch (Exception ex)
{
MessageBox.Show("An error while decrypting the file:\n\n" + ex, "Error");
}
}
}
Does anybody know why this is or how I can fix it? (I don't know if it comes from my encrypting method, but I have another program which uses the exact same thing to encrypt strings and that one does work.)
My encrypting method:
public static void EncryptFile(string path, string key, string saltkey, string ivkey)
{
try
{
byte[] TextBytes;
using (StreamReader reader = new StreamReader(path)) TextBytes = Encoding.UTF8.GetBytes(reader.ReadToEnd());
byte[] KeyBytes = new Rfc2898DeriveBytes(key, Encoding.ASCII.GetBytes(saltkey)).GetBytes(256 / 8);
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros };
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(KeyBytes, Encoding.ASCII.GetBytes(ivkey));
byte[] CipherTextBytes;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(TextBytes, 0, TextBytes.Length);
cs.FlushFinalBlock();
CipherTextBytes = ms.ToArray();
}
}
using (FileStream writer = new FileStream(path, FileMode.Create)) writer.Write(CipherTextBytes, 0, CipherTextBytes.Length);
MessageBox.Show("Encrypt succesfull");
}
catch (Exception ex)
{
MessageBox.Show("An error while encrypting the file:\n\n" + ex, "Error");
}
}
There are a few issues with your code:
You use a padding mode of Zeroes in Encrypt and None in Decrypt. These need to match
You load the bytes from your file using Encoding.UTF8, you need to read the raw bytes, you can do this by using the following instead:
byte[] cipherTextBytes = File.ReadAllBytes(path);
You call cryptoStream.FlushFinalBlock(); when only using a single iteration of a stream. You don't need this call in Decrypt if you are only doing a single block iteration.
You read the original text from your file in UTF8 and then write it back as ASCII. You should either change the result assignment in decrypt to use UTF8 or (preferably) change both to use raw bytes.
You use Create to interact with the files when you are overwriting in-place. If you know the file already exists (as you are replacing it) you should use truncate or better yet just call File.WriteAllBytes.
Your decrypt is all kinds of messed up. It looks like you're tying yourself into knots over byte retrieval. You should just use the raw bytes out of the CryptoStream and not try using UTF8
Here's a revised set of methods for you:
public static void DecryptFile(string path, string key, string saltkey, string ivkey)
{
byte[] cipherTextBytes = File.ReadAllBytes(path);
byte[] keyBytes = new Rfc2898DeriveBytes(key, Encoding.ASCII.GetBytes(saltkey)).GetBytes(256 / 8);
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CFB, Padding = PaddingMode.PKCS7 };
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.ASCII.GetBytes(ivkey));
byte[] plainTextBytes;
const int chunkSize = 64;
using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes))
using (MemoryStream dataOut = new MemoryStream())
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
using (var decryptedData = new BinaryReader(cryptoStream))
{
byte[] buffer = new byte[chunkSize];
int count;
while ((count = decryptedData.Read(buffer, 0, buffer.Length)) != 0)
dataOut.Write(buffer, 0, count);
plainTextBytes = dataOut.ToArray();
}
File.WriteAllBytes(path, plainTextBytes);
}
and:
public static void EncryptFile(string path, string key, string saltkey, string ivkey)
{
byte[] TextBytes = File.ReadAllBytes(path);
byte[] KeyBytes = new Rfc2898DeriveBytes(key, Encoding.ASCII.GetBytes(saltkey)).GetBytes(256 / 8);
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CFB, Padding = PaddingMode.PKCS7 };
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(KeyBytes, Encoding.ASCII.GetBytes(ivkey));
byte[] CipherTextBytes;
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(TextBytes, 0, TextBytes.Length);
cs.FlushFinalBlock();
CipherTextBytes = ms.ToArray();
}
File.WriteAllBytes(path, CipherTextBytes);
}
Most likely your problem comes from cipherTextBytes = Encoding.UTF8.GetBytes(reader.ReadToEnd());
You can't use UTF8 to encode arbitrary binary data, you will likely need to fix both your encrypting end decrypting end. You either must use cipherTextBytes = File.ReadAllBytes(path) or if you are forced to use strings you must first encode the bytes to a valid string using Convert.ToBase64String()
In my case it happened because I was decrypting a value which was never encrypted.
I had my values saved in the database without encryption. But when I introduced encryption and decryption routine in my code and executed my program first time, it was actually trying to decrypt a value which was never encrypted, hence the problem.
Simply clearing the existing values from the database for the initial run solved the problem. If you don't want to lose data even during the first run then you should write a separate routine to encrypt the existing values.

How is encryption done without encoding the string to byte[]?

I've been trying to understand encryption/decryption code of TripleDES for some days. And I have seen many codes in the google, and the code shown below is one of them.
static void Main(string[] args)
{
string original = "Here is some data to encrypt!";
TripleDESCryptoServiceProvider myTripleDES = new TripleDESCryptoServiceProvider();
byte[] encrypted = EncryptStringToBytes(original, myTripleDES.Key, myTripleDES.IV);
string encrypt = Convert.ToBase64String(encrypted);
string roundtrip = DecryptStringFromBytes(encrypted, myTripleDES.Key, myTripleDES.IV);
Console.WriteLine("encryted: {0}", encrypt);
Console.WriteLine("Round Trip: {0}", roundtrip);
Console.ReadLine();
}
static byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
byte[] encrypted;
using (TripleDESCryptoServiceProvider tdsAlg = new TripleDESCryptoServiceProvider())
{
tdsAlg.Key = Key;
tdsAlg.IV = IV;
ICryptoTransform encryptor = tdsAlg.CreateEncryptor(tdsAlg.Key, tdsAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return encrypted;
}
static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
string plaintext = null;
using (TripleDESCryptoServiceProvider tdsAlg = new TripleDESCryptoServiceProvider())
{
tdsAlg.Key = Key;
tdsAlg.IV = IV;
ICryptoTransform decryptor = tdsAlg.CreateDecryptor(tdsAlg.Key, tdsAlg.IV);
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
There is no error in the code. I works fine. But strangely I noticed that the plainText is never been encoded. There is no line like Encoding.Unicode.GetBytes(plainText); or Encoding.UTF8.GetBytes(plainText); or similar like that. So, my question is , how does (in the code) the plainText which is a string gets converted to the encrypted byte? Is there any work done inside the streams? If thats so then where and how? As far as I understood there is no such line in between the streams that converts the string to byte. So , How does the overall code is working without this basic transformation?
Update:
Is this code really a valid code?
You are sending the plaintext to the encryption stream in the line swEncrypt.Write(plaintext). This does the byte conversion.
The StreamWriter is doing the encoding. The constructor being used specifies UTF-8 encoding:
This constructor creates a StreamWriter with UTF-8 encoding without a
Byte-Order Mark (BOM)

length of data to decrypt is invalid with rijndael cryptography

the other links are not being useful to me.
i am encrypting string before saving in mysql database.that is working fine.but when i want to retrieve, its giving me length of data to encrypt is invalid error.
before my encryption requirement, i was using datatype of varchar size 500.now im using varbinary of size 800.can any1 advise me on the size too?
encryption method:
public static byte[] encryptStringToBytes(string plainText)
{
byte[] encrypted;
//create an Rijndael object
using (Rijndael rijAlg = Rijndael.Create())
{
//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 (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return encrypted;
}
decryption method:
public static string decryptStringFromBytes(byte[] cipherText)
{
string plaintext = null;
//create an Rijndael object
using (Rijndael rijAlg = Rijndael.Create())
{
//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(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
//read the decrypted bytes from the decrypting stream and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
retrieving from resultset
using (Rijndael myRijndael = Rijndael.Create())
{
temp5 = EncryptDecrypt.decryptStringFromBytes((byte[])reader.GetValue(reader.GetOrdinal("Body")));
}
You are not controlling key and IV in any way. This is kind of a problem... :) It results in your encryption being a random scrambling of the data because key and IV are randomly initialized by the framework.
Use the same key and IV for decryption as you are using them for encryption. Why do you think the database has to do with the problem? It hasn't and there is not evidence for that.

Decrypted data with usage of TripleDESCryptoServiceProvider has additonal characters

I am facing with problem when decrypting data with usage of TripleDESCryptoServiceProvider. The problem is that decrypted value contains beside of original value some additional, strange characters at the end
Per instance if I provide "rastko" to be encrypted, I will get later with decryption something like this "rastko⥊㮶". For other values it could be different number of 'dummy' characters or in some cases I will get exact value.
Then, I saw that for all encrypted data byte array size is divisible by 8. It looks like any provided data is rounded on value that is divisible by 8. Only in case when original encoded value is divisible by 8, decryption will retrieve appropriate value.
Here are methods that I am using :
public static byte[] EncryptPassword(string password, out byte[] cryptoKey, out byte[] cryptoIV)
{
try
{
UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
byte[] unicodePassword = unicodeEncoding.GetBytes(password);
byte[] encryptedPassword;
using (TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider())
{
tripleDes.Key = GetCryptoKey();
tripleDes.Mode = CipherMode.CBC;
tripleDes.Padding = PaddingMode.PKCS7;
cryptoKey = tripleDes.Key;
cryptoIV = tripleDes.IV;
using (MemoryStream memoryStream = new MemoryStream())
{
ICryptoTransform cryptoTransform = tripleDes.CreateEncryptor();
using (
CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
{
cryptoStream.Write(unicodePassword, 0, unicodePassword.Length);
////cryptoStream.FlushFinalBlock();
}
encryptedPassword = memoryStream.ToArray();
}
}
return encryptedPassword;
}
catch (Exception ex)
{
throw new Exception("Password encryption failed !", ex);
}
}
public static string DecryptPassword(byte[] encryptedPassword, byte[] cryptoKey, byte[] cryptoIV)
{
try
{
UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
string readablePassword;
using (TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider())
{
tripleDes.Key = cryptoKey;
tripleDes.IV = cryptoIV;
tripleDes.Mode = CipherMode.CBC;
tripleDes.Padding = PaddingMode.PKCS7;
// Create a new MemoryStream using the passed
// array of encrypted data.
using (MemoryStream memoryStream = new MemoryStream(encryptedPassword))
{
// Create crypto transform that defines the basic operations of cryptographic transformations.
ICryptoTransform cryptoTransform = tripleDes.CreateDecryptor();
// Create a CryptoStream using the MemoryStream and the passed key and initialization vector (IV).
using (CryptoStream decryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
{
decryptoStream.Write(encryptedPassword, 0, encryptedPassword.Length);
///decryptoStream.FlushFinalBlock();
}
byte[] decryptedPassword = memoryStream.ToArray();
//Convert the buffer into a string and return it.
readablePassword = unicodeEncoding.GetString(decryptedPassword, 0, decryptedPassword.Length);
}
}
return readablePassword;
}
catch (Exception ex)
{
throw new Exception("Password decryption failed !", ex);
}
}
private static byte[] GetCryptoKey()
{
UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
string plainKey = "rastkoisajev2310982josipasenera153";
byte[] encodedKey = unicodeEncoding.GetBytes(plainKey);
// Prepares 192 bit key
byte[] preparedKey = new byte[24];
Array.Copy(encodedKey, preparedKey, 24);
return preparedKey;
}
Here is sample test invocation :
private static void CryptoTest()
{
string password = "rastko";
byte[] cryptoKey;
byte[] cryptoIV;
byte[] encryptedPassword = Crypto.EncryptPassword(password, out cryptoKey, out cryptoIV);
string decryptedPAssword = Crypto.DecryptPassword(encryptedPassword, cryptoKey, cryptoIV);
}
I have not good experience with security. What I see is that IV vector is 8byte size and as I found it is related to BlockSize, that is 8times greater then IV size. TripleDESCryptoServiceProvider for IV vector is using 8byte value. I can not change this.
Could you please tell me what I have to do or did I wrote something wrongly ?
DES is a 64 bit block cypher. Any text that does not divide cleanly into 64 bit (=8 byte) blocks needs to be padded to make up a whole number of blocks. You need to set padding for encryption and decryption. If you have control of both ends then use PKCS#5 padding to encrypt and decrypt. If you only have control over the decryption end, then ask the encrypting end what padding they are using and expect that.
Note that encrypting a password is normally not the way to go. Use PBKDF2 instead. Don't confuse passwords and keys!
Try to make sure that your CryptoStreams get closed or flushed:
http://msdn.microsoft.com/en-us/library/system.security.cryptography.cryptostream.flushfinalblock.aspx
If you don't then the padding/unpadding will likely not be performed, and you get trash instead.
After detail investigation I have found the solution for my problem.
I have changed a little bit decryption logic.
Instead of this part in DecryptPassword method :
// Create a CryptoStream using the MemoryStream and the passed key and initialization vector (IV).
using (CryptoStream decryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
{
decryptoStream.Write(encryptedPassword, 0, encryptedPassword.Length);
///decryptoStream.FlushFinalBlock();
}
byte[] decryptedPassword = memoryStream.ToArray();
//Convert the buffer into a string and return it.
readablePassword = unicodeEncoding.GetString(decryptedPassword, 0, decryptedPassword.Length);
}
I am now using the Read logic from CryptoStream and then I am just removing nullable characters. It is like this now :
// Create a CryptoStream using the MemoryStream and the passed key and initialization vector (IV).
using (CryptoStream decryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Read))
{
// Create buffer to hold the decrypted data.
byte[] fromEncrypt = new byte[encryptedPassword.Length];
decryptoStream.Read(fromEncrypt, 0, fromEncrypt.Length);
//Convert the buffer into a string and return it.
readablePassword = unicodeEncoding.GetString(fromEncrypt);
readablePassword = readablePassword.Replace("\0", string.Empty);
}
This works perfectly for me ! Thank you all for your time.

Categories