[corlib] Parse datetime string using culture calendar. Fixes #18052
[mono.git] / mcs / class / corlib / System.Security.Cryptography / PasswordDeriveBytes.cs
index 9e50b07be87057569b63093a0b1000a841520bf4..80a1dbeead1776cffba2738d31df3710c0aee4b1 100644 (file)
@@ -5,11 +5,7 @@
 //     Sebastien Pouliot (sebastien@ximian.com)
 //
 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// (C) 2004 Novell (http://www.novell.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2007 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
@@ -31,8 +27,8 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-using System;
 using System.Globalization;
+using System.Runtime.InteropServices;
 using System.Text;
 
 namespace System.Security.Cryptography {
@@ -43,6 +39,7 @@ namespace System.Security.Cryptography {
 // b.  IETF RFC2898: PKCS #5: Password-Based Cryptography Specification Version 2.0
 //     http://www.rfc-editor.org/rfc/rfc2898.txt
 
+[ComVisible (true)]
 public class PasswordDeriveBytes : DeriveBytes {
 
        private string HashNameValue;
@@ -56,17 +53,19 @@ public class PasswordDeriveBytes : DeriveBytes {
        private byte[] output;
        private int position;
        private int hashnumber;
-       private int globalPos;
 
        public PasswordDeriveBytes (string strPassword, byte[] rgbSalt) 
        {
-               Prepare (strPassword, rgbSalt, "SHA1", 1);
+               Prepare (strPassword, rgbSalt, "SHA1", 100);
        }
 
        public PasswordDeriveBytes (string strPassword, byte[] rgbSalt, CspParameters cspParams) 
        {
-               throw new NotSupportedException (
-                       Locale.GetText ("CspParameters not supported by Mono"));
+               Prepare (strPassword, rgbSalt, "SHA1", 100);
+               if (cspParams != null) {
+                       throw new NotSupportedException (
+                               Locale.GetText ("CspParameters not supported by Mono for PasswordDeriveBytes."));
+               }
        }
 
        public PasswordDeriveBytes (string strPassword, byte[] rgbSalt, string strHashName, int iterations) 
@@ -76,11 +75,43 @@ public class PasswordDeriveBytes : DeriveBytes {
 
        public PasswordDeriveBytes (string strPassword, byte[] rgbSalt, string strHashName, int iterations, CspParameters cspParams) 
        {
-               throw new NotSupportedException (
-                       Locale.GetText ("CspParameters not supported by Mono"));
+               Prepare (strPassword, rgbSalt, strHashName, iterations);
+               if (cspParams != null) {
+                       throw new NotSupportedException (
+                               Locale.GetText ("CspParameters not supported by Mono for PasswordDeriveBytes."));
+               }
+       }
+
+       public PasswordDeriveBytes (byte[] password, byte[] salt) 
+       {
+               Prepare (password, salt, "SHA1", 100);
+       }
+
+       public PasswordDeriveBytes (byte[] password, byte[] salt, CspParameters cspParams) 
+       {
+               Prepare (password, salt, "SHA1", 100);
+               if (cspParams != null) {
+                       throw new NotSupportedException (
+                               Locale.GetText ("CspParameters not supported by Mono for PasswordDeriveBytes."));
+               }
+       }
+
+       public PasswordDeriveBytes (byte[] password, byte[] salt, string hashName, int iterations) 
+       {
+               Prepare (password, salt, hashName, iterations);
        }
 
-       ~PasswordDeriveBytes () 
+       public PasswordDeriveBytes (byte[] password, byte[] salt, string hashName, int iterations, CspParameters cspParams) 
+       {
+               Prepare (password, salt, hashName, iterations);
+               if (cspParams != null) {
+                       throw new NotSupportedException (
+                               Locale.GetText ("CspParameters not supported by Mono for PasswordDeriveBytes."));
+               }
+       }
+
+#if NET_4_0
+       protected override void Dispose (bool disposing)
        {
                // zeroize buffer
                if (initial != null) {
@@ -88,21 +119,42 @@ public class PasswordDeriveBytes : DeriveBytes {
                        initial = null;
                }
                // zeroize temporary password storage
-               Array.Clear (password, 0, password.Length);
+               if (password != null) {
+                       Array.Clear (password, 0, password.Length);
+                       password = null;
+               }
+               base.Dispose (disposing);
        }
+#endif
 
        private void Prepare (string strPassword, byte[] rgbSalt, string strHashName, int iterations) 
        {
-               HashNameValue = strHashName;
-               SaltValue = rgbSalt;
-               IterationsValue = iterations;
-               state = 0;
-               password = Encoding.UTF8.GetBytes (strPassword);
+               if (strPassword == null)
+                       throw new ArgumentNullException ("strPassword");
+
+               byte[] pwd = Encoding.UTF8.GetBytes (strPassword);
+               Prepare (pwd, rgbSalt, strHashName, iterations);
+               Array.Clear (pwd, 0, pwd.Length);
        }
 
+       private void Prepare (byte[] password, byte[] rgbSalt, string strHashName, int iterations)
+       {
+               if (password == null)
+                       throw new ArgumentNullException ("password");
+
+               this.password = (byte[]) password.Clone ();
+
+               Salt = rgbSalt;
+
+               HashName = strHashName;
+               IterationCount = iterations;
+               state = 0;
+       }
        public string HashName {
                get { return HashNameValue; } 
                set {
+                       if (value == null)
+                               throw new ArgumentNullException ("HashName");
                        if (state != 0) {
                                throw new CryptographicException (
                                        Locale.GetText ("Can't change this property at this stage"));
@@ -114,6 +166,8 @@ public class PasswordDeriveBytes : DeriveBytes {
        public int IterationCount {
                get { return IterationsValue; }
                set {
+                       if (value < 1)
+                               throw new ArgumentOutOfRangeException ("> 0", "IterationCount");
                        if (state != 0) {
                                throw new CryptographicException (
                                        Locale.GetText ("Can't change this property at this stage"));
@@ -123,18 +177,20 @@ public class PasswordDeriveBytes : DeriveBytes {
        }
 
        public byte[] Salt {
-               get { return (byte[]) SaltValue.Clone ();  }
+               get { 
+                       if (SaltValue == null)
+                               return null;
+                       return (byte[]) SaltValue.Clone ();
+               }
                set {
                        if (state != 0) {
                                throw new CryptographicException (
                                        Locale.GetText ("Can't change this property at this stage"));
                        }
-
-// For Fx 1.0/1.1 compatibility
-//                     if (value != null)
+                       if (value != null)
                                SaltValue = (byte[]) value.Clone ();
-//                     else
-//                             SaltValue = null;
+                       else
+                               SaltValue = null;
                }
        }
 
@@ -149,16 +205,20 @@ public class PasswordDeriveBytes : DeriveBytes {
        }
 
        // note: Key is returned - we can't zeroize it ourselve :-(
+       [Obsolete ("see Rfc2898DeriveBytes for PKCS#5 v2 support")]
+ #pragma warning disable 809
        public override byte[] GetBytes (int cb) 
        {
+ #pragma warning restore 809
+
                if (cb < 1)
                        throw new IndexOutOfRangeException ("cb");
 
                if (state == 0) {
-                       state = 1;
                        // it's now impossible to change the HashName, Salt
                        // and IterationCount
                        Reset ();
+                       state = 1;
                }
 
                byte[] result = new byte [cb];
@@ -196,7 +256,8 @@ public class PasswordDeriveBytes : DeriveBytes {
                                        Locale.GetText ("too long"));
                        }
 
-                       int l = Math.Min (cb - cpos, output2.Length);
+                       int rem = output2.Length - position;
+                       int l = Math.Min (cb - cpos, rem);
                        Buffer.BlockCopy (output2, position, result, cpos, l);
                        cpos += l;
                        position += l;
@@ -204,15 +265,13 @@ public class PasswordDeriveBytes : DeriveBytes {
                                position -= output2.Length;
                                hashnumber++;
                        }
-                       globalPos += l;
                }
                return result;
        }
 
        public override void Reset () 
        {
-               // note: Reset doesn't change state
-               globalPos = 0;
+               state = 0;
                position = 0;
                hashnumber = 0;