0

With a bit of help from people on here, i've converted the following PHP functions to C# - But I get very different results between the two and can't work out where i've gone wrong:

PHP:

  function randomKey($amount)
        {
                $keyset  = "abcdefghijklmABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
                $randkey = "";
                for ($i=0; $i<$amount; $i++)
                        $randkey .= substr($keyset, rand(0, strlen($keyset)-1), 1);
                return $randkey;       
        }

        public static function hashPassword($password)
        {
                $salt = self::randomKey(self::SALTLEN);
                $site = new Sites();
                $s = $site->get();
                return self::hashSHA1($s->siteseed.$password.$salt.$s->siteseed).$salt;
        }

c#

public static string randomKey(int amount)
        {
            string keyset = "abcdefghijklmABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            string randkey = string.Empty;
            Random random = new Random();

            for (int i = 0; i < amount; i++)
            {
                randkey += keyset.Substring(0, random.Next(2, keyset.Length - 2));
            }

            return randkey;
        }

        static string hashPassword(string password)
        {
            string salt = randomKey(4);
            string siteSeed = "6facef08253c4e3a709e17d9ff4ba197";
            return CalculateSHA1(siteSeed + password + salt + siteSeed) + siteSeed;
        }


        static string CalculateSHA1(string ipString)
        {
            SHA1 sha1 = new SHA1CryptoServiceProvider();
            byte[] ipBytes = Encoding.Default.GetBytes(ipString.ToCharArray());
            byte[] opBytes = sha1.ComputeHash(ipBytes);

            StringBuilder stringBuilder = new StringBuilder(40);
            for (int i = 0; i < opBytes.Length; i++)
            {
                stringBuilder.Append(opBytes[i].ToString("x2"));
            }

            return stringBuilder.ToString();
        }

EDIT The string 'password' in the PHP function comes out as

"d899d91adf31e0b37e7b99c5d2316ed3f6a999443OZl" 

in the c# it comes out as:

"905d25819d950cf73f629fc346c485c819a3094a6facef08253c4e3a709e17d9ff4ba197"
5
  • This is not an efficient way to generate random strings or hash password .... Commented Jun 27, 2013 at 16:08
  • How are the results different? Given that there's pseudorandomness involved, it's not surprising that you wouldn't get the same exact results. Which function is not returning the values that you expect? Commented Jun 27, 2013 at 16:13
  • What are the very different results you're getting? Commented Jun 27, 2013 at 16:13
  • I've added an example of the different results above. This is when i call String x = hashPassword(txtPassword.Text); Commented Jun 27, 2013 at 16:16
  • You should seriously consider reading the selected answer on this SO post. stackoverflow.com/questions/1054022/… Commented Jun 27, 2013 at 16:25

1 Answer 1

1

You're not using salts correctly, or you're not hashing correctly.

If you salt your data before you hash it, which is good practice, you have to store the salt you used.

The use case is:

A user signs up with your service. They give you a password. You generate a new salt, hash their password with the salt, and then store the hash and the salt.

The user later attempts to log in. You look up the salt you used when they signed up, and then perform the hash again using the same salt. If the hash of the password from the login attempt matches the hash stored in the database, you can authenticate them.

Right now, every time you call hashPassword you hash with a completely new salt because you keep invoking your salt generator. This won't ever work.

You've got other problems too.

When you're creating salts, you use a new instance of Random every single invocation. new Random() without any parameters uses the system time as the seed, and the system time only changes every 10-15 milliseconds. If you do that in a tight loop, it's going to generate the same random value a bunch of times in a row.

Either: create a Random singleton that is constructed once when your program is first started, or use a seed to Random that is going to change constantly. Alternatively, especially since you're implementing security, use a cryptographic-quality random number generator : RNGCryptoServiceProvider

You may also want to use SecureString in your implementation, since that user's password is sitting in memory in the application: SecureString. Yes, you will have to resolve the SecureString to a regular string at some point but SecureString can help prevent the total time that the password is in plain text in memory.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.