Hack Forums
[C#] pbkdf2-sha256 implementation in C# - Printable Version

+- Hack Forums (https://hackforums.net)
+-- Forum: Tech (https://hackforums.net/forumdisplay.php?fid=444)
+--- Forum: Coding (https://hackforums.net/forumdisplay.php?fid=151)
+---- Forum: Software Development (https://hackforums.net/forumdisplay.php?fid=118)
+---- Thread: [C#] pbkdf2-sha256 implementation in C# (/showthread.php?tid=5249050)



pbkdf2-sha256 implementation in C# - morphine1337 - Apr 25, 2016

Hello, i need a method to hash a string so it will give me the same output as
PHP Code

<?php 
hash_pbkdf2
('SHA256', $key, $salt, 1000, 32); 
from php.
I know it has to do with Rfc2898DeriveBytes but i cant make it work


* - GuRuHaX - Apr 25, 2016

A small example of Rfc2898DeriveBytes :

PHP Code

<?php 
public static string HashPassword(string password)
   {
       
// Generate the hash, with an automatic 32 byte salt
       
Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, 32);
       
rfc2898DeriveBytes.IterationCount = 10000;
       
byte[] hash = rfc2898DeriveBytes.GetBytes(20);
       
byte[] salt = rfc2898DeriveBytes.Salt;
       
//Return the salt and the hash
       
return Convert.ToBase64String(salt) + "|" + Convert.ToBase64String(hash);
   } 

Another example :
( Source : https://cmatskas.com/-net-password-hashing-using-pbkdf2/ )

PHP Code

<?php 
public class PasswordHash
{
    public const 
int SaltByteSize = 24;
    public const 
int HashByteSize = 20; // to match the size of the PBKDF2-HMAC-SHA-1 hash 
    
public const int Pbkdf2Iterations = 1000;
    public const 
int IterationIndex = 0;
    public const 
int SaltIndex = 1;
    public const 
int Pbkdf2Index = 2;

    public static 
string HashPassword(string password)
    {
        var 
cryptoProvider = new RNGCryptoServiceProvider();
        
byte[] salt = new byte[SaltByteSize];
        
cryptoProvider.GetBytes(salt);

        var 
hash = GetPbkdf2Bytes(password, salt, Pbkdf2Iterations, HashByteSize);
        return 
Pbkdf2Iterations + ":" +
               
Convert.ToBase64String(salt) + ":" +
               
Convert.ToBase64String(hash);
    }

    public static 
bool ValidatePassword(string password, string correctHash)
    {
        
char[] delimiter = { ':' };
        var 
split = correctHash.Split(delimiter);
        var 
iterations = Int32.Parse(split[IterationIndex]);
        var 
salt = Convert.FromBase64String(split[SaltIndex]);
        var 
hash = Convert.FromBase64String(split[Pbkdf2Index]);

        var 
testHash = GetPbkdf2Bytes(password, salt, iterations, hash.Length);
        return 
SlowEquals(hash, testHash);
    }

    private static 
bool SlowEquals(byte[] a, byte[] b)
    {
        var 
diff = (uint)a.Length ^ (uint)b.Length;
        for (
int i = 0; i < a.Length && i < b.Length; i++)
        {
            
diff |= (uint)(a[i] ^ b[i]);
        }
        return 
diff == 0;
    }
        
    private static 
byte[] GetPbkdf2Bytesstring password, byte[] salt, int iterations, int outputBytes)
    {
        var 
pbkdf2 = new Rfc2898DeriveBytes(password, salt);
        
pbkdf2.IterationCount = iterations;
        return 
pbkdf2.GetBytes(outputBytes);
    }
} 

You can find an example here :

http://lockmedown.com/hash-right-implementing-pbkdf2-net/

Hope this helps !

🤝


* - morphine1337 - Apr 25, 2016

I know how to use Rfc2898DeriveBytes. But its default algorithm for hashing is sha1 and i need sha256. So my question is: how to use Rfc2898DeriveBytes with another hashing algo, specifically sha256 ?


* - GuRuHaX - Apr 25, 2016

(Apr 25, 2016 10:24 AM)morphine1337 Wrote:  I know how to use Rfc2898DeriveBytes. But its default algorithm for hashing is sha1 and i need sha256. So my question is: how to use Rfc2898DeriveBytes with another hashing algo, specifically sha256 ?

Rfc2898DeriveBytes is unfortunately not configurable to use a different hash function as far that i know of, so you'll have to make your own functionality.

This is what i found doing a little search :

PHP Code

<?php 
// NOTE: The iteration count should
// be as high as possible without causing
// unreasonable delay.  Note also that the password
// and salt are byte arrays, not strings.  After use,
// the password and salt should be cleared (with Array.Clear)
public static byte[] PBKDF2Sha256GetBytes(int dklen, byte[] password, byte[] salt, int iterationCount){
    
using(var hmac=new System.Security.Cryptography.HMACSHA256(password)){
        
int hashLength=hmac.HashSize/8;
        if((
hmac.HashSize&7)!=0)
            
hashLength++;
        
int keyLength=dklen/hashLength;
        if((
long)dklen>(0xFFFFFFFFL*hashLength) || dklen<0)
            throw new 
ArgumentOutOfRangeException("dklen");
        if(
dklen%hashLength!=0)
            
keyLength++;
        
byte[] extendedkey=new byte[salt.Length+4];
        
Buffer.BlockCopy(salt,0,extendedkey,0,salt.Length);
        
using(var ms=new System.IO.MemoryStream()){
            for(
int i=0;i<keyLength;i++){
                
extendedkey[salt.Length]=(byte)(((i+1)>>24)&0xFF);
                
extendedkey[salt.Length+1]=(byte)(((i+1)>>16)&0xFF);
                
extendedkey[salt.Length+2]=(byte)(((i+1)>>8)&0xFF);
                
extendedkey[salt.Length+3]=(byte)(((i+1))&0xFF);
                
byte[] u=hmac.ComputeHash(extendedkey);
                Array.
Clear(extendedkey,salt.Length,4);
                
byte[] f=u;
                for(
int j=1;j<iterationCount;j++){
                    
u=hmac.ComputeHash(u);
                    for(
int k=0;k<f.Length;k++){
                        
f[k]^=u[k];
                    }
                }
                
ms.Write(f,0,f.Length);
                Array.
Clear(u,0,u.Length);
                Array.
Clear(f,0,f.Length);
            }
            
byte[] dk=new byte[dklen];
            
ms.Position=0;
            
ms.Read(dk,0,dklen);
            
ms.Position=0;
            for(
long i=0;i<ms.Length;i++){
                
ms.WriteByte(0);
            }
            Array.
Clear(extendedkey,0,extendedkey.Length);
            return 
dk;
        }
    } 

You could also use Bouncy Castle. The C# specification lists the algorithm "PBEwithHmacSHA-256", which can only be PBKDF2 with SHA-256.

🤝


* - idb. - Apr 25, 2016

http://stackoverflow.com/a/18649357 is source for the above code. Just want to make sure author gets proper credit.