Web开发/ PHP:您应该何时/不应该使用加密安全令牌?

时间:2014-12-31 14:26:52

标签: php security token

使用PHP创建加密安全令牌的标准方法似乎是:

$token = bin2hex(openssl_random_pseudo_bytes(16));

我理解你是否正在使用Linux(我总是这样做),因为它使用/ dev / urandom - 根据操作系统中发生的所有事情而改变 - 这使得它几乎无法预测

我的功能更像是这样,所以我可以通过字符长度而不是长度来实现(虽然我不会真正使用它,见下文):

function token($charLength = 32) {

    // Each byte produces 2 hexadecimal characters so bit length should be half the char length
    $bitLength = $charLength / 2;

    // Generate token
    $token = bin2hex(openssl_random_pseudo_bytes($bitLength));

    return $token;

}

这种不可预测性是否安全?我无法帮助他们认为较少安全,因为输出是十六进制的,因此比具有相同数量的字符串的字符串更难以猜测或暴力。其余的字母,大写字母,其他符号等。

这是为什么当人们提到令牌时他们指的是比特长度而不是字符长度?

改为考虑:

function randomString($length,
                      $alpha = true,
                      $alphau = true,
                      $numeric = true,
                      $specialChars = '') {

    $string = $specialChars;

    if($alpha === true) {

        $string .= 'abcdefghijklmnopqrstuvwxyz';

    }

    if($alphau === true) {

        $string .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

    }

    if($numeric === true) {

        $string .= '0123456789';

    }

    $array      = str_split($string);
    $string     = '';

    for($counter = 0; $counter < $length; $counter ++) {

        $string .= $array[array_rand($array)];

    }

    return $string;

}

在Web开发的上下文中,您何时将第一个函数用于第二个函数:

  1. 为密码重置创建随机密码
  2. 创建一次性使用令牌(例如,忘记密码链接)
  3. 为密码哈希创建一个salt(例如bcrypt,sha512,PBKDF2)
  4. 为“记住我”Cookie令牌创建令牌
  5. 在所有情况下,我都会使用randomString()而不是token(),所以我想我是否以及在上述任何一种情况下我是否错了。

    关于以上几点的理由:

    1. 12个字符随机密码,大写,小写和数字很难猜到;加上我在5次登录尝试失败后冻结了15分钟
    2. 64 char随机字符串,如果有人试图强制令牌重置密码,防火墙就会接收它。
    3. 无论如何,盐应该被认为是公开的,只要它们的密码不同就不可能生成彩虹表
    4. 我记得我的令牌是存储在一个cookie中的128个字符随机字符串,并且在数据库中被加盐并且是512

1 个答案:

答案 0 :(得分:1)

随机数生成器的主要关注点通常不是创建的输出,而是生成此数据的可预测性。您的基本问题是为什么不在openssl_random_pseudo_bytes上使用array_rand(内部使用php_rand)进行加密。答案与每个函数采用的技术有关,array_rand是一种更可预测(并且可重现)的方法。请参阅PádraicBrady的文章“在PHP中预测随机数 - 它比您想象的更容易!”更多详情:http://blog.astrumfutura.com/2013/03/predicting-random-numbers-in-php-its-easier-than-you-think/

关于随机数发生器的输出,与蛮力攻击相关的密码/密钥强度通常以熵测量。这通常以比特列出,越多越​​好。关于密码强度的维基百科页面(http://en.wikipedia.org/wiki/Password_strength)有一些很好的参考表,用于确定不同长度的密码的熵级别,并使用各种字符类型组合。 openssl_random_pseudo_bytes()函数利用所有二进制/十六进制值,每个符号产生一个完整的8位熵。你的randomString()函数最多会产生每个符号5.954位的熵。

enter image description here

在所有与安全相关的情况下,应使用加密强随机数,其中猜测其中一个数字的能力会以某种方式对您的网站产生负面影响。 4列表中唯一一个我看到不需要加密强随机数的项目是哈希的盐值。盐值必须是普遍唯一的。它当然可以由加密随机数生成器(CRNG)生成,但这不是必需的,因为结果值可以公开。见https://security.stackexchange.com/questions/8246/what-is-a-good-enough-salt-for-a-saltedhash