// 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
// 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 {
// 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;
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)
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) {
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"));
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"));
}
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;
}
}
}
// 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];
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;
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;