【问题标题】:My encryption/decryption solution not working properly我的加密/解密解决方案无法正常工作
【发布时间】:2014-07-10 10:14:36
【问题描述】:

我正试图找出我的加密/解密代码出了什么问题,但我似乎在 Google 搜索与我类似的问题时遇到了死胡同。

这是我的两个函数的 php 代码,但我会先解释一下。这些工作原理是使用盐、用户密码和他们上次登录的 unix 纪元时间(如果他们以前从未登录过,则为当前纪元时间)来创建加密密码。

现在我正在测试代码以查看它是否有效,然后再将其连接到我的其余 php 代码中。传递给函数的密码是 Test,它使用 time() 提供时间,然后在加密过程中将该值存储到全局变量中,因此我不必在测试时将其存储到数据库中。

在一个 SO 线程 this one 中,我读到在创建 IV 时使用 MCRYPT_RAND 然后不保存生成的 IV 意味着解密将永远无法工作,因为如果您重新调用 mcrypt_create_iv 来创建 IV,IV 会有所不同在解密过程中。因此,我也为 IV 制作了一个全局变量,并在解密过程中进行了尝试,但它仍然无法正确解密。下面的代码反映了这一变化。

  //Encrypt the user's password for storing in database 
function encrypt($password, $id)
{
    echo "Function: encrypt \n"; //For debugging

    $salt2 = getTime($id);

    $salt1 = 'akey'; //Changed for security purposes

    global $cur_iv;

    $key = substr(hash('sha256',$salt1.$password.$salt2),0,32);
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256,MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size,MCRYPT_RAND);
    $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $password, MCRYPT_MODE_ECB, $iv));

    $cur_iv = $iv;

    echo $encrypted;
    echo "\n";

    global $cur_time;

    $cur_time = $salt2; 

    return $encrypted;
}

//Decrypt the user's password for loggin checking
function decrypt($password,$id)
{
    echo "Function: decrypt \n"; //For debugging

    //$salt2 = getTime($id);
    global $cur_time;
    $salt2 = $cur_time;

    $salt1 = 'akey'; //Changed for security purposes

    global $cur_iv;

    $key = substr(hash('sha256',$salt1.$password.$salt2),0,32);
    $iv = $cur_iv;
    $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($pass), MCRYPT_MODE_ECB, $iv);

    echo $decrypted;
    echo "\n";

    return $decrypted;
}

加密后的密码如下所示:xgr5YB0vHwJAkjkqwTl6rnZMjbZL0qmLE4D8JXDT1rM=

但解密后是这样的:NÞÚ±=º)cz_öUñŽP´è8Åáó»d—+ÒAÐ

编辑 2:

这是 Saikios 要求的 getTime 函数:

//Use the last login time for part of the encryption salt to ensure more secure hashing
function getTime($id)
{
    global $sql;

    echo "Function: getTime \n"; //For debugging

    if ($salt_stmt = $sql->prepare("Select Last_Login From login_log Where User_ID = ?;"))
    {
        $salt_stmt->bind_param('i',$id);
        $salt_stmt->execute();
        $salt_stmt->store_result();
        $salt_stmt->bind_result($time);
        $salt_stmt->fetch();

        if ($salt_stmt->num_rows < 1)
        {
            echo "No last login \n";

            $time = time();
        }

        else
        {   
            echo "Last Login Time: ".$time."\n";            
        }

        return $time;

    }

    else
    {
        echo "Error: ".$sql->error; 
    }
}

【问题讨论】:

  • 你为什么不直接使用password_hash()password_verify()
  • 或者只是将用户输入的密码加密并与数据库中的密码进行比较?
  • 在解密函数中你也有:$salt2 == $cur_time; 所以你是比较两者而不是设置。
  • @JonathanKuhn facepalm 感谢您指出这一点,我现在会解决这个问题。编辑:仍然无法正常工作。
  • 我建议为此使用非对称加密。这样您就可以始终保持一把钥匙的安全。

标签: php mcrypt


【解决方案1】:

这里你可以使用我的,但请不要使用 md5('password') 作为你的密钥 :)

function symEncode($decrypted, $key){
        $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);

        $iv_base64 = rtrim(base64_encode($iv), '=');
        // Encrypt $decrypted and an MD5 of $decrypted using $key.  MD5 is fine to use here because it's just to verify successful decryption.
        $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $decrypted . md5($decrypted), MCRYPT_MODE_CBC, $iv));
        // We're done!
        return $iv_base64 . $encrypted;
    }

function symDecode($encrypted, $key){
    // Retrieve $iv which is the first 43 characters plus ==, base64_decoded.
    $iv = base64_decode(substr($encrypted, 0, 43) . '==');
    // Remove $iv from $encrypted.
    $encrypted = substr($encrypted, 43);
    // Decrypt the data.  rtrim won't corrupt the data because the last 32 characters are the md5 hash; thus any \0 character has to be padding.
    //pre_var_export(debug_backtrace(false));
    $decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($encrypted), MCRYPT_MODE_CBC, $iv), "\0\4");
    // Retrieve $hash which is the last 32 characters of $decrypted.
    $hash = substr($decrypted, -32);
    // Remove the last 32 characters from $decrypted.
    $decrypted = substr($decrypted, 0, -32);
    // Integrity check.  If this fails, either the data is corrupted, or the password/salt was incorrect.
    if (md5($decrypted) != $hash){
        die('failed');
    }
    // Yay!
    return $decrypted;
}


$key = md5('password');
$decrypted = 'some important data';

$encrypted = symEncode($decrypted, $key);
echo $encrypted . '<br>';  
echo symDecode($encrypted, $key);

输出:

43p2K/0RG20fnuHEx2B3q18KM7FpGLRfb+BwFfYt1V1mMr5PsAroum/jEeO6LonmC4T9N6QQQfOfMwTmbyNRFG4Qi5imGPAq0LsbgYJHWZ50Lw0C7uSRDb7CC1I4Uv1/LFQ==

some important data

$key = md5('password');
        $decrypted = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc bibendum augue et vehicula adipiscing. Maecenas interdum, enim a accumsan convallis, est urna posuere mauris, eu ultricies lacus enim at justo. Vestibulum auctor sed elit a';

输出:

431nn42sTg7/XlGw4nAw3aFmMiYOnOQCVMjs4xY2m3DNcgiTFyqs1scG3VCxx/srEV9OGePqD4qrV1AectSqIWCSjYCinsS1jThEL9OuxxXeaGCbycXybdeMUCz1gKJZ5zVegMjqcWzyaX6/32sMs+Mh/NO+e9uh9lOdgmpofHEUWc9m4n6yziX2TllDKxbbADogeRjfW5SzzhaR/bx24kV9/44QhMRA1IJwFteHzCI9qTLGL/586MziGUVbZJe9Y9TqhiWEAIgJ0tO0iWVGMBYV1ibwv8VzDr0LcN7qL4345ryoQ3hjrixpLnBNKewKhbCB/4EkJ7+FD1nUyHOZLEyhi52oMqs/uDv1qSk/Pgk+Poku8DCd5ZbxbAJQG6Wp8BlZzfXOak1tyTKaJUsRziM/zmaXvpYrq3WWJti4cQaxc

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc bibendum augue et vehicula adipiscing. Maecenas interdum, enim a accumsan convallis, est urna posuere mauris, eu ultricies lacus enim at justo. Vestibulum auctor sed elit a

【讨论】:

  • 谢谢,我会试着用它来设计一些东西并试一试。
  • 你在加密什么,不同的加密有不同的用途,任何对称2方式加密的缺陷总是必须有相同的密钥。
  • 这也是我不久前发现的一些修改和更新的代码,虽然我觉得我很擅长这个,但我不知道我是否将它用于导弹代码你知道我的意思,大声笑
【解决方案2】:

我知道你想使用你自己的函数,但你为什么不使用它作为基础(Naveen S. Nayak,不是我http://naveensnayak.wordpress.com/2013/03/12/simple-php-encrypt-and-decrypt/),

function encrypt_decrypt($action, $string) {
    $output = false;

    $encrypt_method = "AES-256-CBC";
    $secret_key = 'This is my secret key';
    $secret_iv = 'This is my secret iv';

    // hash
    $key = hash('sha256', $secret_key);

    // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
    $iv = substr(hash('sha256', $secret_iv), 0, 16);

    if( $action == 'encrypt' ) {
        $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
        $output = base64_encode($output);
    }
    else if( $action == 'decrypt' ){
        $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
    }

    return $output;
}

$plain_txt = "This is my plain text";
echo "Plain Text = $plain_txt\n";

$encrypted_txt = encrypt_decrypt('encrypt', $plain_txt);
echo "Encrypted Text = $encrypted_txt\n";

$decrypted_txt = encrypt_decrypt('decrypt', $encrypted_txt);
echo "Decrypted Text = $decrypted_txt\n";

if( $plain_txt === $decrypted_txt ) echo "SUCCESS";
else echo "FAILED";

echo "\n";

(您如何传递变量似乎有问题)

-----旧---------- 我没有 getTime 函数,但是 ....

关于加密更改

$cur_time = salt2;  

$cur_time = $salt2;

【讨论】:

  • 我会将其添加到 OP,但修复代码的一些问题并没有解决原始问题。
  • @Geowil,OP 表示你。
  • @sectus 我以为 TC 是 Topic Creator 而 OP 是 Original Post?
  • 感谢博客的链接,我也会看看这个,看看我能用它做什么;也许结合你自己和ArtisticPhoenix提出的两种方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-20
  • 2014-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
相关资源
最近更新 更多