在插入数据库时​​切断哈希字符串

时间:2013-04-03 18:42:24

标签: php mysql pdo bcrypt password-encryption

我有一个奇怪的问题。我将发布两段代码,希望能够清楚地表达我的问题。以下代码根据用户输入的密码创建哈希,我使用的是hmac和bcrypt:

if(isset($_POST['username'])){
    $username = preg_replace('#[^a-z0-9]#i', '', $_POST['username']);
    $email1 = strip_tags($_POST['email1']);
    $email2 = strip_tags($_POST['email2']);
    $pass1 = strip_tags($_POST['pass1']);
    $pass2 = strip_tags($_POST['pass2']);
    // make sure no fields are blank /////
    if(trim($username) == "" || trim($email1) == "" || trim($pass1) == "" || trim($pass2) == ""){
        echo "Error: All fields are required. Please press back in your browser and try again.";
        $db = null;
        exit();
    }
    /// Make sure both email fields match /////
    if($email1 != $email2){
        echo "Your email fields do not match. Press back and try again";
        exit();
    }
    //// Make sure both password fields match ////
    else if($pass1 != $pass2){
        echo "Your password fields do not match. Press back and try again";
        exit();
    }
    //// create the hmac /////
    $hmac = hash_hmac('sha512', $pass1, file_get_contents('my/path/to/key.txt'));
    //// create random bytes for salt ////
    $bytes = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
    //// Create salt and replace + with . ////
    $salt = strtr(base64_encode($bytes), '+', '.');
    //// make sure our bcrypt hash is 22 characters which is the required length ////
    $salt = substr($salt, 0, 22);
    //// This is the hashed password to store in the db ////
    $bcrypt = crypt($hmac, '$2y$12$' . $salt);
        echo $bcrypt;

此代码工作正常,并创建一个类似于以下内容的哈希:

  

$ 2Y $ 12 $ Oysi / 5oZjF4vlUYx4PvgJ.GSpAQb7njNzSTUnEy / QOFzPxqRpHFV6

我遇到的问题是在执行一些错误处理然后插入数据后,哈希密码被切断了。只是因为你知道我存储它的字段最初被设置为VARCHAR(255),我甚至将它改为TEXT但它仍然被切断了。以下是我刚刚回复上述密码的其余代码:

//// Create token for activation script ////
    $token = md5($bcrypt);
    //// query to check if email is in the db already ////
    $stmt = $db->prepare("SELECT email FROM members WHERE email=:email1 LIMIT 1");
    $stmt->bindValue(':email1',$email1,PDO::PARAM_STR);
    try{
    $stmt->execute();
    $count = $stmt->rowCount();
    }
    catch(PDOException $e){
        echo $e->getMessage();
            $db = null;
            exit();
    }
    //// query to check if the username is in the db already ////
    $unameSQL = $db->prepare("SELECT username FROM members WHERE username=:username LIMIT 1");
    $unameSQL->bindValue('username',$username,PDO::PARAM_STR);
    try{
        $unameSQL->execute();
        $unCount = $unameSQL->rowCount();
    }
    catch(PDOException $e){
        echo $e->getMessage();
        $db = null;
        exit();
    }
    ///Check if email is in the db already ////
    if($count > 0){
        echo "Sorry, that email is already in use in the system";
        $db = null;
        exit();
    }
    //// Check if username is in the db already ////
    if($unCount > 0){
        echo "Sorry, that username is already in use in the system";
        $db = null;
        exit();
    }
    try{
        $db->beginTransaction();
        $ipaddress = getenv('REMOTE_ADDR');
        $stmt2 = $db->prepare("INSERT INTO members (username, email, password, signup_date, ipaddress) VALUES (:username, :email1, :bcrypt, now(), :ipaddress)");
        $stmt2->bindParam(':username', $username, PDO::PARAM_STR);
        $stmt2->bindParam(':email1',$email1,PDO::PARAM_STR);
        $stmt2->bindParam(':bcrypt',$bcrypt,PDO::PARAM_STR);
        $stmt2->bindParam(':ipaddress',$ipaddress,PDO::PARAM_INT);
        $stmt2->execute();
        /// Get the last id inserted to the db which is now this users id for activation and member folder creation ////
        $lastId = $db->lastInsertId();
        $stmt3 = $db->prepare("INSERT INTO activate (user, token) VALUES ('$lastId', :token)");
        $stmt3->bindValue(':token',$token,PDO::PARAM_STR);
        $stmt3->execute();
        //// Send email activation to the new user ////
        $from = "From: Auto Resposder @ GotCode <admin@gotcode.org>";
        $subject = "IMPORTANT: Activate your gotCode account";
        $link = 'http://www.gotcode.org/activate.php?user='.$lastId.'&token='.$token.'';
        //// Start Email Body ////
        $message = "
Thanks for registering an account at gotCode.org! Were glad you decided to join us in this wacky adventure.
Theres just one last step to set up your account. Please click the link below to confirm your identity and get started.
If the link below is not active please copy and paste it into your browser address bar. See you on the site!

$link
";
        //// Set headers ////
        $headers = 'MIME-Version: 1.0' . "rn";
        $headers .= "Content-type: textrn";
        $headers .= "From: $fromrn";
        /// Send the email now ////
        mail($email1, $subject, $message, $headers, '-f noreply@mywebsite.org');
        $db->commit();
        echo "Thanks for joining! Check your email in a few moments to activate your account so that you may log in. See you on the site!<br />$bcrypt<br />$hmac<br />$salt<br />$token"; 
        exit();
        $db = null;
        exit();
    }
        catch(PDOException $e){
            $db->rollBack();
            echo $e->getMessage();
            $db = null;
            exit();
        }
}

其余代码也可以将数据插入到数据库中,并且我的电子邮件激活也会被发送出去。问题是现在散列密码存储在数据库中,如下所示:

  

$ 2hm7KFNCFyfM

我很难弄清楚为什么当我只是按照预期回显哈希密码时它是一个很好的长哈希字符串但是在错误检查和插入数据库后它被切断了。也许一组额外的眼睛可以发现我的错误?非常感谢!

1 个答案:

答案 0 :(得分:0)

好的......我必须做的就是解决这个问题,从5.2升级我的php版本。

更具体地说明问题所在:对于PHP&lt; 5.3使用blowfish算法时,应使用

  

$ 2A $

大于PHP 5.2使用

  

$ $ 2Y

换句话说,如果不更新我的php版本,修复此问题的方法就是更改此行:

$bcrypt = crypt($hmac, '$2y$12$' . $salt);

对此:

$bcrypt = crypt($hmac, '$2a$12$' . $salt);

万一有人遇到同样的问题:)