Decryption is not working..wrong text

G

Guest

Hi everybody,

I am not sure where to put this in this forum. So, I posted this at
several topics. I created a class library that has two public methods
Encrypt() and Decrypt(). I reference this dll to a window application. I used
DESCryptoServiceProvider Algorithm to encrypt and decrypt then with same Key
and IV. But unable to decrypt it back to original text. This project I plan
to use all algorithm and Hash. This is Phase One. There is no problem
ingenerating the Key and IV and at both encrypt and decrypt they are the
same. Can anyone spot the mistake and know how to correct this? Thanks.

Code:
//Generate a Key
private static void GenerateDESKey(DESCryptoServiceProvider
desProv,int keySize,bool maxKeySize)
{
if (Key == null)
{
if (keySize != 0)
desProv.KeySize = keySize;
else
{
KeySizes[] keySizeSets = desProv.LegalKeySizes;
int len = keySizeSets.Length;

for (int x = 0; x < len; x++)
{
if (maxKeySize)
keySize = keySizeSets[0].MaxSize;
else
keySize = keySizeSets[0].MinSize;
}
}
desProv.KeySize = keySize;
desProv.GenerateKey();
Key = desProv.Key;
}
}

//Generate a IV
private static void GenerateDESIV(DESCryptoServiceProvider desProv)
{
if (IV == null)
{
desProv.GenerateIV();
IV = desProv.IV;
}
}

//Encrypting String Data passed as parameter and returns it
public string Encrypt(string strData,int keySize, bool bMaxSize)
{
string strEncrypt = string.Empty;
try
{
//Variable Telling if Crypto or Managed object is selected
MemoryStream memStream = new MemoryStream();

CryptoStream cryptStream;
UnicodeEncoding byteConvert = new UnicodeEncoding();
byte[] byteData = byteConvert.GetBytes(strData);

byte[] encryptedData = { };


if (this.CRYPTOCLASS == Algorithm.DES.ToString())
{
this.CreateDESCrypto();
if (des != null)
{
//Generate Cryptographic Key and saved it
GenerateDESKey(des, keySize, bMaxSize);
//Generate Cryptographic IV and saved it
GenerateDESIV(des);

transform = des.CreateEncryptor((byte[])Key.Clone(),
(byte[])IV.Clone());
}
}
. . . .
//Use the created algorithm object to encrypt data
cryptStream = new CryptoStream(memStream, transform,
CryptoStreamMode.Write);

cryptStream.Write(byteData, 0, byteData.Length);
cryptStream.FlushFinalBlock();

encryptedData = memStream.ToArray();

memStream.Close();
cryptStream.Close();
transform.Dispose();

//Call to dispose data
this.DisposeActiveObjects();
//Convert encrypted bytes[] back to string
strEncrypt = Convert.ToBase64String(encryptedData);

}
catch (Exception ex)
{
this.WriteAppendLogFile(", Encrypt() " + ex.ToString());
}
return strEncrypt;
}

//Decrypting String Data passed as parameter and returns it
public string Decrypt(string strEncrypt)
{
string strData = string.Empty;
try
{
//Variable Telling if Crypto or Managed object is selected

//Check if Key and IV is still has data
if (Key == null || IV == null)
{
return "Cryptographic Key and IV cannot be null.";
}
MemoryStream memStream;
CryptoStream cryptStream;
byte[] encryptedData = Convert.FromBase64String(strEncrypt);
byte[] decryptedData = new Byte[encryptedData.Length];

if (this.CRYPTOCLASS == Algorithm.DES.ToString())
{
this.CreateDESCrypto();
transform = des.CreateDecryptor((byte[])
Key.Clone(),(byte[])IV.Clone());

}
........

//Use the created algorithm object to encrypt data
memStream = new MemoryStream(encryptedData);
cryptStream = new CryptoStream(memStream, transform,
CryptoStreamMode.Read);

cryptStream.Read(decryptedData, 0, decryptedData.Length);

memStream.Close();
cryptStream.Close();
transform.Dispose();

//Call to dispose data
this.DisposeActiveObjects();
//Convert encrypted bytes[] back to string
//strEncrypt = Convert.ToBase64String(decryptedData);
strData = Encoding.ASCII.GetString(decryptedData);
}
catch (Exception ex)
{
this.WriteAppendLogFile(", Decrypt() " + ex.ToString());
}
return strData;
}

den2005
 
J

Jon Skeet [C# MVP]

den 2005 said:
I am not sure where to put this in this forum. So, I posted this at
several topics. I created a class library that has two public methods
Encrypt() and Decrypt(). I reference this dll to a window application. I used
DESCryptoServiceProvider Algorithm to encrypt and decrypt then with same Key
and IV. But unable to decrypt it back to original text. This project I plan
to use all algorithm and Hash. This is Phase One. There is no problem
ingenerating the Key and IV and at both encrypt and decrypt they are the
same. Can anyone spot the mistake and know how to correct this? Thanks.

Well, you've provided quite a lot of code, but not enough for us to
just compile and run.

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.
 
R

rossum

Hi everybody,

I am not sure where to put this in this forum. So, I posted this at
several topics. I created a class library that has two public methods
Encrypt() and Decrypt(). I reference this dll to a window application. I used
DESCryptoServiceProvider Algorithm to encrypt and decrypt then with same Key
and IV. But unable to decrypt it back to original text. This project I plan
to use all algorithm and Hash. This is Phase One. There is no problem
ingenerating the Key and IV and at both encrypt and decrypt they are the
same. Can anyone spot the mistake and know how to correct this? Thanks.

Code:
 [snip]

1 Why are you using DES rather than AES? DES is now obsolete.
Triple-DES is acceptable if you have to link with an existing
application. Use AES for anything else.

2 Your application returns strData even if it finds an exception, this
is a potential security leak. Whenever an exception is thrown you
need to destroy all information for the current message, both
cyphertext and plaintext. Dispose as much as you can, set every
element of encryptedData[] and decryptedData[] to zero. Set strData
to string.Empty. Ideally you should wipe the previous contents of
strData first:

unsafe void OverwriteString(string text) {
const char overwriteChar = 'X';
fixed (char* cp = text) {
for (int i = 0; i < text.Length; ++i) {
cp = overwriteChar;
} // end for
} // end fixed
} // end OverwriteString()

3 Your code is very complex, to me at least it looks more complex then
it needs to be. For security stuff keeeping it simple with very few
options is better; if your users do not have to option to select
keySize then they cannot make the mistake of selecting one that is too
small - keySize = 1? Take out as much of the complexity as you can.

3 To find the problem simplify and see if the problem persists,
something like:

[pseudocode]
byte[] Key = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}
byte[] IV = {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}
string plaintext1 = "Hello World!"

byte[] cyphertext = Encrypt(plaintext1, Key, IV)

string plaintext2 = Decrypt(cyphertext, Key, IV).ToString()

if (plaintext != plaintext2) {
WriteLine("Failed")
} else {
WriteLine("OK")
}
[/pseudocode]

It will be much easier for you to see problems in the simpler code.
Once the simple code is working you can add back the required
complications one at a time, retesting after each new complication.

4 You are using Unicode and ASCII encodings at different places. It
might be worth checking that the mixed character codings are not
causing the problem rather than the encryption/decryption.


rossum
 
G

Guest

Thanks for the reply, Jon. I got idea reply from another post and reply of
rossum in this forum.

Thanks for long reply, rossum. Thanks for tip of cleaning all variable for
security reasons. AES? I would try using fixed key and init vector(IV).
I am new in cryptography, so don't know what is working. I would like to use
the best byte[] conversion to allow all possibilities of keys entered to be
encrypted including special keys and to be used to encrypt web configuration
sections (web.config).
What exactly Padding does? It adds remaining bits if encrypted data is only
40 and allowed is 64 bits, how about if encrypted data is over 64 bits what
happen to rest of encrypted data?

Dennis



--
MCP Year 2005, Philippines


rossum said:
Hi everybody,

I am not sure where to put this in this forum. So, I posted this at
several topics. I created a class library that has two public methods
Encrypt() and Decrypt(). I reference this dll to a window application. I used
DESCryptoServiceProvider Algorithm to encrypt and decrypt then with same Key
and IV. But unable to decrypt it back to original text. This project I plan
to use all algorithm and Hash. This is Phase One. There is no problem
ingenerating the Key and IV and at both encrypt and decrypt they are the
same. Can anyone spot the mistake and know how to correct this? Thanks.

Code:
 [snip]

1 Why are you using DES rather than AES? DES is now obsolete.
Triple-DES is acceptable if you have to link with an existing
application. Use AES for anything else.

2 Your application returns strData even if it finds an exception, this
is a potential security leak. Whenever an exception is thrown you
need to destroy all information for the current message, both
cyphertext and plaintext. Dispose as much as you can, set every
element of encryptedData[] and decryptedData[] to zero. Set strData
to string.Empty. Ideally you should wipe the previous contents of
strData first:

unsafe void OverwriteString(string text) {
const char overwriteChar = 'X';
fixed (char* cp = text) {
for (int i = 0; i < text.Length; ++i) {
cp = overwriteChar;
} // end for
} // end fixed
} // end OverwriteString()

3 Your code is very complex, to me at least it looks more complex then
it needs to be. For security stuff keeeping it simple with very few
options is better; if your users do not have to option to select
keySize then they cannot make the mistake of selecting one that is too
small - keySize = 1? Take out as much of the complexity as you can.

3 To find the problem simplify and see if the problem persists,
something like:

[pseudocode]
byte[] Key = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}
byte[] IV = {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}
string plaintext1 = "Hello World!"

byte[] cyphertext = Encrypt(plaintext1, Key, IV)

string plaintext2 = Decrypt(cyphertext, Key, IV).ToString()

if (plaintext != plaintext2) {
WriteLine("Failed")
} else {
WriteLine("OK")
}
[/pseudocode]

It will be much easier for you to see problems in the simpler code.
Once the simple code is working you can add back the required
complications one at a time, retesting after each new complication.

4 You are using Unicode and ASCII encodings at different places. It
might be worth checking that the mixed character codings are not
causing the problem rather than the encryption/decryption.


rossum
 
R

rossum

Thanks for the reply, Jon. I got idea reply from another post and reply of
rossum in this forum.

Thanks for long reply, rossum. Thanks for tip of cleaning all variable for
security reasons. AES? I would try using fixed key and init vector(IV).
I am new in cryptography, so don't know what is working. I would like to use
the best byte[] conversion to allow all possibilities of keys entered to be
encrypted including special keys and to be used to encrypt web configuration
sections (web.config).
What exactly Padding does? It adds remaining bits if encrypted data is only
40 and allowed is 64 bits, how about if encrypted data is over 64 bits what
happen to rest of encrypted data?

Dennis

If you want to learn about cryptography, the best place to start is
"Practical Cryptography" by Ferguson and Schneier.

For web resources, Wikipedia is very good and also the "Handbook of
Applied Cryptography" at www.cacr.math.uwaterloo.ca/hac. On usenet
sci.crypt can be useful for answers from experts, though discussion
can get a bit fierce at times.

There are many free cypher libraries around if you want to look at
other people's code, though most of them will be in C, C++ or Java
rather than C#.

As to your specific questions. Padding is used when the data size may
not be an exact multiple of the block size so the last block has to be
padded. See Wikipedia: Padding (cryptography).

For dealing with data more than a block size you need to look at mode
of operation - Wikipedia: Block cipher modes of operation. These are
the CBC, CTR and other mysterious letters you might see sometimes.
The formal definitions are in NIST at
http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf

The basic advice to beginners is not to try to do anything real (i.e.
on a commercial basis) yourself but to get in an expert. It is fine
to play for yourself but this is a field where tiny errors can have
big consequences so newbies need to stay from real work until they
have developed enough background.

rossum
 
G

Guest

Thanks for advise, rossum.

I have a Question, i am using rsacryptoserviceprovider to encrypt and
decrypt, I tried several approach, one approach produces error "Bad Data",
another tells me "Invalid length for a Base 64 Char Array", another says "The
data to be decrypted exceeds the maximum for this modulus of 128 bytes".

How exactly would be proper to convert string to bytes, encrypt it using rsa
algorithm, then convert the bytes data back to string for display, and then
used this string data as input to be converted back to bytes for decryption
and the resulting bytes data converted back to string (which should be same
as original text before encryption)? I will look at those links you
mentioned. Thanks.

Here are part of codes I used to do this:

Code:
public string Encrypt(string strData)
{
string strData = string.Empty;
try
{
. .. .
UnicodeEncoding byteConvert = new UnicodeEncoding();
byte[] byteData = byteConvert.GetBytes(strData);
//byte[] byteData = Encoding.Unicode.GetBytes(strData);

.......
encryptedData = rsa.Encrypt(byteData, false);
return Convert.ToBase64String(encryptedData);
. . . .
}
catch (Exception ex)
{
. . . .
}
return strData;
}

public string Decrypt(string strEncrypt)
{
.....
UnicodeEncoding byteConvert = new UnicodeEncoding();
byte[] encryptedData = byteConvert.GetBytes(strEncrypt);
//byte[] byteData = Encoding.Unicode.GetBytes(strEncrypt);

.......
decryptedData = rsa.Decrypt(encryptedData, false);
return Convert.ToBase64String(decryptedData);
......
}

den2005

--
MCP Year 2005, Philippines


rossum said:
Thanks for the reply, Jon. I got idea reply from another post and reply of
rossum in this forum.

Thanks for long reply, rossum. Thanks for tip of cleaning all variable for
security reasons. AES? I would try using fixed key and init vector(IV).
I am new in cryptography, so don't know what is working. I would like to use
the best byte[] conversion to allow all possibilities of keys entered to be
encrypted including special keys and to be used to encrypt web configuration
sections (web.config).
What exactly Padding does? It adds remaining bits if encrypted data is only
40 and allowed is 64 bits, how about if encrypted data is over 64 bits what
happen to rest of encrypted data?

Dennis

If you want to learn about cryptography, the best place to start is
"Practical Cryptography" by Ferguson and Schneier.

For web resources, Wikipedia is very good and also the "Handbook of
Applied Cryptography" at www.cacr.math.uwaterloo.ca/hac. On usenet
sci.crypt can be useful for answers from experts, though discussion
can get a bit fierce at times.

There are many free cypher libraries around if you want to look at
other people's code, though most of them will be in C, C++ or Java
rather than C#.

As to your specific questions. Padding is used when the data size may
not be an exact multiple of the block size so the last block has to be
padded. See Wikipedia: Padding (cryptography).

For dealing with data more than a block size you need to look at mode
of operation - Wikipedia: Block cipher modes of operation. These are
the CBC, CTR and other mysterious letters you might see sometimes.
The formal definitions are in NIST at
http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf

The basic advice to beginners is not to try to do anything real (i.e.
on a commercial basis) yourself but to get in an expert. It is fine
to play for yourself but this is a field where tiny errors can have
big consequences so newbies need to stay from real work until they
have developed enough background.

rossum
 
R

rossum

Thanks for advise, rossum.

I have a Question, i am using rsacryptoserviceprovider to encrypt and
decrypt, I tried several approach, one approach produces error "Bad Data",
another tells me "Invalid length for a Base 64 Char Array", another says "The
data to be decrypted exceeds the maximum for this modulus of 128 bytes".

How exactly would be proper to convert string to bytes, encrypt it using rsa
algorithm, then convert the bytes data back to string for display, and then
used this string data as input to be converted back to bytes for decryption
and the resulting bytes data converted back to string (which should be same
as original text before encryption)? I will look at those links you
mentioned. Thanks.

Here are part of codes I used to do this:

Code:
public string Encrypt(string strData)
{
string strData = string.Empty;[/QUOTE]
strData is your original parameter.  Perhaps you meant to declare
encryptedData here.
[QUOTE]
try
{
. .. .
UnicodeEncoding byteConvert = new UnicodeEncoding();
byte[] byteData = byteConvert.GetBytes(strData);
//byte[] byteData = Encoding.Unicode.GetBytes(strData);

.......
encryptedData = rsa.Encrypt(byteData, false);[/QUOTE]
rsa is undeclared - you need to post enough code that I can compile
it.[QUOTE]
return Convert.ToBase64String(encryptedData);
. . . .
}
catch (Exception ex)
{
. . . .
}
return strData;[/QUOTE]
I suspect that you want to return encryptedData here, not merely
returning the original input parameter.
[QUOTE]
}

public string Decrypt(string strEncrypt)
{
.....
UnicodeEncoding byteConvert = new UnicodeEncoding();
byte[] encryptedData = byteConvert.GetBytes(strEncrypt);[/QUOTE]
encryptedData is undeclared here, I suspect you meant decryptedData
which you use below.
[QUOTE]
//byte[] byteData = Encoding.Unicode.GetBytes(strEncrypt);

.......
decryptedData = rsa.Decrypt(encryptedData, false);[/QUOTE]
decryptedData is undeclared here.[QUOTE]
return Convert.ToBase64String(decryptedData);[/QUOTE]
Why are you returning a Base-64 string here?  The original data was a
string, not a Base-64 string.[QUOTE]
......
}

den2005

When posting code cut and paste the code from your code editor, do not
attempt to retype it.

Post enough code to compile immediately without any changes.

Post the minimum of code needed to show the problem. In this case
take out all the try/catch parts, and remove the various conversions,
work everything as byte arrays. It is easy enough to write a simple
functions to test two arrays for equality.

rossum
 
G

Guest

Hi rossum,

I think I solved using rsacryptoserviceprovider, right now testing
rng...it seems similar to random class. Is there?

Thanks for reply..

Dennis
--
MCP Year 2005, Philippines


rossum said:
Thanks for advise, rossum.

I have a Question, i am using rsacryptoserviceprovider to encrypt and
decrypt, I tried several approach, one approach produces error "Bad Data",
another tells me "Invalid length for a Base 64 Char Array", another says "The
data to be decrypted exceeds the maximum for this modulus of 128 bytes".

How exactly would be proper to convert string to bytes, encrypt it using rsa
algorithm, then convert the bytes data back to string for display, and then
used this string data as input to be converted back to bytes for decryption
and the resulting bytes data converted back to string (which should be same
as original text before encryption)? I will look at those links you
mentioned. Thanks.

Here are part of codes I used to do this:

Code:
public string Encrypt(string strData)
{
string strData = string.Empty;[/QUOTE]
strData is your original parameter.  Perhaps you meant to declare
encryptedData here.
[QUOTE]
try
{
. .. .
UnicodeEncoding byteConvert = new UnicodeEncoding();
byte[] byteData = byteConvert.GetBytes(strData);
//byte[] byteData = Encoding.Unicode.GetBytes(strData);

.......
encryptedData = rsa.Encrypt(byteData, false);[/QUOTE]
rsa is undeclared - you need to post enough code that I can compile
it.[QUOTE]
return Convert.ToBase64String(encryptedData);
. . . .
}
catch (Exception ex)
{
. . . .
}
return strData;[/QUOTE]
I suspect that you want to return encryptedData here, not merely
returning the original input parameter.
[QUOTE]
}

public string Decrypt(string strEncrypt)
{
.....
UnicodeEncoding byteConvert = new UnicodeEncoding();
byte[] encryptedData = byteConvert.GetBytes(strEncrypt);[/QUOTE]
encryptedData is undeclared here, I suspect you meant decryptedData
which you use below.
[QUOTE]
//byte[] byteData = Encoding.Unicode.GetBytes(strEncrypt);

.......
decryptedData = rsa.Decrypt(encryptedData, false);[/QUOTE]
decryptedData is undeclared here.[QUOTE]
return Convert.ToBase64String(decryptedData);[/QUOTE]
Why are you returning a Base-64 string here?  The original data was a
string, not a Base-64 string.[QUOTE]
......
}

den2005

When posting code cut and paste the code from your code editor, do not
attempt to retype it.

Post enough code to compile immediately without any changes.

Post the minimum of code needed to show the problem. In this case
take out all the try/catch parts, and remove the various conversions,
work everything as byte arrays. It is easy enough to write a simple
functions to test two arrays for equality.

rossum
 
G

Guest

Sorry for that..I try next time to post more complete codes without exposing
unnecessary connections...Right now, using cryptography on web.config. Thanks
again.

Dennis

--
MCP Year 2005, Philippines


rossum said:
Thanks for advise, rossum.

I have a Question, i am using rsacryptoserviceprovider to encrypt and
decrypt, I tried several approach, one approach produces error "Bad Data",
another tells me "Invalid length for a Base 64 Char Array", another says "The
data to be decrypted exceeds the maximum for this modulus of 128 bytes".

How exactly would be proper to convert string to bytes, encrypt it using rsa
algorithm, then convert the bytes data back to string for display, and then
used this string data as input to be converted back to bytes for decryption
and the resulting bytes data converted back to string (which should be same
as original text before encryption)? I will look at those links you
mentioned. Thanks.

Here are part of codes I used to do this:

Code:
public string Encrypt(string strData)
{
string strData = string.Empty;[/QUOTE]
strData is your original parameter.  Perhaps you meant to declare
encryptedData here.
[QUOTE]
try
{
. .. .
UnicodeEncoding byteConvert = new UnicodeEncoding();
byte[] byteData = byteConvert.GetBytes(strData);
//byte[] byteData = Encoding.Unicode.GetBytes(strData);

.......
encryptedData = rsa.Encrypt(byteData, false);[/QUOTE]
rsa is undeclared - you need to post enough code that I can compile
it.[QUOTE]
return Convert.ToBase64String(encryptedData);
. . . .
}
catch (Exception ex)
{
. . . .
}
return strData;[/QUOTE]
I suspect that you want to return encryptedData here, not merely
returning the original input parameter.
[QUOTE]
}

public string Decrypt(string strEncrypt)
{
.....
UnicodeEncoding byteConvert = new UnicodeEncoding();
byte[] encryptedData = byteConvert.GetBytes(strEncrypt);[/QUOTE]
encryptedData is undeclared here, I suspect you meant decryptedData
which you use below.
[QUOTE]
//byte[] byteData = Encoding.Unicode.GetBytes(strEncrypt);

.......
decryptedData = rsa.Decrypt(encryptedData, false);[/QUOTE]
decryptedData is undeclared here.[QUOTE]
return Convert.ToBase64String(decryptedData);[/QUOTE]
Why are you returning a Base-64 string here?  The original data was a
string, not a Base-64 string.[QUOTE]
......
}

den2005

When posting code cut and paste the code from your code editor, do not
attempt to retype it.

Post enough code to compile immediately without any changes.

Post the minimum of code needed to show the problem. In this case
take out all the try/catch parts, and remove the various conversions,
work everything as byte arrays. It is easy enough to write a simple
functions to test two arrays for equality.

rossum
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top