Home All Groups Group Topic Archive Search About

Rijndael decryption succeeds SOMETIMES

Author
5 Apr 2005 11:43 PM
Derek Knudsen
I'm working on a solution that takes a random passphrase of a user and hashes
it to produce an crypto key, which is then used to encrypt and decrypt.  What
we are finding is that it works on most machines all the time (throws "PKCS7
padding is invalid ..." when invalid passphrase passed - probably not a
perfect check) but not on all of the machines and not all the time. 
Sometimes you can give it a passphrase and the decryption of the encrypted
information will work.  Also, in this case, the decrypted info will be
different than what it should be.  What am I doing wrong?  Why is it
sometimes working on invalid passphrases?  Here's the code:

        public static byte[] Decrypt(byte[] cipherText_, byte[] salt_, byte[] iv_,
string passPhrase_)
        {
            byte[] plainText = new byte[cipherText_.Length];
            byte[] temp;

            using(MemoryStream cipherStream = new MemoryStream(cipherText_))
            {
                //hash password
                PasswordDeriveBytes key = new PasswordDeriveBytes(passPhrase_, salt_,
PasswordDeriveHashName, PasswordDeriveIterations);

                //Encrypt
                SymmetricAlgorithm sa = RijndaelManaged.Create();
                ICryptoTransform decryptor = sa.CreateDecryptor(key.GetBytes(32), iv_);
                CryptoStream cryptoStream = new CryptoStream(cipherStream, decryptor,
CryptoStreamMode.Read);
                int read = cryptoStream.Read(plainText, 0, plainText.Length);
                temp = new byte[read];
                Array.Copy(plainText, 0, temp, 0, read);
            }
            return temp;
        }

Author
6 Apr 2005 5:21 AM
chuck rudolph
Derek, I remember a like question on a web farm. The answer had to do with
the seed value the crypto routines were using to get fired up. The default is
autogenerate which will cause your application to require processor affinity
to work--so it will work on one machine or the other, but it won't span two
machines. The solution was to set the seed value to all the cpus in the web
farm to the same value and that way your app could pick up where it left off
on any cpu. Your description smells like you might be encountering the same
type of issue; but this could be totally wrong because I don't know anything
of Rijndael...Chuck

Show quoteHide quote
"Derek Knudsen" wrote:

> I'm working on a solution that takes a random passphrase of a user and hashes
> it to produce an crypto key, which is then used to encrypt and decrypt.  What
> we are finding is that it works on most machines all the time (throws "PKCS7
> padding is invalid ..." when invalid passphrase passed - probably not a
> perfect check) but not on all of the machines and not all the time. 
> Sometimes you can give it a passphrase and the decryption of the encrypted
> information will work.  Also, in this case, the decrypted info will be
> different than what it should be.  What am I doing wrong?  Why is it
> sometimes working on invalid passphrases?  Here's the code:
>
>         public static byte[] Decrypt(byte[] cipherText_, byte[] salt_, byte[] iv_,
> string passPhrase_)
>         {
>             byte[] plainText = new byte[cipherText_.Length];
>             byte[] temp;
>
>             using(MemoryStream cipherStream = new MemoryStream(cipherText_))
>             {
>                 //hash password
>                 PasswordDeriveBytes key = new PasswordDeriveBytes(passPhrase_, salt_,
> PasswordDeriveHashName, PasswordDeriveIterations);
>
>                 //Encrypt
>                 SymmetricAlgorithm sa = RijndaelManaged.Create();
>                 ICryptoTransform decryptor = sa.CreateDecryptor(key.GetBytes(32), iv_);
>                 CryptoStream cryptoStream = new CryptoStream(cipherStream, decryptor,
> CryptoStreamMode.Read);
>                 int read = cryptoStream.Read(plainText, 0, plainText.Length);
>                 temp = new byte[read];
>                 Array.Copy(plainText, 0, temp, 0, read);
>             }
>             return temp;
>         }
>
>
>
Are all your drivers up to date? click for free checkup

Author
6 Apr 2005 4:09 PM
Derek Knudsen
I was wondering if it was something hardware related!  The test machines we
have are dual-proc, while our dev machines are single proc.  I don't know if
what your saying applies to HT procs as well but I will try turning HT on on
one machine to see if we start seeing the inconsistency.  Thanks, Chuck!

Show quoteHide quote
"chuck rudolph" wrote:

> Derek, I remember a like question on a web farm. The answer had to do with
> the seed value the crypto routines were using to get fired up. The default is
> autogenerate which will cause your application to require processor affinity
> to work--so it will work on one machine or the other, but it won't span two
> machines. The solution was to set the seed value to all the cpus in the web
> farm to the same value and that way your app could pick up where it left off
> on any cpu. Your description smells like you might be encountering the same
> type of issue; but this could be totally wrong because I don't know anything
> of Rijndael...Chuck
>
> "Derek Knudsen" wrote:
>
> > I'm working on a solution that takes a random passphrase of a user and hashes
> > it to produce an crypto key, which is then used to encrypt and decrypt.  What
> > we are finding is that it works on most machines all the time (throws "PKCS7
> > padding is invalid ..." when invalid passphrase passed - probably not a
> > perfect check) but not on all of the machines and not all the time. 
> > Sometimes you can give it a passphrase and the decryption of the encrypted
> > information will work.  Also, in this case, the decrypted info will be
> > different than what it should be.  What am I doing wrong?  Why is it
> > sometimes working on invalid passphrases?  Here's the code:
> >
> >         public static byte[] Decrypt(byte[] cipherText_, byte[] salt_, byte[] iv_,
> > string passPhrase_)
> >         {
> >             byte[] plainText = new byte[cipherText_.Length];
> >             byte[] temp;
> >
> >             using(MemoryStream cipherStream = new MemoryStream(cipherText_))
> >             {
> >                 //hash password
> >                 PasswordDeriveBytes key = new PasswordDeriveBytes(passPhrase_, salt_,
> > PasswordDeriveHashName, PasswordDeriveIterations);
> >
> >                 //Encrypt
> >                 SymmetricAlgorithm sa = RijndaelManaged.Create();
> >                 ICryptoTransform decryptor = sa.CreateDecryptor(key.GetBytes(32), iv_);
> >                 CryptoStream cryptoStream = new CryptoStream(cipherStream, decryptor,
> > CryptoStreamMode.Read);
> >                 int read = cryptoStream.Read(plainText, 0, plainText.Length);
> >                 temp = new byte[read];
> >                 Array.Copy(plainText, 0, temp, 0, read);
> >             }
> >             return temp;
> >         }
> >
> >
> >
Author
7 Apr 2005 7:14 AM
Valery Pryamikov
Hi,
Results that you get is what should be expected. PKCS7 is padding scheme
when each padding byte equal to the number of all padding bytes. I.e. if it
is only 1 byte padding, then padding byte contains 0x01. Decryptor is not
aware of number of padding bytes used. It just checks if it got valid
padding. In case if last byte is 0x01 - decryptor consider it to be valid
one byte padding. But with one byte padding you have about 1/256 probability
that a random AES key would produce 0x01 after decryption. In other words -
if you try many-many attempts to decrypt any cipher with random AES key, at
least one key out of each 256 keys would decrypt one padding byte correctly
and therefore would not report padding error. The plain text in these cases
would be just some random binary garbage.

-Valery.
http://www.harper.no/valery

Show quoteHide quote
"Derek Knudsen" <Derek Knud***@discussions.microsoft.com> wrote in message
news:ED5FB49F-7A60-4F90-9EB9-B70298E39A41@microsoft.com...
> I'm working on a solution that takes a random passphrase of a user and
> hashes
> it to produce an crypto key, which is then used to encrypt and decrypt.
> What
> we are finding is that it works on most machines all the time (throws
> "PKCS7
> padding is invalid ..." when invalid passphrase passed - probably not a
> perfect check) but not on all of the machines and not all the time.
> Sometimes you can give it a passphrase and the decryption of the encrypted
> information will work.  Also, in this case, the decrypted info will be
> different than what it should be.  What am I doing wrong?  Why is it
> sometimes working on invalid passphrases?  Here's the code:
>
> public static byte[] Decrypt(byte[] cipherText_, byte[] salt_, byte[] iv_,
> string passPhrase_)
> {
> byte[] plainText = new byte[cipherText_.Length];
> byte[] temp;
>
> using(MemoryStream cipherStream = new MemoryStream(cipherText_))
> {
> //hash password
> PasswordDeriveBytes key = new PasswordDeriveBytes(passPhrase_, salt_,
> PasswordDeriveHashName, PasswordDeriveIterations);
>
> //Encrypt
> SymmetricAlgorithm sa = RijndaelManaged.Create();
> ICryptoTransform decryptor = sa.CreateDecryptor(key.GetBytes(32), iv_);
> CryptoStream cryptoStream = new CryptoStream(cipherStream, decryptor,
> CryptoStreamMode.Read);
> int read = cryptoStream.Read(plainText, 0, plainText.Length);
> temp = new byte[read];
> Array.Copy(plainText, 0, temp, 0, read);
> }
> return temp;
> }
>
>
>
Author
7 Apr 2005 7:46 AM
Valery Pryamikov
I already answered why you get no padding error reported in my prev. post to
that thread. Here is another thing concerning your use of 256 bit AES key.
First of all this is completely redundant - you just using unnecessary
processor cycles on larger round keys schedule and extra AES round for
nothing. AES is not the weakest link in your program. Do you know that to
match 256 bits key strength you need a really strong and quite random
alphanumeric password of size at least 40 characters? Do you really believe
that someone would be able to remember that kind of password?

And despite some common paranoia - 2^128 is a much bigger number than it
seems. I believe that 128 bit AES is not something we will se broken in our
life time unless some extraordinary breakthrough – like ability to transfer
information with the speed much faster than speed of light and store
information on units of size smaller than size of electrons.

Here are just a few simple calculations:

Electrical signal is conveyed with the speed about 70% of speed of the
light. i.e. 210000000 (10^8.322219295) meters per second;

If you consider two circuits placed on distance of 50 nanometers
(non-existent technology that would not be available in at least next 4-8
years if Moore's law would not choke up during that time), then just for
electrical signal being able to pass between these two circuits 2^128 times
it would take 10^(128/log2(10)+log10(0.00000005)-log10(210000000)) =
8.10196*10^22 seconds or 9.37727*10^17 days (2.56912*10^15 years - much
longer that total existence of the solar system J) ).



Now suppose we talk about latest IBM supercomputer that is able to perform
65 terraflops (65 * 10^9 floating point calculation per second). 2^128 is
about 10^38.5 i.e. 10^29 seconds to perform 2^128 floating point operations
on that supercomputer. The earth surface is about 0.51 * 10^15 square
meters. If we imagine impossible – that such supercomputer has dimensions of
only one cubic meter (while as in reality it takes hundreds times more than
that), then you have to cover whole earth surface including ocean with these
supercomputers almost 200000 times (ie. put 200000 layers of these super
computers on top of each other) to perform that many floating point
operations per one year.

And if you talk about decryption operation - one decryption operation is
many times slower than one floating point operation.



It's very much unlikely that 2^128 operations will be achievable in our
lifetime (unless some extreme breakthroughs would allow us to transmit
information much faster than the speed of light with using some particles
that are much smaller than the size of electrons).





The only concern of people talking about security of 128 bit keys is
birthday paradox that means that with f.e. CBC mode of operations you are
risking to leak information about one plain text block after you transmit
2^64 blocks of data with using single encryption key (i.e.. with 128 bit
blocks its about 10000000 Terabytes of data). If you ask me - I would not be
worry about that.



-Valery.

http://www.harper.no/valery



P.S. here are just a few facts about the Earth:
diameter:10^7 × 1.27 m,
area: 10^15 × 0.510 m2,
volume: 10^21 × 1.1 m3,
density: 10^3 × 5.5 kg/m3 (5.5 g/cm3),
mass: 10^25 × 0.60 kg


Show quoteHide quote
"Derek Knudsen" <Derek Knud***@discussions.microsoft.com> wrote in message
news:ED5FB49F-7A60-4F90-9EB9-B70298E39A41@microsoft.com...
> I'm working on a solution that takes a random passphrase of a user and
> hashes
> it to produce an crypto key, which is then used to encrypt and decrypt.
> What
> we are finding is that it works on most machines all the time (throws
> "PKCS7
> padding is invalid ..." when invalid passphrase passed - probably not a
> perfect check) but not on all of the machines and not all the time.
> Sometimes you can give it a passphrase and the decryption of the encrypted
> information will work.  Also, in this case, the decrypted info will be
> different than what it should be.  What am I doing wrong?  Why is it
> sometimes working on invalid passphrases?  Here's the code:
>
> public static byte[] Decrypt(byte[] cipherText_, byte[] salt_, byte[] iv_,
> string passPhrase_)
> {
> byte[] plainText = new byte[cipherText_.Length];
> byte[] temp;
>
> using(MemoryStream cipherStream = new MemoryStream(cipherText_))
> {
> //hash password
> PasswordDeriveBytes key = new PasswordDeriveBytes(passPhrase_, salt_,
> PasswordDeriveHashName, PasswordDeriveIterations);
>
> //Encrypt
> SymmetricAlgorithm sa = RijndaelManaged.Create();
> ICryptoTransform decryptor = sa.CreateDecryptor(key.GetBytes(32), iv_);
> CryptoStream cryptoStream = new CryptoStream(cipherStream, decryptor,
> CryptoStreamMode.Read);
> int read = cryptoStream.Read(plainText, 0, plainText.Length);
> temp = new byte[read];
> Array.Copy(plainText, 0, temp, 0, read);
> }
> return temp;
> }
>
>
>
Author
24 May 2005 8:14 PM
David Whitchurch-Bennett
I'm not sure if you are having these problems, but I have solved a similar
problem that has been troubling me all afternoon....

1. Check the IV is the same in the decrypt as encrypt (I am sure you already
know this).

2. If you are converting bytes to text using an ASCIIEncoder, or any other
8-bit encoder, it will only convert using 8-bits, i.e. a byte value of 129
will become 1!!

I had this problem because the MSDN sample uses an ASCII encoder! How
annoying!!!!! I hope this helps.

Show quoteHide quote
"Derek Knudsen" wrote:

> I'm working on a solution that takes a random passphrase of a user and hashes
> it to produce an crypto key, which is then used to encrypt and decrypt.  What
> we are finding is that it works on most machines all the time (throws "PKCS7
> padding is invalid ..." when invalid passphrase passed - probably not a
> perfect check) but not on all of the machines and not all the time. 
> Sometimes you can give it a passphrase and the decryption of the encrypted
> information will work.  Also, in this case, the decrypted info will be
> different than what it should be.  What am I doing wrong?  Why is it
> sometimes working on invalid passphrases?  Here's the code:
>
>         public static byte[] Decrypt(byte[] cipherText_, byte[] salt_, byte[] iv_,
> string passPhrase_)
>         {
>             byte[] plainText = new byte[cipherText_.Length];
>             byte[] temp;
>
>             using(MemoryStream cipherStream = new MemoryStream(cipherText_))
>             {
>                 //hash password
>                 PasswordDeriveBytes key = new PasswordDeriveBytes(passPhrase_, salt_,
> PasswordDeriveHashName, PasswordDeriveIterations);
>
>                 //Encrypt
>                 SymmetricAlgorithm sa = RijndaelManaged.Create();
>                 ICryptoTransform decryptor = sa.CreateDecryptor(key.GetBytes(32), iv_);
>                 CryptoStream cryptoStream = new CryptoStream(cipherStream, decryptor,
> CryptoStreamMode.Read);
>                 int read = cryptoStream.Read(plainText, 0, plainText.Length);
>                 temp = new byte[read];
>                 Array.Copy(plainText, 0, temp, 0, read);
>             }
>             return temp;
>         }
>
>
>

Bookmark and Share

Post Thread options