what's wrong with this code?, getting lot of \0\0\0

J

Jeff

hi

..NET 3.5

I have created some code which encrypt and decrypt text. The decryption
doesn't return the exact same string as the original...

If I have the string "sambi" and encrypt it... after decrypting the
encrypted string I get this. "sambi\0\0\0\0\0\0\0\0\0\0\0"

So I wonder what in my code produces all those \0\0\0\0\0\0\0\0\0\0\0

Here is my code:
public sealed class CryptoString
{
public CryptoString() {}

private static byte[] savedKey = null;
private static byte[] savedIV = null;

public static byte[] Key
{
get { return savedKey; }
set { savedKey = value; }
}

public static byte[] IV
{
get { return savedIV; }
set { savedIV = value; }
}

private static void RdGenerateSecretKey(RijndaelManaged rdProvider)
{
if (savedKey == null)
{
rdProvider.KeySize = 256;
rdProvider.GenerateKey();
savedKey = rdProvider.Key;
}
}

private static void RdGenerateSecretInitVector(RijndaelManaged
rdProvider)
{
if (savedIV == null)
{
rdProvider.GenerateIV();
savedIV = rdProvider.IV;
}
}

public static string Encrypt(string originalStr)
{
//Encode data string to be stored in memory
byte[] originalStrAsBytes =
Encoding.ASCII.GetBytes(originalStr);
byte[] originalBytes = { };

//create MemoryStream to contain output
MemoryStream memStream = new
MemoryStream(originalStrAsBytes.Length);

RijndaelManaged rijndael = new RijndaelManaged();
RdGenerateSecretKey(rijndael);
RdGenerateSecretInitVector(rijndael);

if (savedKey == null || savedIV == null)
{
throw (new NullReferenceException("savedKey and savedIV must
not be non-null"));
}

//create encryptor, and stream objects
ICryptoTransform rdTransform =
rijndael.CreateEncryptor((byte[])savedKey.Clone(), (byte[])savedIV.Clone());
CryptoStream cryptoStream = new CryptoStream(memStream,
rdTransform, CryptoStreamMode.Write);

//write encrypted data to the memorystream
cryptoStream.Write(originalStrAsBytes, 0,
originalStrAsBytes.Length);
cryptoStream.FlushFinalBlock();
originalBytes = memStream.ToArray();

//release all resources
memStream.Close();
cryptoStream.Close();
rdTransform.Dispose();
rijndael.Clear();

//convert encrypted string
string encryptedStr = Convert.ToBase64String(originalBytes);
return (encryptedStr);

}

public static string Decrypt(string encryptedStr)
{
//unconvert encrypted string
byte[] encryptedStrAsBytes =
Convert.FromBase64String(encryptedStr);
byte[] initialText = new Byte[encryptedStrAsBytes.Length];

RijndaelManaged rijndael = new RijndaelManaged();
MemoryStream memStream = new MemoryStream(encryptedStrAsBytes);

if (savedKey == null || savedIV == null)
{
throw (new NullReferenceException("savedKey and savedIV must
be non-null"));
}

//create decryptor, and stream objects
ICryptoTransform rdTransform =
rijndael.CreateDecryptor((byte[])savedKey.Clone(), (byte[])savedIV.Clone());
CryptoStream cryptoStream = new CryptoStream(memStream,
rdTransform, CryptoStreamMode.Read);

//read in decrypted string as a byte[]
cryptoStream.Read(initialText, 0, initialText.Length);

//release all resources
memStream.Close();
cryptoStream.Close();
rdTransform.Dispose();
rijndael.Clear();

//convert byte[] to string
string decryptedStr = Encoding.ASCII.GetString(initialText);
return (decryptedStr);
}


}
 
A

Arne Vajhøj

Jeff said:
I have created some code which encrypt and decrypt text. The decryption
doesn't return the exact same string as the original...

If I have the string "sambi" and encrypt it... after decrypting the
encrypted string I get this. "sambi\0\0\0\0\0\0\0\0\0\0\0"

So I wonder what in my code produces all those \0\0\0\0\0\0\0\0\0\0\0

Here is my code:
public sealed class CryptoString
{
public CryptoString() {}

private static byte[] savedKey = null;
private static byte[] savedIV = null;

public static byte[] Key
{
get { return savedKey; }
set { savedKey = value; }
}

public static byte[] IV
{
get { return savedIV; }
set { savedIV = value; }
}

private static void RdGenerateSecretKey(RijndaelManaged rdProvider)
{
if (savedKey == null)
{
rdProvider.KeySize = 256;
rdProvider.GenerateKey();
savedKey = rdProvider.Key;
}
}

private static void RdGenerateSecretInitVector(RijndaelManaged
rdProvider)
{
if (savedIV == null)
{
rdProvider.GenerateIV();
savedIV = rdProvider.IV;
}
}

public static string Encrypt(string originalStr)
{
//Encode data string to be stored in memory
byte[] originalStrAsBytes =
Encoding.ASCII.GetBytes(originalStr);
byte[] originalBytes = { };

//create MemoryStream to contain output
MemoryStream memStream = new
MemoryStream(originalStrAsBytes.Length);

RijndaelManaged rijndael = new RijndaelManaged();
RdGenerateSecretKey(rijndael);
RdGenerateSecretInitVector(rijndael);

if (savedKey == null || savedIV == null)
{
throw (new NullReferenceException("savedKey and savedIV must
not be non-null"));
}

//create encryptor, and stream objects
ICryptoTransform rdTransform =
rijndael.CreateEncryptor((byte[])savedKey.Clone(), (byte[])savedIV.Clone());
CryptoStream cryptoStream = new CryptoStream(memStream,
rdTransform, CryptoStreamMode.Write);

//write encrypted data to the memorystream
cryptoStream.Write(originalStrAsBytes, 0,
originalStrAsBytes.Length);
cryptoStream.FlushFinalBlock();
originalBytes = memStream.ToArray();

//release all resources
memStream.Close();
cryptoStream.Close();
rdTransform.Dispose();
rijndael.Clear();

//convert encrypted string
string encryptedStr = Convert.ToBase64String(originalBytes);
return (encryptedStr);

}

public static string Decrypt(string encryptedStr)
{
//unconvert encrypted string
byte[] encryptedStrAsBytes =
Convert.FromBase64String(encryptedStr);
byte[] initialText = new Byte[encryptedStrAsBytes.Length];

RijndaelManaged rijndael = new RijndaelManaged();
MemoryStream memStream = new MemoryStream(encryptedStrAsBytes);

if (savedKey == null || savedIV == null)
{
throw (new NullReferenceException("savedKey and savedIV must
be non-null"));
}

//create decryptor, and stream objects
ICryptoTransform rdTransform =
rijndael.CreateDecryptor((byte[])savedKey.Clone(), (byte[])savedIV.Clone());
CryptoStream cryptoStream = new CryptoStream(memStream,
rdTransform, CryptoStreamMode.Read);

//read in decrypted string as a byte[]
cryptoStream.Read(initialText, 0, initialText.Length);

//release all resources
memStream.Close();
cryptoStream.Close();
rdTransform.Dispose();
rijndael.Clear();

//convert byte[] to string
string decryptedStr = Encoding.ASCII.GetString(initialText);
return (decryptedStr);
}


}

My guess would be that the problem is because Decrypt byte array
initialText includes room for padding bytes - you should use the
actual number of read bytes returned by Read.

Arne

PS: And I am sure the use of Encoding.ASCII will give you problems
at some time !
 
J

Jeff

you are right, the encryptedStrAsBytes.Length has value 16,

Unsure how to remove the traling 11 bytes from encryptedStrAsBytes, I mean I
can just subtract 11:
encryptedStrAsBytes.Length - 11
But that doesn't fix the problem, as "sambi" is an example. The code must be
able to handle string of any length, but I doubt the string will be longer
than 50

you got any more tips?



rossum said:
hi

.NET 3.5

I have created some code which encrypt and decrypt text. The decryption
doesn't return the exact same string as the original...

If I have the string "sambi" and encrypt it... after decrypting the
encrypted string I get this. "sambi\0\0\0\0\0\0\0\0\0\0\0"
Rijndael is a 128 bit block cypher, so a block is 16 bytes. Including
the extra null bytes, what you have above is 16 bytes so at some point
you are taking an entire block rather than your actual text, which
only forms part of a block.

Checking RijndaelManaged shows that it defaults to CBC mode and PKCS7
padding. What you have above is not PKCS7 padding so I would suspect
that the problem is somewhere on the decryption side.

So I wonder what in my code produces all those \0\0\0\0\0\0\0\0\0\0\0

Here is my code:

[snip part code]
public static string Decrypt(string encryptedStr)
{
//unconvert encrypted string
byte[] encryptedStrAsBytes =
Convert.FromBase64String(encryptedStr);
byte[] initialText = new Byte[encryptedStrAsBytes.Length];
The length you are dealing with here may well be a full block (16
bytes) rather than just your text (5 bytes). Check lengths at this
point.

RijndaelManaged rijndael = new RijndaelManaged();
MemoryStream memStream = new
MemoryStream(encryptedStrAsBytes);

if (savedKey == null || savedIV == null)
{
throw (new NullReferenceException("savedKey and savedIV
must
be non-null"));
}

//create decryptor, and stream objects
ICryptoTransform rdTransform =
rijndael.CreateDecryptor((byte[])savedKey.Clone(),
(byte[])savedIV.Clone());
CryptoStream cryptoStream = new CryptoStream(memStream,
rdTransform, CryptoStreamMode.Read);

//read in decrypted string as a byte[]
cryptoStream.Read(initialText, 0, initialText.Length);
If the initialText.length is a full block, 16 bytes, then you will try
to read 16 bytes here. CryptoStream.Read() returns the number of
bytes actually read. I suggest that you capture and check that number
- I suspect that it will be 5. Only the first 5 bytes of initialText
will come from the Read(), the rest will be left over from the
declaration. That would explain why they are zero.

rossum
//release all resources
memStream.Close();
cryptoStream.Close();
rdTransform.Dispose();
rijndael.Clear();

//convert byte[] to string
string decryptedStr = Encoding.ASCII.GetString(initialText);
return (decryptedStr);
}


}
 
A

Arne Vajhøj

Jeff said:
you are right, the encryptedStrAsBytes.Length has value 16,

Unsure how to remove the traling 11 bytes from encryptedStrAsBytes, I mean I
can just subtract 11:
encryptedStrAsBytes.Length - 11
But that doesn't fix the problem, as "sambi" is an example. The code must be
able to handle string of any length, but I doubt the string will be longer
than 50

As I wrote, then Read will return the actual number of bytes.

Arne
 
J

Jeff

okay, I do an TrimEnd(Char.Parse("\0") ), I suppose that remove the \0


Jeff said:
you are right, the encryptedStrAsBytes.Length has value 16,

Unsure how to remove the traling 11 bytes from encryptedStrAsBytes, I mean
I can just subtract 11:
encryptedStrAsBytes.Length - 11
But that doesn't fix the problem, as "sambi" is an example. The code must
be able to handle string of any length, but I doubt the string will be
longer than 50

you got any more tips?



rossum said:
hi

.NET 3.5

I have created some code which encrypt and decrypt text. The decryption
doesn't return the exact same string as the original...

If I have the string "sambi" and encrypt it... after decrypting the
encrypted string I get this. "sambi\0\0\0\0\0\0\0\0\0\0\0"
Rijndael is a 128 bit block cypher, so a block is 16 bytes. Including
the extra null bytes, what you have above is 16 bytes so at some point
you are taking an entire block rather than your actual text, which
only forms part of a block.

Checking RijndaelManaged shows that it defaults to CBC mode and PKCS7
padding. What you have above is not PKCS7 padding so I would suspect
that the problem is somewhere on the decryption side.

So I wonder what in my code produces all those \0\0\0\0\0\0\0\0\0\0\0

Here is my code:

[snip part code]
public static string Decrypt(string encryptedStr)
{
//unconvert encrypted string
byte[] encryptedStrAsBytes =
Convert.FromBase64String(encryptedStr);
byte[] initialText = new Byte[encryptedStrAsBytes.Length];
The length you are dealing with here may well be a full block (16
bytes) rather than just your text (5 bytes). Check lengths at this
point.

RijndaelManaged rijndael = new RijndaelManaged();
MemoryStream memStream = new
MemoryStream(encryptedStrAsBytes);

if (savedKey == null || savedIV == null)
{
throw (new NullReferenceException("savedKey and savedIV
must
be non-null"));
}

//create decryptor, and stream objects
ICryptoTransform rdTransform =
rijndael.CreateDecryptor((byte[])savedKey.Clone(),
(byte[])savedIV.Clone());
CryptoStream cryptoStream = new CryptoStream(memStream,
rdTransform, CryptoStreamMode.Read);

//read in decrypted string as a byte[]
cryptoStream.Read(initialText, 0, initialText.Length);
If the initialText.length is a full block, 16 bytes, then you will try
to read 16 bytes here. CryptoStream.Read() returns the number of
bytes actually read. I suggest that you capture and check that number
- I suspect that it will be 5. Only the first 5 bytes of initialText
will come from the Read(), the rest will be left over from the
declaration. That would explain why they are zero.

rossum
//release all resources
memStream.Close();
cryptoStream.Close();
rdTransform.Dispose();
rijndael.Clear();

//convert byte[] to string
string decryptedStr = Encoding.ASCII.GetString(initialText);
return (decryptedStr);
}


}
 
J

Jeff

When I encrypt a string, the result returned by Encrypt has 2 trailing ==,
like:
Rrs7tA2FrFXFlFAJRw==

I'm trying to construct a link and have the values returned by Encrypt as a
parameter in the link, but the problem is that those links I create don't
work because the == is not considered part of the link, it just becomes
plain text. like:

www.test.com?id=Rrs7tA2FrFXFlFAJRw==

and that link don't work as also the == need to be underlined

any suggestions?
 
G

Göran Andersson

Jeff said:
hi

.NET 3.5

I have created some code which encrypt and decrypt text. The decryption
doesn't return the exact same string as the original...

If I have the string "sambi" and encrypt it... after decrypting the
encrypted string I get this. "sambi\0\0\0\0\0\0\0\0\0\0\0"

So I wonder what in my code produces all those \0\0\0\0\0\0\0\0\0\0\0

This is a common problem when you are not using the Read method
correctly. As Arne has said (several times), you have to use the return
value from the Read method to determine how many bytes are read. Also,
the Read method doesn't have to return the number of bytes that you
requested, so you have to call the Read method until it returns the
value zero, which means that you have reached the end of the stream.

byte[] initialText;

byte[] buffer = new byte[1000];
MemoryStream m = new MemoryStream();
int len;
while ((len = cryptoStream.Read(buffer, 0, 1000)) > 0) {
m.Write(buffer, 0, len);
}
initialText = m.ToArray();
 
G

Göran Andersson

Jeff said:
When I encrypt a string, the result returned by Encrypt has 2 trailing ==,
like:
Rrs7tA2FrFXFlFAJRw==

I'm trying to construct a link and have the values returned by Encrypt as a
parameter in the link, but the problem is that those links I create don't
work because the == is not considered part of the link, it just becomes
plain text. like:

www.test.com?id=Rrs7tA2FrFXFlFAJRw==

and that link don't work as also the == need to be underlined

any suggestions?

You need to encode the value to put it in an URL. Use the UrlEncode
method in the HttpUtility or HttpServerUtility classes.
 
A

Arne Vajhøj

Jeff said:
When I encrypt a string, the result returned by Encrypt has 2 trailing ==,
like:
Rrs7tA2FrFXFlFAJRw==

I'm trying to construct a link and have the values returned by Encrypt as a
parameter in the link, but the problem is that those links I create don't
work because the == is not considered part of the link, it just becomes
plain text. like:

www.test.com?id=Rrs7tA2FrFXFlFAJRw==

and that link don't work as also the == need to be underlined

any suggestions?

Either URL encode.

Or switch from Base64 to Hex.

Arne
 

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