2006-11-16 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / Test / System.Security.Cryptography / PasswordDeriveBytesTest.cs
index 0ff24ad42510829a65f4cbad53b65b675e76b777..c9525db76536919049ced2455914ec157e5c3711 100644 (file)
@@ -5,7 +5,26 @@
 //     Sebastien Pouliot (sebastien@ximian.com)
 //
 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// (C) 2004 Novell (http://novell.com)
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
 using NUnit.Framework;
@@ -19,14 +38,263 @@ namespace MonoTests.System.Security.Cryptography {
 //     http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html
 
 [TestFixture]
-public class PasswordDeriveBytesTest : Assertion {
+public class PasswordDeriveBytesTest {
+
+       static byte[] salt = { 0xDE, 0xAD, 0xC0, 0xDE };
+       static string ssalt = "DE-AD-C0-DE";
+
+       // Constructors
 
-       public void AssertEquals (string msg, byte[] array1, byte[] array2)
+       [Test]
+#if NET_2_0
+       [ExpectedException (typeof (ArgumentNullException))]
+#endif
+       public void Ctor_PasswordNullSalt ()
        {
-               AllTests.AssertEquals (msg, array1, array2);
+               string pwd = null;
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes (pwd, salt);
        }
 
-       static byte[] salt = { 0xDE, 0xAD, 0xC0, 0xDE };
+       [Test]
+       public void Ctor_PasswordSaltNull ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", null);
+               Assert.AreEqual ("SHA1", pdb.HashName, "HashName");
+               Assert.AreEqual (100, pdb.IterationCount, "IterationCount");
+               Assert.IsNull (pdb.Salt, "Salt");
+       }
+
+       [Test]
+       public void Ctor_PasswordSalt ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt);
+               Assert.AreEqual ("SHA1", pdb.HashName, "HashName");
+               Assert.AreEqual (100, pdb.IterationCount, "IterationCount");
+               Assert.AreEqual (ssalt, BitConverter.ToString (pdb.Salt), "Salt");
+       }
+
+       [Test]
+#if NET_2_0
+       [ExpectedException (typeof (ArgumentNullException))]
+#else
+       [Category ("NotWorking")] // CspParameters aren't supported by Mono (requires CryptoAPI)
+#endif
+       public void Ctor_PasswordNullSaltCspParameters ()
+       {
+               string pwd = null;
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes (pwd, salt, new CspParameters ());
+       }
+
+       [Test]
+       [Category ("NotWorking")] // CspParameters aren't supported by Mono (requires CryptoAPI)
+       public void Ctor_PasswordSaltNullCspParameters ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", null, new CspParameters ());
+               Assert.AreEqual ("SHA1", pdb.HashName, "HashName");
+               Assert.AreEqual (100, pdb.IterationCount, "IterationCount");
+               Assert.IsNull (pdb.Salt, "Salt");
+       }
+
+       [Test]
+       public void Ctor_PasswordSaltCspParametersNull ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, null);
+               Assert.AreEqual ("SHA1", pdb.HashName, "HashName");
+               Assert.AreEqual (100, pdb.IterationCount, "IterationCount");
+               Assert.AreEqual (ssalt, BitConverter.ToString (pdb.Salt), "Salt");
+       }
+
+       [Test]
+       [Category ("NotWorking")] // CspParameters aren't supported by Mono (requires CryptoAPI)
+       public void Ctor_PasswordSaltCspParameters ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, new CspParameters ());
+               Assert.AreEqual ("SHA1", pdb.HashName, "HashName");
+               Assert.AreEqual (100, pdb.IterationCount, "IterationCount");
+               Assert.AreEqual (ssalt, BitConverter.ToString (pdb.Salt), "Salt");
+       }
+
+       [Test]
+#if NET_2_0
+       [ExpectedException (typeof (ArgumentNullException))]
+#endif
+       public void Ctor_PasswordNullSaltHashIteration ()
+       {
+               string pwd = null;
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes (pwd, salt, "SHA1", 1);
+       }
+
+       [Test]
+       public void Ctor_PasswordSaltNullHashIteration ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", null, "SHA1", 1);
+               Assert.AreEqual ("SHA1", pdb.HashName, "HashName");
+               Assert.AreEqual (1, pdb.IterationCount, "IterationCount");
+               Assert.IsNull (pdb.Salt, "Salt");
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentNullException))]
+       public void Ctor_PasswordSaltHashNullIteration ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, null, 1);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentOutOfRangeException))]
+       public void Ctor_PasswordSaltHashIterationNegative ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, "SHA1", -1);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentOutOfRangeException))]
+       public void Ctor_PasswordSaltHashIterationZero ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, "SHA1", 0);
+       }
+
+       [Test]
+       public void Ctor_PasswordSaltHashIterationMaxValue ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, "SHA1", Int32.MaxValue);
+               Assert.AreEqual ("SHA1", pdb.HashName, "HashName");
+               Assert.AreEqual (Int32.MaxValue, pdb.IterationCount, "IterationCount");
+               Assert.AreEqual (ssalt, BitConverter.ToString (pdb.Salt), "Salt");
+       }
+
+       [Test]
+       public void Ctor_PasswordSaltHashIteration ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, "SHA1", 1);
+               Assert.AreEqual ("SHA1", pdb.HashName, "HashName");
+               Assert.AreEqual (1, pdb.IterationCount, "IterationCount");
+               Assert.AreEqual (ssalt, BitConverter.ToString (pdb.Salt), "Salt");
+       }
+
+       [Test]
+#if NET_2_0
+       [ExpectedException (typeof (ArgumentNullException))]
+#else
+       [Category ("NotWorking")] // CspParameters aren't supported by Mono (requires CryptoAPI)
+#endif
+       public void Ctor_PasswordNullSaltHashIterationCspParameters ()
+       {
+               string pwd = null;
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes (pwd, salt, "SHA1", 1, new CspParameters ());
+       }
+
+       [Test]
+       [Category ("NotWorking")] // CspParameters aren't supported by Mono (requires CryptoAPI)
+       public void Ctor_PasswordSaltNullHashIterationCspParameters ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", null, "SHA1", 1, new CspParameters ());
+               Assert.AreEqual ("SHA1", pdb.HashName, "HashName");
+               Assert.AreEqual (1, pdb.IterationCount, "IterationCount");
+               Assert.IsNull (pdb.Salt, "Salt");
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentNullException))]
+       public void Ctor_PasswordSaltHashNullIterationCspParameters ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, null, 1, new CspParameters ());
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentOutOfRangeException))]
+       public void Ctor_PasswordSaltHashIterationNegativeCspParameters ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, "SHA1", -1, new CspParameters ());
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentOutOfRangeException))]
+       public void Ctor_PasswordSaltHashIterationZeroCspParameters ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, "SHA1", 0, new CspParameters ());
+       }
+
+       [Test]
+       [Category ("NotWorking")] // CspParameters aren't supported by Mono (requires CryptoAPI)
+       public void Ctor_PasswordSaltHashIterationMaxValueCspParameters ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, "SHA1", Int32.MaxValue, new CspParameters ());
+               Assert.AreEqual ("SHA1", pdb.HashName, "HashName");
+               Assert.AreEqual (Int32.MaxValue, pdb.IterationCount, "IterationCount");
+               Assert.AreEqual (ssalt, BitConverter.ToString (pdb.Salt), "Salt");
+       }
+
+       [Test]
+       public void Ctor_PasswordSaltHashIterationCspParametersNull ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, "SHA1", 1, null);
+               Assert.AreEqual ("SHA1", pdb.HashName, "HashName");
+               Assert.AreEqual (1, pdb.IterationCount, "IterationCount");
+               Assert.AreEqual (ssalt, BitConverter.ToString (pdb.Salt), "Salt");
+       }
+
+       [Test]
+       [Category ("NotWorking")] // CspParameters aren't supported by Mono (requires CryptoAPI)
+       public void Ctor_PasswordSaltHashIterationCspParameters ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, "SHA1", 1, new CspParameters ());
+               Assert.AreEqual ("SHA1", pdb.HashName, "HashName");
+               Assert.AreEqual (1, pdb.IterationCount, "IterationCount");
+               Assert.AreEqual (ssalt, BitConverter.ToString (pdb.Salt), "Salt");
+       }
+
+       // Properties
+
+       [Test]
+       [ExpectedException (typeof (ArgumentNullException))]
+       public void Property_HashName_Null ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, "SHA1", 1);
+               Assert.AreEqual ("SHA1", pdb.HashName, "HashName");
+               pdb.HashName = null;
+       }
+
+       [Test]
+#if !NET_2_0
+       // Fixed in 2.0 beta 1
+       [ExpectedException (typeof (NullReferenceException))]
+#endif
+       public void Property_Salt ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt);
+               Assert.AreEqual (ssalt, BitConverter.ToString (pdb.Salt), "Salt");
+               pdb.Salt = null;
+               Assert.IsNull (pdb.Salt, "Salt");
+       }
+
+       [Test]
+       public void Property_Salt_Modify ()
+       {
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt);
+               Assert.AreEqual (ssalt, BitConverter.ToString (pdb.Salt), "Salt");
+               pdb.Salt [0] = 0xFF;
+               // modification rejected (the property returned a copy of the salt)
+               Assert.AreEqual (ssalt, BitConverter.ToString (pdb.Salt), "Salt");
+       }
+
+       // 1.0/1.1 compatibility
+
+#if !NET_2_0
+       // 1.0/1.1 accepted a null password as valid - but throw the 
+       // ArgumentNullException when GetBytes is called
+       // byte stream from the null input. Check that we can do the same...
+       [Test]
+       [ExpectedException (typeof (ArgumentNullException))]
+       public void GetBytes_PasswordNull ()
+       {
+               string pwd = null;
+               PasswordDeriveBytes pdb = new PasswordDeriveBytes (pwd, salt);
+               pdb.GetBytes (24);
+       }
+#endif
+
+       // Old tests
 
        static int ToInt32LE(byte [] bytes, int offset)
        {
@@ -46,7 +314,7 @@ public class PasswordDeriveBytesTest : Assertion {
                                        break;
                                }
                        }
-                       Assert (msg + " #" + j, compare);
+                       Assert.IsTrue (compare, msg + " #" + j);
                        pd.Reset ();
                }
        }
@@ -60,7 +328,7 @@ public class PasswordDeriveBytesTest : Assertion {
                for (int i=0; i < iter; i++) {
                        pass = pd.GetBytes (bloc);
                }
-               AssertEquals (msg, pass, finalKey);
+               Assert.AreEqual (pass, finalKey, msg);
        }
 
        public void Run (string password, byte[] salt, string hashname, int iterations, int getbytes, int lastFourBytes) 
@@ -72,7 +340,7 @@ public class PasswordDeriveBytesTest : Assertion {
                msg += ", hash=" + hashname;
                msg += ", iter=" + iterations;
                msg += ", get=" + getbytes + "]";
-               AssertEquals (msg, lastFourBytes, ToInt32LE (key, key.Length - 4));
+               Assert.AreEqual (lastFourBytes, ToInt32LE (key, key.Length - 4), msg);
        }
 
        [Test]
@@ -89,18 +357,18 @@ public class PasswordDeriveBytesTest : Assertion {
                
                // this should work (we check the last four devired bytes to be sure)
                byte[] key = pd.GetBytes (size);
-               AssertEquals ("Last 4 bytes", lastFourBytes, ToInt32LE (key, size - 4));
+               Assert.AreEqual (lastFourBytes, ToInt32LE (key, size - 4), "Last 4 bytes");
 
                // but we can't get another byte from it!
                try {
                        key = pd.GetBytes (1);
-                       Fail ("Expected CryptographicException but got none");
+                       Assert.Fail ("Expected CryptographicException but got none");
                }
                catch (CryptographicException) {
                        // LAMESPEC: no limit is documented
                }
                catch (Exception e) {
-                       Fail ("Expected CryptographicException but got " + e.ToString ());
+                       Assert.Fail ("Expected CryptographicException but got " + e.ToString ());
                }
        }
 
@@ -270,13 +538,12 @@ public class PasswordDeriveBytesTest : Assertion {
                for (int i=0; i < iter; i++) {
                        pass = pd.GetBytes (bloc);
                }
-               AssertEquals (msg, pass, key);
+               Assert.AreEqual (pass, key, msg);
        }
 
        [Test]
        public void SHA1SaltShortRun ()
        {
-               byte[] salt = { 0xDE, 0xAD, 0xC0, 0xDE };
                byte[] key = { 0x0B, 0x61, 0x93, 0x96, 0x3A, 0xFF, 0x0D, 0xFC, 0xF6, 0x3D, 0xA3, 0xDB, 0x34, 0xC2, 0x99, 0x71, 0x69, 0x11, 0x61, 0xB5 };
                PasswordDeriveBytes pd = new PasswordDeriveBytes ("password", salt, "SHA1", 1);
                string msg = "PKCS#5 password salt SHA1 (1)";
@@ -286,7 +553,6 @@ public class PasswordDeriveBytesTest : Assertion {
        [Test]
        public void SHA1SaltLongRun () 
        {
-               byte[] salt = { 0xDE, 0xAD, 0xC0, 0xDE };
                byte[] key = { 0x91, 0xDA, 0xF9, 0x9D, 0x7C, 0xA9, 0xB4, 0x42, 0xB8, 0xD9, 0x45, 0xAB, 0x69, 0xEE, 0x12, 0xBC, 0x48, 0xDD, 0x38, 0x74 };
                PasswordDeriveBytes pd = new PasswordDeriveBytes ("password", salt, "SHA1", 1);
                string msg = "PKCS#5-Long password salt SHA1 (1)";
@@ -314,7 +580,6 @@ public class PasswordDeriveBytesTest : Assertion {
        [Test]
        public void MD5SaltShortRun ()
        {
-               byte[] salt = { 0xDE, 0xAD, 0xC0, 0xDE };
                byte[] key = { 0xA5, 0x4D, 0x4E, 0xDD, 0x3A, 0x59, 0xAC, 0x98, 0x08, 0xDA, 0xE7, 0xF2, 0x85, 0x2F, 0x7F, 0xF2 };
                PasswordDeriveBytes pd = new PasswordDeriveBytes ("mono", salt, "MD5", 100);
                string msg = "PKCS#5 mono salt MD5 (100)";
@@ -324,7 +589,6 @@ public class PasswordDeriveBytesTest : Assertion {
        [Test]
        public void MD5SaltLongRun () 
        {
-               byte[] salt = { 0xDE, 0xAD, 0xC0, 0xDE };
                byte[] key = { 0x92, 0x51, 0x4D, 0x10, 0xE1, 0x5F, 0xA8, 0x44, 0xEF, 0xFC, 0x0F, 0x1F, 0x6F, 0x3E, 0x40, 0x36 };
                PasswordDeriveBytes pd = new PasswordDeriveBytes ("mono", salt, "MD5", 100);
                string msg = "PKCS#5-Long mono salt MD5 (100)";
@@ -352,93 +616,93 @@ public class PasswordDeriveBytesTest : Assertion {
        [Test]
        public void Properties () 
        {
-               byte[] salt = { 0xDE, 0xAD, 0xC0, 0xDE };
                // create object...
                PasswordDeriveBytes pd = new PasswordDeriveBytes ("password", null, "MD5", 1000);
-               AssertEquals ("HashName-MD5", "MD5", pd.HashName);
-               AssertEquals ("IterationCount-1000", 1000, pd.IterationCount);
+               Assert.AreEqual ("MD5", pd.HashName, "HashName-MD5");
+               Assert.AreEqual (1000, pd.IterationCount, "IterationCount-1000");
                // ...then change all its properties...
                pd.HashName = "SHA1";
-               AssertEquals ("HashName-SHA1", "SHA1", pd.HashName);
+               Assert.AreEqual ("SHA1", pd.HashName, "HashName-SHA1");
                pd.Salt = salt;
-               AssertEquals ("Salt", "DE-AD-C0-DE", BitConverter.ToString (pd.Salt));
+               Assert.AreEqual (ssalt, BitConverter.ToString (pd.Salt), "Salt");
                pd.IterationCount = 1;
-               AssertEquals ("IterationCount-1", 1, pd.IterationCount);
+               Assert.AreEqual (1, pd.IterationCount, "IterationCount-1");
                byte[] expectedKey = { 0x0b, 0x61, 0x93, 0x96 };
                // ... before using it
-               AssertEquals ("PKCS#5 test properties", expectedKey, pd.GetBytes (4));
+               Assert.AreEqual (expectedKey, pd.GetBytes (4), "PKCS#5 test properties");
                // it should work but if we try to set any properties after GetBytes
                // they should all throw an exception
                try {
                        pd.HashName = "SHA256";
-                       Fail ("PKCS#5 can't set HashName after GetBytes - expected CryptographicException but got none");
+                       Assert.Fail ("PKCS#5 can't set HashName after GetBytes - expected CryptographicException but got none");
                }
                catch (CryptographicException) {
                        // do nothing, this is what we expect
                }
                catch (Exception e) {
-                       Fail ("PKCS#5 can't set HashName after GetBytes - expected CryptographicException but got " + e.ToString ());
+                       Assert.Fail ("PKCS#5 can't set HashName after GetBytes - expected CryptographicException but got " + e.ToString ());
                }
                try {
                        pd.Salt = expectedKey;
-                       Fail ("PKCS#5 can't set Salt after GetBytes - expected CryptographicException but got none");
+                       Assert.Fail ("PKCS#5 can't set Salt after GetBytes - expected CryptographicException but got none");
                }
                catch (CryptographicException) {
                        // do nothing, this is what we expect
                }
                catch (Exception e) {
-                       Fail ("PKCS#5 can't set Salt after GetBytes - expected CryptographicException but got " + e.ToString ());
+                       Assert.Fail ("PKCS#5 can't set Salt after GetBytes - expected CryptographicException but got " + e.ToString ());
                }
                try {
                        pd.IterationCount = 10;
-                       Fail ("PKCS#5 can't set IterationCount after GetBytes - expected CryptographicException but got none");
+                       Assert.Fail ("PKCS#5 can't set IterationCount after GetBytes - expected CryptographicException but got none");
                }
                catch (CryptographicException) {
                        // do nothing, this is what we expect
                }
                catch (Exception e) {
-                       Fail ("PKCS#5 can't set IterationCount after GetBytes - expected CryptographicException but got " + e.ToString ());
+                       Assert.Fail ("PKCS#5 can't set IterationCount after GetBytes - expected CryptographicException but got " + e.ToString ());
                }
                // same thing after Reset
                pd.Reset ();
                try {
                        pd.HashName = "SHA256";
-                       Fail ("PKCS#5 can't set HashName after Reset - expected CryptographicException but got none");
+                       Assert.Fail ("PKCS#5 can't set HashName after Reset - expected CryptographicException but got none");
                }
                catch (CryptographicException) {
                        // do nothing, this is what we expect
                }
                catch (Exception e) {
-                       Fail ("PKCS#5 can't set HashName after Reset - expected CryptographicException but got " + e.ToString ());
+                       Assert.Fail ("PKCS#5 can't set HashName after Reset - expected CryptographicException but got " + e.ToString ());
                }
                try {
                        pd.Salt = expectedKey;
-                       Fail ("PKCS#5 can't set Salt after Reset - expected CryptographicException but got none");
+                       Assert.Fail ("PKCS#5 can't set Salt after Reset - expected CryptographicException but got none");
                }
                catch (CryptographicException) {
                        // do nothing, this is what we expect
                }
                catch (Exception e) {
-                       Fail ("PKCS#5 can't set Salt after Reset - expected CryptographicException but got " + e.ToString ());
+                       Assert.Fail ("PKCS#5 can't set Salt after Reset - expected CryptographicException but got " + e.ToString ());
                }
                try {
                        pd.IterationCount = 10;
-                       Fail ("PKCS#5 can't set IterationCount after Reset - expected CryptographicException but got none");
+                       Assert.Fail ("PKCS#5 can't set IterationCount after Reset - expected CryptographicException but got none");
                }
                catch (CryptographicException) {
                        // do nothing, this is what we expect
                }
                catch (Exception e) {
-                       Fail ("PKCS#5 can't set IterationCount after Reset - expected CryptographicException but got " + e.ToString ());
+                       Assert.Fail ("PKCS#5 can't set IterationCount after Reset - expected CryptographicException but got " + e.ToString ());
                }
        }
 
        // FIXME: should we treat this as a bug or as a feature ?
        [Test]
+#if ! NET_2_0
        [ExpectedException (typeof (NullReferenceException))]
+#endif
        public void StrangeBehaviour ()
        {
-               byte[] salt = { 0xDE, 0xAD, 0xC0, 0xDE };
                // create object with a salt...
                PasswordDeriveBytes pd = new PasswordDeriveBytes ("password", salt, "MD5", 1000);
                // ...then change the salt to null
@@ -452,6 +716,21 @@ public class PasswordDeriveBytesTest : Assertion {
                PasswordDeriveBytes pd = new PasswordDeriveBytes ("password", null, "MD5", 1000);
                pd.CryptDeriveKey ("AlgName", "MD5", 256, new byte [8]);
        }
+
+       [Test]
+       [Category ("NotWorking")] // bug #79499
+       public void LongMultipleGetBytes ()
+       {
+               // based on http://bugzilla.ximian.com/show_bug.cgi?id=79499
+               PasswordDeriveBytes pd = new PasswordDeriveBytes ("mono", new byte[20]);
+               string key = BitConverter.ToString (pd.GetBytes (32));
+               Assert.AreEqual ("88-0A-AE-0A-41-61-02-78-FD-E2-70-9F-25-13-14-28-1F-C7-D9-72-9A-AE-CA-3F-BD-31-B4-F0-BD-8E-5B-98", key, "key");
+               string iv = BitConverter.ToString (pd.GetBytes (16));
+               Assert.AreEqual ("FD-E2-70-9F-25-13-14-28-4D-3F-9B-F8-EE-AA-95-ED", iv, "iv");
+               pd.Reset ();
+               // bytes from 32-40 are different from calling GetBytes separately
+               Assert.AreEqual (key + "-F6-55-6C-3E-54-8B-F3-73-4D-3F-9B-F8-EE-AA-95-ED", BitConverter.ToString (pd.GetBytes (48)), "same");
+       }
 }
 
 }