【问题标题】:how to encrypt / decrypt password with salt using libsodium php如何使用 libsodium php 用盐加密/解密密码
【发布时间】:2017-10-23 05:13:24
【问题描述】:

我想要得到的是

  • 用 libsodium 加密密码 + 盐
  • 将其存储到数据库中
  • 读取并解密(取回纯密码进行身份验证)

我得到了我想用来加密/解密我的密码的盐的列表。 当我加密密码时,我得到一个哈希值,这样一个似乎可以工作,但在解密时我总是得到 false 作为返回值。

我是否使用了错误的方法来使用 libsodium 进行加密/解密,还是我完全走错了方向?

我的加密/解密来源:

function encrypt_libsodium($to_encrypt, $salt_to_use){
        if(!$data || !$salt_to_use){
            return null;
        }

        //get stored salt
        $this->key_ = substr(md5($this->pw_key[$salt_to_use].'_'), 0, $this->ks);

        //some libsodium specific stuff
        $out_len = \Sodium\CRYPTO_SIGN_SEEDBYTES;
        $ops_limit = \Sodium\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE;
        $mem_limit =\Sodium\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE;

        //create hash using libsodium
        $hash = \Sodium\crypto_pwhash($out_len, $to_encrypt, $this->key_,$ops_limit, $mem_limit);
        return $hash;
    }

    function decrypt_libsodium($hash, $salt_to_use){
        if(!$hash || !$what){
            return null;
        }

        //get stored salt
        $this->key_ = substr(md5($this->pw_key[$salt_to_use].'_'), 0, $this->ks);

        //get verification hash
        $decrypted = \Sodium\crypto_pwhash_scryptsalsa208sha256_str_verify($this->key_, $hash);
        return $decrypted;
    }

感谢您的帮助!

问候多姆

【问题讨论】:

  • HASH 不(假定)是可逆的,所以您所能做的就是以相同的方式对纯文本密码进行哈希处理并比较 HASH
  • 那么解释一下为什么需要能够转换为明文进行身份验证?
  • 我有一个密码来进行身份验证,并希望将其加密存储在我的本地数据库中,但我需要它来进行身份验证。
  • 你的“本地加密数据库”就像 KeePassX 一样?
  • 不,我的数据库是一个简单的 mysql 数据库。我的意思是将我的加密密码存储到本地数据库。

标签: php hash passwords salt libsodium


【解决方案1】:

看起来你正在尝试混合许多不相关的东西。 CRYPTO_SIGN_SEEDBYTES 用于签名,与密码哈希无关,crypto_pwhash 不使用 scrypt 算法,因此 CRYPTO_PWHASH_SCRYPTSALSA208SHA256_* 常量不适用,我不确定 md5() 在这里做了什么.而且您可能想对密码进行哈希处理,而不是对其进行加密。

无论如何,crypto_pwhash_str() 函数可以满足您的一切需求。它创建一个盐,对密码进行哈希处理,并将结果(连同盐、算法及其参数)编码为可以直接存储到数据库中的字符串:

$password = 'correct horse battery staple';
$h = \Sodium\crypto_pwhash_str($password,                                   
         \Sodium\CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
         \Sodium\CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE);

$h 是您需要存储在数据库中的所有内容。

然后,验证数据库中的内容对于给定密码是否有效:

if (\Sodium\crypto_pwhash_str_verify($h, $password) === FALSE) {
    // wrong password!
}

【讨论】:

  • 感谢您的帮助,这让事情变得更清楚了。是否也可以再次解密存储的密码?因为我需要它来进行身份验证。
  • 密码没有加密,它们是散列的。可以验证给定密码是否正确,但考虑到数据库中的内容,查找密码需要付出很多努力。如果密码被加密,您的应用程序中的漏洞可能允许攻击者检索整个密码列表,立即可用。请不要存储用户密码,即使使用您的应用程序知道的密钥进行加密。
  • 是的,您在这里缺少对散列、加密和密码验证意味着什么的基本理解......所以散列是一种单向过程。要“验证”,您获取用户键入的内容,然后对其进行哈希处理并将其与数据库中密码的哈希版本进行比较。您永远不想“解密”或“取消哈希”数据库中的内容。 “nonce”意味着散列的特定算法对于数据库中的每个密码都是不同的。这很好,因为它可以阻止某些类型的攻击。
【解决方案2】:

如果你不需要专门使用libsodium,通过这个功能你应该可以将加密的数据存储在数据库中并解密。

define("ENCRYPT_METHOD", "AES-256-CBC");
define("SECRET_KEY","randomtextrandomtextforthesecretkey");
define("SECRET_IV", "randomtextforthesecretiv");
function encriptar($action, $string)
{
  $output = false;
  $key    = hash("sha256", SECRET_KEY);
  $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 = base64_decode($string);
        $output = openssl_decrypt($output, ENCRYPT_METHOD, $key, 0, $iv);
    }
  return $output;
}

输出将是您将存储/获取到数据库的数据。

【讨论】:

  • 这可能对我有用,因为我想做的就是找到一个更新版本的 mcrypt,因为那个已经被贬低了。我想使用 libsodium,因为我读了很多帖子说 libsodium 是加密/解密的最佳方式。我想只要我不让钠工作,我就会和 openssl 一起生活。
猜你喜欢
  • 1970-01-01
  • 2021-07-23
  • 2016-04-09
  • 2015-02-10
  • 1970-01-01
  • 1970-01-01
  • 2014-01-24
  • 2017-03-10
  • 2014-11-30
相关资源
最近更新 更多