2016-09-09 10 views
2

WordPressに移植するメンバーシップシステムを.NETで構築し、PBKDF2暗号化を複製する必要があるため、パスワードをリセットする必要はありません。しかしRfc2898DeriveBytesをPHPに変換するC#PBKDF2

--Salt-- 
5SyOX+Rbclzvvit3MEM2nA== 
--HashedPassword-- 
5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ 
--IsValid-- 
True 

static void Main(string[] args) 
{ 
    var isValid = CheckPassword("#0zEZcD7uNmv", "5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ"); 
} 

public static int PBKDF2IterCount = 10000; 
public static int PBKDF2SubkeyLength = 256/8; // 256 bits 
public static int SaltSize = 128/8; // 128 bits 

private static bool CheckPassword(string Password, string ExistingHashedPassword) 
{ 
    byte[] saltAndPassword = Convert.FromBase64String(ExistingHashedPassword); 
    byte[] salt = new byte[SaltSize]; 

    Array.Copy(saltAndPassword, 0, salt, 0, SaltSize); 

    Console.WriteLine("--Salt--"); 
    Console.WriteLine(Convert.ToBase64String(salt)); 

    string hashedPassword = HashPassword(Password, salt); 

    Console.WriteLine("--HashedPassword--"); 
    Console.WriteLine(hashedPassword); 

    return hashedPassword == ExistingHashedPassword; 
} 

private static string HashPassword(string Password, byte[] salt) 
{ 
    byte[] hash = new byte[PBKDF2SubkeyLength]; 
    using (var pbkdf2 = new Rfc2898DeriveBytes(Password, salt, PBKDF2IterCount)) 
    { 
    hash = pbkdf2.GetBytes(PBKDF2SubkeyLength); 
    } 

    byte[] hashBytes = new byte[PBKDF2SubkeyLength + SaltSize]; 
    Array.Copy(salt, 0, hashBytes, 0, SaltSize); 
    Array.Copy(hash, 0, hashBytes, SaltSize, PBKDF2SubkeyLength); 

    string hashedPassword = Convert.ToBase64String(hashBytes); 
    return hashedPassword; 
} 

コンソールアプリは以下を生成します:私は次のコードを使用して、簡単に.NETでこれを複製することができましたノウハウハッシュされたパスワードを使用して

PHP側では私は同じ結果を得ることはできません。これまでの私のコードは以下の通りです。

$mySalt = base64_decode('5SyOX+Rbclzvvit3MEM2nA=='); 
$dev = pbkdf2('sha1', '#0zEZcD7uNmv', $mySalt, 10000, 48, true); 
$key = substr($dev, 0, 32); //Keylength: 32 
$iv = substr($dev, 32, 16); // IV-length: 16 

echo 'PHP<br/>'; 
echo 'PASS: '.base64_encode($dev).'<br/>'; 
echo 'SALT: '.base64_encode($iv).'<br/><br/>'; 

echo '.NET<br/>'; 
echo 'PASS: 5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ<br/>'; 
echo 'SALT: 5SyOX+Rbclzvvit3MEM2nA==<br/><br/>'; 

function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false) 
{ 
    $algorithm = strtolower($algorithm); 
    if(!in_array($algorithm, hash_algos(), true)) 
     die('PBKDF2 ERROR: Invalid hash algorithm.'); 
    if($count <= 0 || $key_length <= 0) 
     die('PBKDF2 ERROR: Invalid parameters.'); 

    $hash_length = strlen(hash($algorithm, "", true)); 
    $block_count = ceil($key_length/$hash_length); 

    $output = ""; 
    for($i = 1; $i <= $block_count; $i++) { 
     // $i encoded as 4 bytes, big endian. 
     $last = $salt . pack("N", $i); 
     // first iteration 
     $last = $xorsum = hash_hmac($algorithm, $last, $password, true); 
     // perform the other $count - 1 iterations 
     for ($j = 1; $j < $count; $j++) { 
      $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true)); 
     } 
     $output .= $xorsum; 
    } 
    return substr($output, 0, $key_length); 
} 

そして結果は以下のとおりです。

PHP 
PASS: FFo9WjYztlOzuffOddN/Jbg6HBOUku+lxSUKvJuWCRCsYe+1Tgbb8Ob4FtxumMal 
SALT: rGHvtU4G2/Dm+BbcbpjGpQ== 

.NET 
PASS: 5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ 
SALT: 5SyOX+Rbclzvvit3MEM2nA== 

任意の助けをいただければ幸いです。

+0

、http://php.net/manual/en/function.hash-pbkdf2.php – ArtisticPhoenix

+0

@ArtisticPhoenixありがとう、カスタムメソッドのためにそれを切り替えると、結果はまったく同じ結果になりました。これはコードを単純化しても、残念なことに同じ問題を抱えていることは素晴らしいです。 – philba888

+0

もう一つの問題は '$ iv'を印刷してSALTというラベルを付けることです。次に、strlenが適切かどうか質問します。しかし、.NETが文字列パスワードをUTF-8経由でバイトに変換することは難しいでしょう。 PHPがUCS-2またはUTF-16を使用する場合、バイナリのHMACキーは同じではありません。 – bartonjs

答えて

2

https://github.com/defuse/password-hashingライブラリを使用して作業を終了しました。マイナーな変更がハッシュのフォーマットと一致しました。インポート中のデータベースで作業していました。

しかし、私の主な問題は、私がハッシュからキーを取得しようとしているこれらの行にありました。

$dev = pbkdf2('sha1', '#0zEZcD7uNmv', $mySalt, 10000, 48, true); 
$key = substr($dev, 0, 32); //Keylength: 32 
$iv = substr($dev, 32, 16); // IV-length: 16 

これを32ビット長のハッシュハッシュを作成して、塩に戻すハッシュを結合することで問題が解決されました。今マッチング.NET以下の出力で

$dev = pbkdf2('sha1', '#0zEZcD7uNmv', $mySalt, 10000, 32, true); 
echo 'PASS: '.base64_encode($mySalt.$dev).'<br />'; 

:あなたはおそらくこれを試みることができる

PASS: 5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ 
関連する問題