Re: Can't get basic encryption to work



Thanks a lot for your help! I wish someone like you would write a MSPress
book on .NET security.

I am reading the O'reilly book on .NET security but have no gotten to the
crypt section yet. The first part on CAS is a high level conceptual overview
with almost no code and no mention of how to use the MS config tools for
..NET.

So, I am stuck with the MCTS 70-536 book, which is pretty bad. It looks
like they just made quick guesses at the security stuff, since it doesn't
even jive with what the MSDN docs say at times, and the code does not always
work.

Sometimes I wonder if MS really even wants anyone to learn how to program
..NET.

Rick


"Joe Kaplan" wrote:

This is why I was suggesting that you buy a book like Practical Cryptography
and read it. You'll get a better grounding in the fundamentals.

If you don't want to buy a book, the Wikipedia articles on crypto are
actually pretty decent and make a nice reference. Here is a article on
block cipher operation modes that explains how the IV works and provides
some more details:

http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation

To summarize:
- The IV is not a secret! The key IS a secret.
- Every time you encrypt, you should generate a new random IV (use the
RNGCryptoServiceProvider; don't both deriving from a password for the IV).
If you don't, you weaken your security and can potentially compromise your
key.
- Include the IV with the encrypted data (somehow or another; I tend to
insert it at the beginning of the encrypted data) so that it can be
recovered during decryption.

The way you are doing it now is not correct, as you are using a fixed IV and
an IV that is based on the key itself. Bad bad bad!

Also, it is generally a good idea to avoid using ASCII encoding with crypto,
especially in a framework where strings are Unicode. ASCII encoding of a
string that contains non-Unicode characters results in data loss. If you
use UTF8 consistently, you won't have a problem.

ASCII encoding isn't technically a problem if you are positive that the
string in question will never contain non-ASCII characters, but why take the
chance? It is a bad habit that I've seen come back to haunt many an
implementation. UTF8 has the additional benefit of producing the same
binary output for ASCII characters, so there is no size gain in your binary
data if you use UTF8 on ASCII data. There is basically no downside.

Joe K.
--
Joe Kaplan-MS MVP Directory Services Programming
Co-author of "The .NET Developer's Guide to Directory Services Programming"
http://www.directoryprogramming.net
--
"DXRick" <DXRick@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:2BAE5112-BC54-4A88-9854-6000602932C8@xxxxxxxxxxxxxxxx
Thanks. I am not quite grasping this concept. If I am generating both
the
key and IV from a Rfc2898DeriveBytes object on both sides, using strings
or a
byte array that is only known to each side, how could the IV be any less
secure than the key:

Lets say the client and server have these two strings:

private string saltString =
"This34is45a99string77to55use77for88a88salt";
private string encPw = "Common44string44t";

cryptAlg = new RijndaelManaged();
cryptAlg.Key = derivedKey.GetBytes(cryptAlg.KeySize / 8);
cryptAlg.IV = derivedKey.GetBytes(cryptAlg.BlockSize / 8);

How would the IV be more "hackable"?

Thanks!


They use them to do this:

byte[] saltBytes = Encoding.ASCII.GetBytes(saltString);
Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(encPw,
saltBytes);


"Joe Kaplan" wrote:

I somehow missed that you were the same person. :) No worries.

The important thing I was trying to get across was in regards to the
initialization vector, IV, not the key. The key is a secret. You can
derive it from a password or generate a random one or whatever, but with
symmetric encryption, both sides must have the secret and guard it.

With the IV, that should be new and random every time you encrypt, but it
is
not a secret. It is exchanged with the encrypted data.

Once you get this down, moving on to asymmetric is a reasonable idea.
Symmetric encryption is one of the fundamental building blocks of
asymmetric
encryption, so it makes sense to understand it well.

Joe K.

--
Joe Kaplan-MS MVP Directory Services Programming
Co-author of "The .NET Developer's Guide to Directory Services
Programming"
http://www.directoryprogramming.net
--
"DXRick" <DXRick@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:E4E32CD3-B602-44B6-B888-BEF029699770@xxxxxxxxxxxxxxxx
I was trying to learn symmetric encryption where the client and server
would
be able to derive the same symmetric key from shared data of some sort.
I
was using the password to derive the key, but it dawned on me that if I
did
that and, and sent the encrypted name and password to the server, that
the
server would have to know what the password was to decrypt the data (a
catch-22). So, I decided just to use hard coded values for now to see
if
I
could get the encryption and decryption to work.

I am doing what you suggested before and learn one piece at a time. I
am
going to play with asymmetric now. Maybe I will end up using
asymmetric
encryption for the client and server to share the data that will be
given
to
the Rfc2898DeriveBytes object on both ends that will be used to
generate
the
key and IV.

Then I need to understand hashing and digital signing better.

So, that is why I asked the question a while ago about what system an
intranet or internet client/server app would use to pass data back and
forth.
The first data sent is the name a password of a user to either create a
new
account or retrieve their current account. Then I need to ensure that
the
account data (currently being sent as a class object) is encrypted
before
being sent back and forth.

I guess you could say I am trying to learn A, B, and C, before
attempting
to
see how they all might fit together to create a secure app. In this
thread I
couldn't even get A to work!

Thanks!!


"Joe Kaplan" wrote:

This is basically fine. Sometimes it is a good idea to be more
explicit
about the encoding method that is used to convert the string to binary
in
the stream, as this can cause headaches. In your case, you are
probably
fine since you are wrapping with StreamWriter/StreamReader and that
uses
UTF8 by default on both ends.

Also, if you convert the encrypted data to string, make sure you use
Base64.

Another thing to be aware of is proper usage of IV. It is supposed to
be
random and should be different each time. It is not a secret though
like
the key. As such, you generally want to generate a new IV with each
encryption and store the IV you used with the encrypted data so that
you
can
recover the IV that was used when you go to decrypt. One way that
people
often do this is to generate new random IV and append it to the
beginning
of
the array of encrypted data. If you know how long it is (which you
should),
then you just pull off the first X bytes as IV before doing the
encryption.

Using a static IV, an "all 0" IV or an IV that is the same as the key
all
undermine what the IV is used for (which is to help ensure that the
same
input will produce different encrypted output each time and will thus
make
your data harder to plaintext attack).

Joe K.

--
Joe Kaplan-MS MVP Directory Services Programming
Co-author of "The .NET Developer's Guide to Directory Services
Programming"
http://www.directoryprogramming.net
--
"DXRick" <DXRick@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:D506FB89-4530-49A7-AB96-9CD3F2F4CE26@xxxxxxxxxxxxxxxx
Thanks both of you. I was doing that BEFORE the write command, and
was
then
getting a padding error exception in the decryption routine. Now,
the
encryption and decryption both work.

So, here is my final code (the stuff above it is the same):

mStream = new MemoryStream();
cStream = new CryptoStream(mStream, encryptor,
CryptoStreamMode.Write);
sWriter = new StreamWriter(cStream);
sWriter.Flush();
sWriter.Write(dataToEncrypt);
sWriter.Flush();
cStream.FlushFinalBlock();

this.encryptedData = mStream.ToArray();



Thanks!


"Joe Kaplan" wrote:

You should always call FlushFinalBlock when working with block
ciphers
(which AES/Rjindael is one of). Block ciphers need to add padding
to
data
to make the final output be an even block size, so they need to
know
when
you are done adding data.

Joe K.

--
Joe Kaplan-MS MVP Directory Services Programming
Co-author of "The .NET Developer's Guide to Directory Services
Programming"
http://www.directoryprogramming.net
--
"DXRick" <DXRick@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:10F02053-2B27-4D99-A518-5AC9C4355861@xxxxxxxxxxxxxxxx
Where did you add those? If I try to close the writer before the
sWriter.Write() command I get an exception that it cannot write
to a
closed
stream.

If I just include this command, I will get a 16 byte array in
hookie:

cStream.FlushFinalBlock();

I have no clue why that would be needed.

Thanks.

"Dominick Baier" wrote:

adding an

sWriter.Flush();
sWriter.Close();

works for me...


-----
Dominick Baier (http://www.leastprivilege.com)

Developing More Secure Microsoft ASP.NET 2.0 Applications
(http://www.microsoft.com/mspress/books/9989.asp)

Those did not work.

This:

int sttr = (int)mStream.Length;

give me a 0 length. The MemoryStream is not being used?

Thanks.

"Dominick Baier" wrote:

just some ideas:

try to flush the streamwriter first...
if that doesn't help, try to position the memstream to the
beginning
(using
..Seek)
-----
Dominick Baier (http://www.leastprivilege.com)
Developing More Secure Microsoft ASP.NET 2.0 Applications
.



Relevant Pages

  • Re: LDIFDE Error when trying to change passwords.
    ... "Joe Kaplan" wrote: ... The -h adds the encryption. ... Co-author of "The .NET Developer's Guide to Directory Services ... command or the bind command as I am not sure how to use them. ...
    (microsoft.public.windows.server.active_directory)
  • Re: LDIFDE Error when trying to change passwords.
    ... "Joe Kaplan" wrote: ... Co-author of "The .NET Developer's Guide to Directory Services Programming" ... The -h adds the encryption. ... command or the bind command as I am not sure how to use them. ...
    (microsoft.public.windows.server.active_directory)
  • Re: Cant get basic encryption to work
    ... string that contains non-Unicode characters results in data loss. ... Joe Kaplan-MS MVP Directory Services Programming ... Co-author of "The .NET Developer's Guide to Directory Services Programming" ... symmetric encryption, both sides must have the secret and guard it. ...
    (microsoft.public.dotnet.security)
  • Re: Cant get basic encryption to work
    ... "Joe Kaplan" wrote: ... Symmetric encryption is one of the fundamental building blocks of asymmetric ... Co-author of "The .NET Developer's Guide to Directory Services Programming" ... Also, if you convert the encrypted data to string, make sure you use ...
    (microsoft.public.dotnet.security)
  • Re: Cant get basic encryption to work
    ... I was trying to learn symmetric encryption where the client and server would ... "Joe Kaplan" wrote: ... the stream, ...
    (microsoft.public.dotnet.security)