473,396 Members | 1,775 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

CryptoStream/MemoryStream problems

Are there any know problems with using a MemoryStream as a backing store for
a CryptoStream? I'm trying to simply encrypt and decrypt text in memory.
I'd like to create some simple methods to encrypt text before writing to a
database and decrypt it when reading it back. I figured I'd use a
MemoryStream that I can either store as a blob or convert to a string and
store as a varchar. Anyway, I can't get the CryptoStream to write to the
MemoryStream. The buffer remains empty. If I use a FileStream it works
great. But I don't want to write to a file.

Is there something I need to do differently when using a MemoryStream? Are
there any know issues/incompatiblities with CryptoStream and MemoryStream?
Is there an easier way for me to do what I want to do?

TIA,
John
Jul 21 '05 #1
7 9498
Hi John,

There are no such issues... it's just you not doing it right.

If you search VS help, keywords "cryptostream memorystream", will find several samples using MemoryStreams.

I should warn you for a different problem you will face after getting your buffer full of ciphertext.

It's a common (newbie) misunderstanding, about storing ciphertext as strings. The point is you shouldn't. Converting a buffer into a string and vice-versa is called Text encoding and decoding. There are several encoding schemes (Ascii, Unicode, UTF8, etc). Each ciphertext byte can range from 0 to 255. Encoding schemes do not preserve all those unique values. And a single wrong byte is enough to make decryption impossible.

You should always store and handle ciphertext as a buffer (array of bytes). If you really need to store it as a string then you need to get a Base encoding representation of the buffer (hexadecimal, or Base64/Mime). You can create your own Base encoding functions or use framework System.Convert.ToBase64(buffer).

Regards,
Mario
"Stingray" <nospam> wrote in message news:Ou**************@TK2MSFTNGP11.phx.gbl...
Are there any know problems with using a MemoryStream as a backing store for
a CryptoStream? I'm trying to simply encrypt and decrypt text in memory.
I'd like to create some simple methods to encrypt text before writing to a
database and decrypt it when reading it back. I figured I'd use a
MemoryStream that I can either store as a blob or convert to a string and
store as a varchar. Anyway, I can't get the CryptoStream to write to the
MemoryStream. The buffer remains empty. If I use a FileStream it works
great. But I don't want to write to a file.

Is there something I need to do differently when using a MemoryStream? Are
there any know issues/incompatiblities with CryptoStream and MemoryStream?
Is there an easier way for me to do what I want to do?

TIA,
John

Jul 21 '05 #2
Thanks Mario,

The search on my VS help didn't return anything useful but I searched on MSDN and found a good example. I was missing a FlushFinalBlock() on the CryptoStream (evidently a Flush() isn't enough). Anyway it works now!

Regarding conversion to/from string, is the following code "safe"?

byte[] buffer = ... // buffer contains encrypted byte array
// convert byte array to string
string encryptedString = Convert.ToBase64String (buffer, 0, buffer.Length);
// store encrypted string in an nvarchar in database
....
// read from database
....
// convert back to byte array
byte[] buffer = Convert.FromBase64String (encryptedString);

This seems to work perfectly, but let me know if there's something that will bite me. I can store it in the database as varbinary directly from the byte array or as an nvarchar (converted as above) and they both seem to work. I know you recommend keeping it in a byte array, but text is easier to work with, especially when it needs to be exported to xml and back. But I can deal with this if it is necessary. Is there a "standard" way that most people store encrypted values?

Also, do you have a recommendation on which algrorithm is best (Rijndael, DES, etc)? I'm using Rijndael right now. Thanks again.

John

"Mario" <mz******@DONTWANTSPAMmail.pt> wrote in message news:et**************@TK2MSFTNGP12.phx.gbl...
Hi John,

There are no such issues... it's just you not doing it right.

If you search VS help, keywords "cryptostream memorystream", will find several samples using MemoryStreams.

I should warn you for a different problem you will face after getting your buffer full of ciphertext.

It's a common (newbie) misunderstanding, about storing ciphertext as strings. The point is you shouldn't. Converting a buffer into a string and vice-versa is called Text encoding and decoding. There are several encoding schemes (Ascii, Unicode, UTF8, etc). Each ciphertext byte can range from 0 to 255. Encoding schemes do not preserve all those unique values. And a single wrong byte is enough to make decryption impossible.

You should always store and handle ciphertext as a buffer (array of bytes). If you really need to store it as a string then you need to get a Base encoding representation of the buffer (hexadecimal, or Base64/Mime). You can create your own Base encoding functions or use framework System.Convert.ToBase64(buffer).

Regards,
Mario
"Stingray" <nospam> wrote in message news:Ou**************@TK2MSFTNGP11.phx.gbl...
Are there any know problems with using a MemoryStream as a backing store for
a CryptoStream? I'm trying to simply encrypt and decrypt text in memory.
I'd like to create some simple methods to encrypt text before writing to a
database and decrypt it when reading it back. I figured I'd use a
MemoryStream that I can either store as a blob or convert to a string and
store as a varchar. Anyway, I can't get the CryptoStream to write to the
MemoryStream. The buffer remains empty. If I use a FileStream it works
great. But I don't want to write to a file.

Is there something I need to do differently when using a MemoryStream? Are
there any know issues/incompatiblities with CryptoStream and MemoryStream?
Is there an easier way for me to do what I want to do?

TIA,
John

Jul 21 '05 #3
Hi John,



Glad to know it's working now. Yes, FlushFinalBlock() is needed for padding. Symmetric algorithms are block ciphers, and many times plaintext length don't fill the last block completely (for instance, a 25 bytes buffer don't fill the second block completely; because Rijndael block size is 16 bytes, 7 bytes are missing to fill the last block). So we need to pad it with zeros or other byte value. Zero padding cannot be removed unambiguously because last plaintext bytes could be zeros as well. That's why we use a padding scheme called PKCS7 that has rules to remove padded bytes and get the same exact text. Framework default padding mode is PKCS7. As long as you don't change the default padding mode, you don't need to worry about padding at all. It's all done on your back by framework classes. I'm just saying this for curiosity.



Yes, correct, your Base64 encoding/decoding code is safe.



You can store safe Base64 encoded strings in database, no problem at all.

Base64 encoded strings take a little bit more space in the database, but are easier to use.



Most people today use Base64, taking advantage of that Framework Convert class.

In the old days, Hexadecimal format was popular, because Hex encoding is simpler than Base64; and as there was none, people implemented Hex instead of Base64.

I recommend you use Base64 strings.



You made a good choice picking Rijndael. Rijndael is AES, the new NIST standard that replaces DES.

Rijndael can work with several key sizes (128 bits, 192, 256); larger keys are safer, and take the same CPU time to encrypt/decrypt. On the other side, 128 bits (16 bytes) are safe enough. So, if you don't mind handling 32 bytes keys instead of 16 bytes keys, you can choose 256 bits keysize.



Best Regards,

Mario
"Stingray" <nospam> wrote in message news:%2****************@TK2MSFTNGP12.phx.gbl...
Thanks Mario,

The search on my VS help didn't return anything useful but I searched on MSDN and found a good example. I was missing a FlushFinalBlock() on the CryptoStream (evidently a Flush() isn't enough). Anyway it works now!

Regarding conversion to/from string, is the following code "safe"?

byte[] buffer = ... // buffer contains encrypted byte array
// convert byte array to string
string encryptedString = Convert.ToBase64String (buffer, 0, buffer.Length);
// store encrypted string in an nvarchar in database
...
// read from database
...
// convert back to byte array
byte[] buffer = Convert.FromBase64String (encryptedString);

This seems to work perfectly, but let me know if there's something that will bite me. I can store it in the database as varbinary directly from the byte array or as an nvarchar (converted as above) and they both seem to work. I know you recommend keeping it in a byte array, but text is easier to work with, especially when it needs to be exported to xml and back. But I can deal with this if it is necessary. Is there a "standard" way that most people store encrypted values?

Also, do you have a recommendation on which algrorithm is best (Rijndael, DES, etc)? I'm using Rijndael right now. Thanks again.

John

"Mario" <mz******@DONTWANTSPAMmail.pt> wrote in message news:et**************@TK2MSFTNGP12.phx.gbl...
Hi John,

There are no such issues... it's just you not doing it right.

If you search VS help, keywords "cryptostream memorystream", will find several samples using MemoryStreams.

I should warn you for a different problem you will face after getting your buffer full of ciphertext.

It's a common (newbie) misunderstanding, about storing ciphertext as strings. The point is you shouldn't. Converting a buffer into a string and vice-versa is called Text encoding and decoding. There are several encoding schemes (Ascii, Unicode, UTF8, etc). Each ciphertext byte can range from 0 to 255. Encoding schemes do not preserve all those unique values. And a single wrong byte is enough to make decryption impossible.

You should always store and handle ciphertext as a buffer (array of bytes). If you really need to store it as a string then you need to get a Base encoding representation of the buffer (hexadecimal, or Base64/Mime). You can create your own Base encoding functions or use framework System.Convert.ToBase64(buffer).

Regards,
Mario
"Stingray" <nospam> wrote in message news:Ou**************@TK2MSFTNGP11.phx.gbl...
Are there any know problems with using a MemoryStream as a backing store for
a CryptoStream? I'm trying to simply encrypt and decrypt text in memory.
I'd like to create some simple methods to encrypt text before writing to a
database and decrypt it when reading it back. I figured I'd use a
MemoryStream that I can either store as a blob or convert to a string and
store as a varchar. Anyway, I can't get the CryptoStream to write to the
MemoryStream. The buffer remains empty. If I use a FileStream it works
great. But I don't want to write to a file.

Is there something I need to do differently when using a MemoryStream? Are
there any know issues/incompatiblities with CryptoStream and MemoryStream?
Is there an easier way for me to do what I want to do?

TIA,
John

Jul 21 '05 #4
Mario,
Thank you so much for explaining all of this. You've been very helpful.
John

"Mario" <mz******@DONTWANTSPAMmail.pt> wrote in message news:Oy**************@TK2MSFTNGP12.phx.gbl...
Hi John,



Glad to know it's working now. Yes, FlushFinalBlock() is needed for padding. Symmetric algorithms are block ciphers, and many times plaintext length don't fill the last block completely (for instance, a 25 bytes buffer don't fill the second block completely; because Rijndael block size is 16 bytes, 7 bytes are missing to fill the last block). So we need to pad it with zeros or other byte value. Zero padding cannot be removed unambiguously because last plaintext bytes could be zeros as well. That's why we use a padding scheme called PKCS7 that has rules to remove padded bytes and get the same exact text. Framework default padding mode is PKCS7. As long as you don't change the default padding mode, you don't need to worry about padding at all. It's all done on your back by framework classes. I'm just saying this for curiosity.



Yes, correct, your Base64 encoding/decoding code is safe.



You can store safe Base64 encoded strings in database, no problem at all.

Base64 encoded strings take a little bit more space in the database, but are easier to use.



Most people today use Base64, taking advantage of that Framework Convert class.

In the old days, Hexadecimal format was popular, because Hex encoding is simpler than Base64; and as there was none, people implemented Hex instead of Base64.

I recommend you use Base64 strings.



You made a good choice picking Rijndael. Rijndael is AES, the new NIST standard that replaces DES.

Rijndael can work with several key sizes (128 bits, 192, 256); larger keys are safer, and take the same CPU time to encrypt/decrypt. On the other side, 128 bits (16 bytes) are safe enough. So, if you don't mind handling 32 bytes keys instead of 16 bytes keys, you can choose 256 bits keysize.



Best Regards,

Mario
"Stingray" <nospam> wrote in message news:%2****************@TK2MSFTNGP12.phx.gbl...
Thanks Mario,

The search on my VS help didn't return anything useful but I searched on MSDN and found a good example. I was missing a FlushFinalBlock() on the CryptoStream (evidently a Flush() isn't enough). Anyway it works now!

Regarding conversion to/from string, is the following code "safe"?

byte[] buffer = ... // buffer contains encrypted byte array
// convert byte array to string
string encryptedString = Convert.ToBase64String (buffer, 0, buffer.Length);
// store encrypted string in an nvarchar in database
...
// read from database
...
// convert back to byte array
byte[] buffer = Convert.FromBase64String (encryptedString);

This seems to work perfectly, but let me know if there's something that will bite me. I can store it in the database as varbinary directly from the byte array or as an nvarchar (converted as above) and they both seem to work. I know you recommend keeping it in a byte array, but text is easier to work with, especially when it needs to be exported to xml and back. But I can deal with this if it is necessary. Is there a "standard" way that most people store encrypted values?

Also, do you have a recommendation on which algrorithm is best (Rijndael, DES, etc)? I'm using Rijndael right now. Thanks again.

John

"Mario" <mz******@DONTWANTSPAMmail.pt> wrote in message news:et**************@TK2MSFTNGP12.phx.gbl...
Hi John,

There are no such issues... it's just you not doing it right.

If you search VS help, keywords "cryptostream memorystream", will find several samples using MemoryStreams.

I should warn you for a different problem you will face after getting your buffer full of ciphertext.

It's a common (newbie) misunderstanding, about storing ciphertext as strings. The point is you shouldn't. Converting a buffer into a string and vice-versa is called Text encoding and decoding. There are several encoding schemes (Ascii, Unicode, UTF8, etc). Each ciphertext byte can range from 0 to 255. Encoding schemes do not preserve all those unique values. And a single wrong byte is enough to make decryption impossible.

You should always store and handle ciphertext as a buffer (array of bytes). If you really need to store it as a string then you need to get a Base encoding representation of the buffer (hexadecimal, or Base64/Mime). You can create your own Base encoding functions or use framework System.Convert.ToBase64(buffer).

Regards,
Mario
"Stingray" <nospam> wrote in message news:Ou**************@TK2MSFTNGP11.phx.gbl...
Are there any know problems with using a MemoryStream as a backing store for
a CryptoStream? I'm trying to simply encrypt and decrypt text in memory.
I'd like to create some simple methods to encrypt text before writing to a
database and decrypt it when reading it back. I figured I'd use a
MemoryStream that I can either store as a blob or convert to a string and
store as a varchar. Anyway, I can't get the CryptoStream to write to the
MemoryStream. The buffer remains empty. If I use a FileStream it works
great. But I don't want to write to a file.

Is there something I need to do differently when using a MemoryStream? Are
there any know issues/incompatiblities with CryptoStream and MemoryStream?
Is there an easier way for me to do what I want to do?

TIA,
John

Jul 21 '05 #5
One other thing to look out for - Rijndael streams can be self correcting. If you change a bit in the encrypted data, part of the plaintext will come out okay, and part of it will be corrupted. Rijndael won't tell you if there is an error.

To correct this, run your plaintext through an SHA1 hash and encrypt it along with your data. I find it is easy to put the Base64 version of the hash, along with the plaintext in a CDATA section, into an XML document and encrypt the whole thing. When you decrypt, you can tell if the data has been corrupted in any way by comparing hash values.

Oh, and if your plaintext is an XML document, you can use Zero Padding just fine.
"Stingray" <nospam> wrote in message news:%2****************@TK2MSFTNGP11.phx.gbl...
Mario,
Thank you so much for explaining all of this. You've been very helpful.
John

"Mario" <mz******@DONTWANTSPAMmail.pt> wrote in message news:Oy**************@TK2MSFTNGP12.phx.gbl...
Hi John,



Glad to know it's working now. Yes, FlushFinalBlock() is needed for padding. Symmetric algorithms are block ciphers, and many times plaintext length don't fill the last block completely (for instance, a 25 bytes buffer don't fill the second block completely; because Rijndael block size is 16 bytes, 7 bytes are missing to fill the last block). So we need to pad it with zeros or other byte value. Zero padding cannot be removed unambiguously because last plaintext bytes could be zeros as well. That's why we use a padding scheme called PKCS7 that has rules to remove padded bytes and get the same exact text. Framework default padding mode is PKCS7. As long as you don't change the default padding mode, you don't need to worry about padding at all. It's all done on your back by framework classes. I'm just saying this for curiosity.



Yes, correct, your Base64 encoding/decoding code is safe.



You can store safe Base64 encoded strings in database, no problem at all.

Base64 encoded strings take a little bit more space in the database, but are easier to use.



Most people today use Base64, taking advantage of that Framework Convert class.

In the old days, Hexadecimal format was popular, because Hex encoding is simpler than Base64; and as there was none, people implemented Hex instead of Base64.

I recommend you use Base64 strings.



You made a good choice picking Rijndael. Rijndael is AES, the new NIST standard that replaces DES.

Rijndael can work with several key sizes (128 bits, 192, 256); larger keys are safer, and take the same CPU time to encrypt/decrypt. On the other side, 128 bits (16 bytes) are safe enough. So, if you don't mind handling 32 bytes keys instead of 16 bytes keys, you can choose 256 bits keysize.



Best Regards,

Mario
"Stingray" <nospam> wrote in message news:%2****************@TK2MSFTNGP12.phx.gbl...
Thanks Mario,

The search on my VS help didn't return anything useful but I searched on MSDN and found a good example. I was missing a FlushFinalBlock() on the CryptoStream (evidently a Flush() isn't enough). Anyway it works now!

Regarding conversion to/from string, is the following code "safe"?

byte[] buffer = ... // buffer contains encrypted byte array
// convert byte array to string
string encryptedString = Convert.ToBase64String (buffer, 0, buffer.Length);
// store encrypted string in an nvarchar in database
...
// read from database
...
// convert back to byte array
byte[] buffer = Convert.FromBase64String (encryptedString);

This seems to work perfectly, but let me know if there's something that will bite me. I can store it in the database as varbinary directly from the byte array or as an nvarchar (converted as above) and they both seem to work. I know you recommend keeping it in a byte array, but text is easier to work with, especially when it needs to be exported to xml and back. But I can deal with this if it is necessary. Is there a "standard" way that most people store encrypted values?

Also, do you have a recommendation on which algrorithm is best (Rijndael, DES, etc)? I'm using Rijndael right now. Thanks again.

John

"Mario" <mz******@DONTWANTSPAMmail.pt> wrote in message news:et**************@TK2MSFTNGP12.phx.gbl...
Hi John,

There are no such issues... it's just you not doing it right.

If you search VS help, keywords "cryptostream memorystream", will find several samples using MemoryStreams.

I should warn you for a different problem you will face after getting your buffer full of ciphertext.

It's a common (newbie) misunderstanding, about storing ciphertext as strings. The point is you shouldn't. Converting a buffer into a string and vice-versa is called Text encoding and decoding. There are several encoding schemes (Ascii, Unicode, UTF8, etc). Each ciphertext byte can range from 0 to 255. Encoding schemes do not preserve all those unique values. And a single wrong byte is enough to make decryption impossible.

You should always store and handle ciphertext as a buffer (array of bytes). If you really need to store it as a string then you need to get a Base encoding representation of the buffer (hexadecimal, or Base64/Mime). You can create your own Base encoding functions or use framework System.Convert.ToBase64(buffer).

Regards,
Mario
"Stingray" <nospam> wrote in message news:Ou**************@TK2MSFTNGP11.phx.gbl...
Are there any know problems with using a MemoryStream as a backing store for
a CryptoStream? I'm trying to simply encrypt and decrypt text in memory.
I'd like to create some simple methods to encrypt text before writing to a
database and decrypt it when reading it back. I figured I'd use a
MemoryStream that I can either store as a blob or convert to a string and
store as a varchar. Anyway, I can't get the CryptoStream to write to the
MemoryStream. The buffer remains empty. If I use a FileStream it works
great. But I don't want to write to a file.

Is there something I need to do differently when using a MemoryStream? Are
there any know issues/incompatiblities with CryptoStream and MemoryStream?
Is there an easier way for me to do what I want to do?

TIA,
John

Jul 21 '05 #6
Thanks Jason. I'll keep this in mind also.

I do have one further question though for anyone: Where is a good place to store keys? Apps need to be able to get to them easily but most people should not.

John
"Jason Smith" <ja***@nospam.com> wrote in message news:%2****************@TK2MSFTNGP11.phx.gbl...
One other thing to look out for - Rijndael streams can be self correcting. If you change a bit in the encrypted data, part of the plaintext will come out okay, and part of it will be corrupted. Rijndael won't tell you if there is an error.

To correct this, run your plaintext through an SHA1 hash and encrypt it along with your data. I find it is easy to put the Base64 version of the hash, along with the plaintext in a CDATA section, into an XML document and encrypt the whole thing. When you decrypt, you can tell if the data has been corrupted in any way by comparing hash values.

Oh, and if your plaintext is an XML document, you can use Zero Padding just fine.
"Stingray" <nospam> wrote in message news:%2****************@TK2MSFTNGP11.phx.gbl...
Mario,
Thank you so much for explaining all of this. You've been very helpful.
John

"Mario" <mz******@DONTWANTSPAMmail.pt> wrote in message news:Oy**************@TK2MSFTNGP12.phx.gbl...
Hi John,



Glad to know it's working now. Yes, FlushFinalBlock() is needed for padding. Symmetric algorithms are block ciphers, and many times plaintext length don't fill the last block completely (for instance, a 25 bytes buffer don't fill the second block completely; because Rijndael block size is 16 bytes, 7 bytes are missing to fill the last block). So we need to pad it with zeros or other byte value. Zero padding cannot be removed unambiguously because last plaintext bytes could be zeros as well. That's why we use a padding scheme called PKCS7 that has rules to remove padded bytes and get the same exact text. Framework default padding mode is PKCS7. As long as you don't change the default padding mode, you don't need to worry about padding at all. It's all done on your back by framework classes. I'm just saying this for curiosity.



Yes, correct, your Base64 encoding/decoding code is safe.



You can store safe Base64 encoded strings in database, no problem at all.

Base64 encoded strings take a little bit more space in the database, but are easier to use.



Most people today use Base64, taking advantage of that Framework Convert class.

In the old days, Hexadecimal format was popular, because Hex encoding is simpler than Base64; and as there was none, people implemented Hex instead of Base64.

I recommend you use Base64 strings.



You made a good choice picking Rijndael. Rijndael is AES, the new NIST standard that replaces DES.

Rijndael can work with several key sizes (128 bits, 192, 256); larger keys are safer, and take the same CPU time to encrypt/decrypt. On the other side, 128 bits (16 bytes) are safe enough. So, if you don't mind handling 32 bytes keys instead of 16 bytes keys, you can choose 256 bits keysize.



Best Regards,

Mario
"Stingray" <nospam> wrote in message news:%2****************@TK2MSFTNGP12.phx.gbl...
Thanks Mario,

The search on my VS help didn't return anything useful but I searched on MSDN and found a good example. I was missing a FlushFinalBlock() on the CryptoStream (evidently a Flush() isn't enough). Anyway it works now!

Regarding conversion to/from string, is the following code "safe"?

byte[] buffer = ... // buffer contains encrypted byte array
// convert byte array to string
string encryptedString = Convert.ToBase64String (buffer, 0, buffer.Length);
// store encrypted string in an nvarchar in database
...
// read from database
...
// convert back to byte array
byte[] buffer = Convert.FromBase64String (encryptedString);

This seems to work perfectly, but let me know if there's something that will bite me. I can store it in the database as varbinary directly from the byte array or as an nvarchar (converted as above) and they both seem to work. I know you recommend keeping it in a byte array, but text is easier to work with, especially when it needs to be exported to xml and back. But I can deal with this if it is necessary. Is there a "standard" way that most people store encrypted values?

Also, do you have a recommendation on which algrorithm is best (Rijndael, DES, etc)? I'm using Rijndael right now. Thanks again.

John

"Mario" <mz******@DONTWANTSPAMmail.pt> wrote in message news:et**************@TK2MSFTNGP12.phx.gbl...
Hi John,

There are no such issues... it's just you not doing it right.

If you search VS help, keywords "cryptostream memorystream", will find several samples using MemoryStreams.

I should warn you for a different problem you will face after getting your buffer full of ciphertext.

It's a common (newbie) misunderstanding, about storing ciphertext as strings. The point is you shouldn't. Converting a buffer into a string and vice-versa is called Text encoding and decoding. There are several encoding schemes (Ascii, Unicode, UTF8, etc). Each ciphertext byte can range from 0 to 255. Encoding schemes do not preserve all those unique values. And a single wrong byte is enough to make decryption impossible.

You should always store and handle ciphertext as a buffer (array of bytes). If you really need to store it as a string then you need to get a Base encoding representation of the buffer (hexadecimal, or Base64/Mime). You can create your own Base encoding functions or use framework System.Convert.ToBase64(buffer).

Regards,
Mario
"Stingray" <nospam> wrote in message news:Ou**************@TK2MSFTNGP11.phx.gbl...
Are there any know problems with using a MemoryStream as a backing store for
a CryptoStream? I'm trying to simply encrypt and decrypt text in memory.
I'd like to create some simple methods to encrypt text before writing to a
database and decrypt it when reading it back. I figured I'd use a
MemoryStream that I can either store as a blob or convert to a string and
store as a varchar. Anyway, I can't get the CryptoStream to write to the
MemoryStream. The buffer remains empty. If I use a FileStream it works
great. But I don't want to write to a file.

Is there something I need to do differently when using a MemoryStream? Are
there any know issues/incompatiblities with CryptoStream and MemoryStream?
Is there an easier way for me to do what I want to do?

TIA,
John

Jul 21 '05 #7
check out:
http://msdn.microsoft.com/msdnmag/is...a/default.aspx

On Mon, 22 Sep 2003 11:49:13 -0600, "Stingray" <nospam> wrote:
Thanks Jason. I'll keep this in mind also.

I do have one further question though for anyone: Where is a good place to store keys? Apps need to be able to get to them easily but most people should not.

John
"Jason Smith" <ja***@nospam.com> wrote in message news:%2****************@TK2MSFTNGP11.phx.gbl...
One other thing to look out for - Rijndael streams can be self correcting. If you change a bit in the encrypted data, part of the plaintext will come out okay, and part of it will be corrupted. Rijndael won't tell you if there is an error.

To correct this, run your plaintext through an SHA1 hash and encrypt it along with your data. I find it is easy to put the Base64 version of the hash, along with the plaintext in a CDATA section, into an XML document and encrypt the whole thing. When you decrypt, you can tell if the data has been corrupted in any way by comparing hash values.

Oh, and if your plaintext is an XML document, you can use Zero Padding just fine.
"Stingray" <nospam> wrote in message news:%2****************@TK2MSFTNGP11.phx.gbl...
Mario,
Thank you so much for explaining all of this. You've been very helpful.
John

"Mario" <mz******@DONTWANTSPAMmail.pt> wrote in message news:Oy**************@TK2MSFTNGP12.phx.gbl...
Hi John,

Glad to know it's working now. Yes, FlushFinalBlock() is needed for padding. Symmetric algorithms are block ciphers, and many times plaintext length don't fill the last block completely (for instance, a 25 bytes buffer don't fill the second block completely; because Rijndael block size is 16 bytes, 7 bytes are missing to fill the last block). So we need to pad it with zeros or other byte value. Zero padding cannot be removed unambiguously because last plaintext bytes could be zeros as well. That's why we use a padding scheme called PKCS7 that has rules to remove padded bytes and get the same exact text. Framework default padding mode is PKCS7. As long as you don't change the default padding mode, you don't need to worry about padding at all. It's all done on your back by framework classes. I'm just saying this for curiosity.

Yes, correct, your Base64 encoding/decoding code is safe.

You can store safe Base64 encoded strings in database, no problem at all.

Base64 encoded strings take a little bit more space in the database, but are easier to use.

Most people today use Base64, taking advantage of that Framework Convert class.

In the old days, Hexadecimal format was popular, because Hex encoding is simpler than Base64; and as there was none, people implemented Hex instead of Base64.

I recommend you use Base64 strings.

You made a good choice picking Rijndael. Rijndael is AES, the new NIST standard that replaces DES.

Rijndael can work with several key sizes (128 bits, 192, 256); larger keys are safer, and take the same CPU time to encrypt/decrypt. On the other side, 128 bits (16 bytes) are safe enough. So, if you don't mind handling 32 bytes keys instead of 16 bytes keys, you can choose 256 bits keysize.

Best Regards,

Mario
"Stingray" <nospam> wrote in message news:%2****************@TK2MSFTNGP12.phx.gbl...
Thanks Mario,

The search on my VS help didn't return anything useful but I searched on MSDN and found a good example. I was missing a FlushFinalBlock() on the CryptoStream (evidently a Flush() isn't enough). Anyway it works now!

Regarding conversion to/from string, is the following code "safe"?

byte[] buffer = ... // buffer contains encrypted byte array
// convert byte array to string
string encryptedString = Convert.ToBase64String (buffer, 0, buffer.Length);
// store encrypted string in an nvarchar in database
...
// read from database
...
// convert back to byte array
byte[] buffer = Convert.FromBase64String (encryptedString);

This seems to work perfectly, but let me know if there's something that will bite me. I can store it in the database as varbinary directly from the byte array or as an nvarchar (converted as above) and they both seem to work. I know you recommend keeping it in a byte array, but text is easier to work with, especially when it needs to be exported to xml and back. But I can deal with this if it is necessary. Is there a "standard" way that most people store encrypted values?

Also, do you have a recommendation on which algrorithm is best (Rijndael, DES, etc)? I'm using Rijndael right now. Thanks again.

John

"Mario" <mz******@DONTWANTSPAMmail.pt> wrote in message news:et**************@TK2MSFTNGP12.phx.gbl...
Hi John,

There are no such issues... it's just you not doing it right.

If you search VS help, keywords "cryptostream memorystream", will find several samples using MemoryStreams.

I should warn you for a different problem you will face after getting your buffer full of ciphertext.

It's a common (newbie) misunderstanding, about storing ciphertext as strings. The point is you shouldn't. Converting a buffer into a string and vice-versa is called Text encoding and decoding. There are several encoding schemes (Ascii, Unicode, UTF8, etc). Each ciphertext byte can range from 0 to 255. Encoding schemes do not preserve all those unique values. And a single wrong byte is enough to make decryption impossible.

You should always store and handle ciphertext as a buffer (array of bytes). If you really need to store it as a string then you need to get a Base encoding representation of the buffer (hexadecimal, or Base64/Mime). You can create your own Base encoding functions or use framework System.Convert.ToBase64(buffer).

Regards,
Mario
"Stingray" <nospam> wrote in message news:Ou**************@TK2MSFTNGP11.phx.gbl...
> Are there any know problems with using a MemoryStream as a backing store for
> a CryptoStream? I'm trying to simply encrypt and decrypt text in memory.
> I'd like to create some simple methods to encrypt text before writing to a
> database and decrypt it when reading it back. I figured I'd use a
> MemoryStream that I can either store as a blob or convert to a string and
> store as a varchar. Anyway, I can't get the CryptoStream to write to the
> MemoryStream. The buffer remains empty. If I use a FileStream it works
> great. But I don't want to write to a file.
>
> Is there something I need to do differently when using a MemoryStream? Are
> there any know issues/incompatiblities with CryptoStream and MemoryStream?
> Is there an easier way for me to do what I want to do?
>
> TIA,
> John
>
>


Jul 21 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: MattP | last post by:
Ok, with the help of some examples found on the web and some minor modifications on our own, we have a simple and working encrypt and decrypt solution. It runs as a service, watches for files with...
1
by: Casey Watson | last post by:
Hi :) I'm having some major trouble with an XML Client/Server application that I am writing. I am using NetworkStream with CryptoStream to Read and Write XML between computers. Now, whenever I...
5
by: weixiang | last post by:
Hi, I want to use DES and CryptoStream to serialize a encrypted stream to a file with a header "CRYPT". And I wrote these code: To store: FileStream fileStream = new FileStream(fileName,...
3
by: James | last post by:
Hi, I am developing a ActiveX Control which will be used in a web page. The control will encrypt some value then decrypt it when the web page opens next time. I tested the control in a windows...
1
by: Nicholas Holder | last post by:
A client creates a connection to the server using the TCPListener/Client classes and transfers data via a NetworkStream. When the client connects, the server creates a process and redirects its...
7
by: Stingray | last post by:
Are there any know problems with using a MemoryStream as a backing store for a CryptoStream? I'm trying to simply encrypt and decrypt text in memory. I'd like to create some simple methods to...
7
by: semedao | last post by:
Hi, I am using cryptostream on both sides on tcp connection that pass data. I am also use asyc socket , so , the data that recieved in the callback method not always have the length of the buffer...
9
by: TC | last post by:
Hey All, I posted this to the Crypto users group and forgot to add the VB.Net users group. I apologize for any confusion. I have been testing a try / catch / finally block and purposely...
2
by: Anil Gupte/iCinema.com | last post by:
I am getting the following message and no, it is not even going to that statement twice. Why is this happening? System.NotSupportedException was caught Message="FlushFinalBlock() method was...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.