【问题标题】:Long random string generator in PHPPHP中的长随机字符串生成器
【发布时间】:2023-04-06 17:33:02
【问题描述】:

有谁知道如何在 PHP 中生成一个长的(例如 280 个字符)随机 string 而不必使用将循环字符 280 次的 for 循环?我需要它来创建自定义会话 ID。

在我看来,PHPSESSID 不够安全,它太短且不太随机。我知道 Facebook 和 Twitter,使用长会话 ID(分别为 150、550 个字符)。

可以选择使用MD5 字符串或Bcrypt 加密不同的字符串,例如PHPSESSID、主机、用户代理等,但我不确定这是正确的做法。

【问题讨论】:

  • 为什么不使用 for 循环?只需使用一个字符数组并在循环中将它们称为for ($i = 0; $i < 280; $i++) $buffer .= $characters[rand(0, $charactersLength)];
  • 循环有什么问题?如果你想减少循环次数,你总是可以连接几个哈希。
  • 循环没有问题,它只是使用一些内存,在流量较高的网站上,这可能会减慢加载时间。
  • 如果你不想使用 for 循环,你总是可以使用 while 循环来代替
  • 我不想在这里过于直率,但是如果您的网站因一个微不足道的 for 循环迭代 280 次而变慢,那么您就会遇到严重问题。在大多数现代硬件上,我们所说的实际上是 100 微秒...A Quick Benchmark....

标签: php random


【解决方案1】:

如果您要问这样的问题,这可能意味着您对密码学或安全性一无所知。尝试生成“长随机字符串”,因为正如您所说,“PHPSESSID 不够安全”可能会导致您使用自定义且不安全的实现。

生成随机字符串是不可能,至少在您当前的硬件上不会:您可以近似一个公平的伪随机生成器,但这仅用于教育目的。

PHP 的 Session ID 生成算法相当高效;如果您认为它不够安全,那么您可能会浪费时间来改进它。如果您正在寻找最大的安全性(例如使用客户端证书),您可能希望使用不同的身份验证机制。

如果 Twitter、Facebook 或其他具有类似流量的网站使用更长的会话 ID,这可能不是因为它更安全(在某种程度上),而是因为它避免了冲突。

最后,如果您想要一个更长的会话 ID 而不是尝试编写自己的算法,您应该使用以下 PHP 配置指令:

session.hash_function 可以采用 PHP 已知的任何哈希算法。

您可能还想使用session.bits_per_characters 来缩短或延长字符串。请注意,如果这样做,字符串可能会更长或更短,但数据保持不变——只是表示方式不同(以 16 为基数、以 32 为基数等)

附加信息:

您还可以通过使用自定义源(文件)并设置种子的长度来增加熵:

ini_set("session.hash_function", "sha512");
ini_set("session.bits_per_charater", 4); // 4 means hex
ini_set("session.entropy_file", "/dev/urandom");
ini_set("session.entropy_length", "512");

【讨论】:

  • “PHPSESSID 不够安全”与我的技能无关,当然你不是判断它的人。 PHPSESSID 的弱点不是我发现的,而是在网络上高度讨论的,但无论如何,我感谢您抽出宝贵时间与我们分享您的想法和经验。
  • 我不会“评判”你的全球技能,我只是根据你的问题做出了一个假设。不要被冒犯。据说我删除了“技能”部分,但它仍然适用。
  • 我没有被你的话冒犯,因为我同意我之前没有使用过cryptography,而且我正在处理的应用程序需要一些额外的安全性。所以,这就是我发布的原因这个问题想看看其他人对此有何看法以及最常见的方法是什么,我可以使用loop 生成一个字符串并将其与用户User-Agentmd5 连接,但不确定它是否正确.
  • @AndreiStalbe:这个答案和 PaulDixon 提供的答案清楚地表明,内置的 PHP 会话生成器非常好。会话劫持的可能性非常低,您可以通过提供一些更好/更大的随机数据来降低它们。
  • 谢谢你们的回答,这真的帮助我决定走哪条路。
【解决方案2】:

可以是二进制十六进制吗?

bin2hex(mcrypt_create_iv(140, MCRYPT_DEV_URANDOM));

或者如果你可以访问hash_pbkdf2():

hash_pbkdf2('sha256', PHPSESSID, mt_rand(), 1, 280, false);

【讨论】:

  • 这可能对他有用bin2hex(mcrypt_create_iv(140, MCRYPT_DEV_URANDOM))
  • bcryptPBKDF2 这样的哈希函数被设计为使用大量时间,这对哈希密码有好处,因为您需要大量时间才能找到原始密码。对于生成随机字符串,它绝对是错误的工具,生成的 id 绝不会更加独特或不可预测。 mcrypt_create_iv() 的第一种方式适合这项工作。
  • @martinstoeckli:PBKDF2 通过拉伸密钥来消耗时间(在我的示例中为 2048 次)。如果需要,您可以将其设置为非常低的值。
  • @Alix Axel - 如果您不想进行迭代并将迭代次数设置为 1,您可以直接调用 sha256。这就像编写一个 for 循环,当您知道它只运行一次时。而且迭代不会改善结果,只会让你的服务器很忙。
  • @martinstoeckli:不是那样的。 1. 直接调用sha256 永远不会产生280 字节的字符串,而PBKDF2 会。 2. 迭代实际上会改善结果(就安全性而言)——我认为这与 OP 目标无关,这就是我改变它的原因。
【解决方案3】:

您可能会发现,并非“长”会话 id 中的所有位都是纯随机的 - 它们可能会为应用程序提供额外信息,以便快速提取关键信息。

默认情况下 PHP 会话 ID 并不算太差,并且可以通过提供一些额外的熵来改进(例如来自 /dev/urandom)

查看php源码中ext/session/session.c中的php_session_create_id

是这样的:

  • 获取时间
  • 获取远程IP地址
  • 用当前时间的秒数和微秒以及 IP 地址构建一个字符串
  • 将其输入配置的session hash function(MD5 或 SHA1)
  • 如果已配置,请从entropy file 提供一些额外的随机性
  • 生成最终哈希值

因此,获取副本或预测会话 ID 非常困难。

【讨论】:

  • 很抱歉,我也没有 2 个正确答案来检查您的答案。不过谢谢你的解释。 +1。
【解决方案4】:

让自己成为一个长字符串并shuffle它。

$string = 'asdfhdfiadfshsdfDSGFADSFDSFDSFER524353452345';
$new_string = shuffle($string);

【讨论】:

  • -1 Shuffle 使用 rand() 根据他/她的要求,这对于 OP 来说显然不够随机。此外,这不会创建随机字符串,而是以“随机”顺序放置某些字符串。
猜你喜欢
  • 2011-05-20
  • 1970-01-01
  • 2012-11-06
  • 2018-01-25
  • 2015-08-16
  • 2013-10-01
  • 2014-02-01
  • 2012-05-22
相关资源
最近更新 更多