2012-02-08 17 views
1

こんにちはに対するプレーンテキストのパスワードを認証し、お読みいただきありがとうございました、はmd5ハッシュ

私は、CMS /フロントエンドとしてのjoomlaを持っているMySQLデータベースに格納されているパスワードに対して、UN/PWのペアを認証するためのタスクを持っています。

JoomlaのWebアプリケーションは言っデータベースにユーザ名とパスワードを格納し、新しいユーザーを保存するとき、それは、次の手順を経るように思われるサポート -

$salt = JUserHelper::genRandomPassword(32); 
$crypt = JUserHelper::getCryptedPassword($array['password'], $salt); 
$array['password'] = $crypt.':'.$salt; 

genRandomPasswordがどのように見える -

/** 
* Generate a random password 
* 
* @static 
* @param int  $length Length of the password to generate 
* @return string   Random Password 
* @since 1.5 
*/ 
public static function genRandomPassword($length = 8) 
{ 
    $salt = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    $len = strlen($salt); 
    $makepass = ''; 

    $stat = @stat(__FILE__); 
    if (empty($stat) || !is_array($stat)) $stat = array(php_uname()); 

    mt_srand(crc32(microtime() . implode('|', $stat))); 

    for ($i = 0; $i < $length; $i ++) { 
     $makepass .= $salt[mt_rand(0, $len -1)]; 
    } 

    return $makepass; 
} 

最後に、getCryptedPasswordとgetSaltは次のようになります。 -

/** 
* Formats a password using the current encryption. 
* 
* @access public 
* @param string $plaintext The plaintext password to encrypt. 
* @param string $salt  The salt to use to encrypt the password. [] 
*        If not present, a new salt will be 
*        generated. 
* @param string $encryption The kind of pasword encryption to use. 
*        Defaults to md5-hex. 
* @param boolean $show_encrypt Some password systems prepend the kind of 
*        encryption to the crypted password ({SHA}, 
*        etc). Defaults to false. 
* 
* @return string The encrypted password. 
*/ 
public static function getCryptedPassword($plaintext, $salt = '', $encryption = 'md5-hex', $show_encrypt = false) 
{ 
    // Get the salt to use. 
    $salt = JUserHelper::getSalt($encryption, $salt, $plaintext); 

    // Encrypt the password. 
    switch ($encryption) 
    { 
     case 'plain' : 
      return $plaintext; 

     case 'sha' : 
      $encrypted = base64_encode(mhash(MHASH_SHA1, $plaintext)); 
      return ($show_encrypt) ? '{SHA}'.$encrypted : $encrypted; 

     case 'crypt' : 
     case 'crypt-des' : 
     case 'crypt-md5' : 
     case 'crypt-blowfish' : 
      return ($show_encrypt ? '{crypt}' : '').crypt($plaintext, $salt); 

     case 'md5-base64' : 
      $encrypted = base64_encode(mhash(MHASH_MD5, $plaintext)); 
      return ($show_encrypt) ? '{MD5}'.$encrypted : $encrypted; 

     case 'ssha' : 
      $encrypted = base64_encode(mhash(MHASH_SHA1, $plaintext.$salt).$salt); 
      return ($show_encrypt) ? '{SSHA}'.$encrypted : $encrypted; 

     case 'smd5' : 
      $encrypted = base64_encode(mhash(MHASH_MD5, $plaintext.$salt).$salt); 
      return ($show_encrypt) ? '{SMD5}'.$encrypted : $encrypted; 

     case 'aprmd5' : 
      $length = strlen($plaintext); 
      $context = $plaintext.'$apr1$'.$salt; 
      $binary = JUserHelper::_bin(md5($plaintext.$salt.$plaintext)); 

      for ($i = $length; $i > 0; $i -= 16) { 
       $context .= substr($binary, 0, ($i > 16 ? 16 : $i)); 
      } 
      for ($i = $length; $i > 0; $i >>= 1) { 
       $context .= ($i & 1) ? chr(0) : $plaintext[0]; 
      } 

      $binary = JUserHelper::_bin(md5($context)); 

      for ($i = 0; $i < 1000; $i ++) { 
       $new = ($i & 1) ? $plaintext : substr($binary, 0, 16); 
       if ($i % 3) { 
        $new .= $salt; 
       } 
       if ($i % 7) { 
        $new .= $plaintext; 
       } 
       $new .= ($i & 1) ? substr($binary, 0, 16) : $plaintext; 
       $binary = JUserHelper::_bin(md5($new)); 
      } 

      $p = array(); 
      for ($i = 0; $i < 5; $i ++) { 
       $k = $i +6; 
       $j = $i +12; 
       if ($j == 16) { 
        $j = 5; 
       } 
       $p[] = JUserHelper::_toAPRMD5((ord($binary[$i]) << 16) | (ord($binary[$k]) << 8) | (ord($binary[$j])), 5); 
      } 

      return '$apr1$'.$salt.'$'.implode('', $p).JUserHelper::_toAPRMD5(ord($binary[11]), 3); 

     case 'md5-hex' : 
     default : 
      $encrypted = ($salt) ? md5($plaintext.$salt) : md5($plaintext); 
      return ($show_encrypt) ? '{MD5}'.$encrypted : $encrypted; 
    } 
} 

/** 
* Returns a salt for the appropriate kind of password encryption. 
* Optionally takes a seed and a plaintext password, to extract the seed 
* of an existing password, or for encryption types that use the plaintext 
* in the generation of the salt. 
* 
* @access public 
* @param string $encryption The kind of pasword encryption to use. 
*       Defaults to md5-hex. 
* @param string $seed  The seed to get the salt from (probably a 
*       previously generated password). Defaults to 
*       generating a new seed. 
* @param string $plaintext The plaintext password that we're generating 
*       a salt for. Defaults to none. 
* 
* @return string The generated or extracted salt. 
*/ 
public static function getSalt($encryption = 'md5-hex', $seed = '', $plaintext = '') 
{ 
    // Encrypt the password. 
    switch ($encryption) 
    { 
     case 'crypt' : 
     case 'crypt-des' : 
      if ($seed) { 
       return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 2); 
      } else { 
       return substr(md5(mt_rand()), 0, 2); 
      } 
      break; 

     case 'crypt-md5' : 
      if ($seed) { 
       return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 12); 
      } else { 
       return '$1$'.substr(md5(mt_rand()), 0, 8).'$'; 
      } 
      break; 

     case 'crypt-blowfish' : 
      if ($seed) { 
       return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 16); 
      } else { 
       return '$2$'.substr(md5(mt_rand()), 0, 12).'$'; 
      } 
      break; 

     case 'ssha' : 
      if ($seed) { 
       return substr(preg_replace('|^{SSHA}|', '', $seed), -20); 
      } else { 
       return mhash_keygen_s2k(MHASH_SHA1, $plaintext, substr(pack('h*', md5(mt_rand())), 0, 8), 4); 
      } 
      break; 

     case 'smd5' : 
      if ($seed) { 
       return substr(preg_replace('|^{SMD5}|', '', $seed), -16); 
      } else { 
       return mhash_keygen_s2k(MHASH_MD5, $plaintext, substr(pack('h*', md5(mt_rand())), 0, 8), 4); 
      } 
      break; 

     case 'aprmd5' : 
      /* 64 characters that are valid for APRMD5 passwords. */ 
      $APRMD5 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; 

      if ($seed) { 
       return substr(preg_replace('/^\$apr1\$(.{8}).*/', '\\1', $seed), 0, 8); 
      } else { 
       $salt = ''; 
       for ($i = 0; $i < 8; $i ++) { 
        $salt .= $APRMD5 { 
         rand(0, 63) 
         }; 
       } 
       return $salt; 
      } 
      break; 

     default : 
      $salt = ''; 
      if ($seed) { 
       $salt = $seed; 
      } 
      return $salt; 
      break; 
    } 
} 

私はPHPやJoomlaのエキスパートですが、私はある程度は何が起こっているのか理解しています。私は、暗号化アルゴリズムが行われる限り、md5が使用されていると信じています。

私の質問は -

私はこのように保存されたパスワードに対する国連/ PWコンボを認証するために行うには何が必要ですか?現在のところ、塩はPWと一緒に保管されていないので、ここで正確に何をする必要がありますか?私はコードや擬似コードは必要ありません。私は踏み出すステップの明確なリストが必要です。コードを提供したいと思ったら、Javaでアプリケーションを書いています。

EDIT - 私はさらに彼らもすべてhasing /復号化を経た後にマッチしていないと言っているが私が使用している認証ライブラリに塩/暗号パスワードを供給得ている

わかりました。私はもう少しこれで周りを遊ばなければならないと思う。

Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken - TestUser, rememberMe=false] did not match the expected credentials. 

私は思うよ -

SimpleAuthenticationInfo info = new SimpleAuthenticationInfo("TestUser", 
      "564c6d2c10a7135fe0ddf0b21d1a1226", getName()); 
    info.setCredentialsSalt(new SimpleByteSource("B9YEkhvnV8pZ8BU7fvVlIVTbEux5N17J")); 


    return info; 

そして、これは私が得る応答である:私は以下のコメントに供給PWは、ここに私のJavaコードは次のようになります。その例を使用して

私はまだそこにいません。 getCryptedPassword PHP関数にアルゴリズム名を渡すわけではないので、MD5のように見えるデフォルトを使用していると推測しています。私はなぜこれが動作していないのだろうか。

は、

-Zacharyカーター

+0

もう一度見てから、塩がコロンで区切られたパスワードと並べて保存されていると思います。例えば、パスワードが 564c6d2c10a7135fe0ddf0b21d1a1226のようになります。B9YEkhvnV8pZ8BU7fvVlIVTbEux5N17J ので、私はB9YEkhvnV8pZ8BU7fvVlIVTbEux5N17Jが塩であることを推測しています。私はまだこれに対して認証するために何をする必要があるのか​​という点で、より多くの説明を使用することができます。 –

+0

それを取り除く。平らなmd5は、塩でさえも吸う。 – CodesInChaos

+0

非常に有用なコメントではありません。データベースやフロントエンドのWebアプリケーションを設定していないため、ユーザーを認証しようとしています。 –

答えて

1

Joomlaはプレーンテキストのpw + saltとしてハッシュを構築していましたが、Shiroが認証するとハッシュをsalt + plain-text pwとして構築します。解決策は、SimpleCredentialsMatcherとAbstractHashをサブクラス化することでした。それらはすべて保護されていたので、既存のサブクラスのメソッドをオーバーライドできませんでした。

1

ありがとうこれを試してみてください。

jimport('joomla.user.helper'); 
$userId = JUserHelper::getUserId($un); 
$user = JUser::getInstance($userId); 

$existingPasswordParts = explode(':', $user->password); 
$salt = $existingPasswordParts[1]; 
$crypt = JUserHelper::getCryptedPassword($pw, $salt); 
$password = $crypt . ':' . $salt; 

if ($user->password == $password) 
{ 
    /* match */ 
} 

ユーザーがフェッチされ、そして使用される塩は、プレーンテキストのパスワードを暗号化するために再利用されます。

は、ユーザー名$unとプレーンテキストのパスワード$pwを考えます。その後、両方の暗号化されたパスワードを互いに比較することができます。 これはJ1.6、J1.7、J2.5で動作するはずです。

+0

私は何かを読んだことがありますか?私は、PHPではなくJavaでこれを行う必要があると言いました。 –

+0

さて、お詫び申し上げます。私は "Joomla"を読んで、すべてのPHPコードを見たとき、私は正確に読み終わったと思います。 Java同等のコードが機能しない場合は、MD5関数を使用している可能性が非常に高いです。これはjavaとPHPの違いがあります。 – parvus

+0

私の答えで説明したように、Apache Shiroは、Jommlaがハッシュ(salt + plain-textpw)vsハッシュ(plain-text + salt)と逆の順序でハッシュを実行していたという問題がありました。 –

関連する問題