如何在 php 中正确创建唯一标记?
How to create unique tokens correctly in php?
我是 php 的新手,我正在自学,通常我创建我的标记并将它们插入 table 中,如下所示:
private function create_token($reference, $bytes, $slice)
{
$key = substr(preg_replace('/\W/', "", base64_encode(bin2hex(random_bytes($bytes)))), 0, $slice);
return $reference . $key;
}
function create_token('token_B8', 34, 22); //token_B8eEr32EEddDsfSDGRGgHHhg
这可能是创建令牌的正确方法,但我怀疑这是否真的是正确的方法,我在想,显然在相同的 table 中有 2 个令牌和 1到 1000000000 正确吗?或者有没有办法创建一个令牌,上面写着:
Under no circumstances create an equal token
无需创建函数来检查 table 中的令牌是否已经存在。
我相信我应该做的是创建一个令牌,我创建它的方式是创建一个函数来检查这个令牌是否已经存在于 table,如果存在,它会生成另一个令牌,如果不是,则将其插入 table。这似乎是一种正确的方法,但由于我是新手,我不知道是否有更合适的方法,有人可以让我摆脱这种怀疑吗?谢谢
random_bytes()
生成的字符串具有最大的随机性,从字面上看,您之后对它所做的一切都会减少字符串中的随机性,从而减少它可能的值的数量。
random_bytes()
每字节8位随机。
bin2hex()
将输入的每个字节扩展为两个字节。 [x0.5]
base64_encode()
在 4 个输出字节上扩展 3 个输入字节。 [x0.75]
preg_replace('/\W/', "", $input)
有效地从 base64 编码更改为 base62,再次稍微减少 space。 [X??? < 1]
所以大家都说你生成的 22 字节令牌代表 22 * 8 * 0.5 * 0.75 * ??? <= 66
位随机数据。所以 <= 73,786,976,294,838,206,464 种可能性。
男孩你好,看起来确实很多,对吧?好吧,不是真的。由于 Birthday Paradox 碰撞的可能性可能会进入导致问题的范围,而您距离填充范围仍有几个数量级的距离。
我想如果我们删除那个毫无意义的 bin2hex()
我们可以挤出另外 66 位总共 132 位?但这 真的 还能给我们带来多少?
5,444,517,870,735,015,415,413,993,718,908,291,383,296
很多。 手。我什至不关心那个 preg_replace()
了。
为了完整起见,只 random_bytes(22)
怎么样? 176 位?
95,780,971,304,118,053,647,396,689,196,894,323,976,171,195,136,475,136
我猜要点是:
- 不要仅仅因为输出 看起来 乱码就将数据 编码 与“随机化”混淆。 [注意:哈希函数也是如此]
- 如果您不知道他们实际在做什么,请不要随意应用functions/encodings。
在代码中:
$input = 'abc';
// all of these outputs contain the SAME amount of entropy, some of them are just longer representations
var_dump(
$input,
bin2hex($input),
base64_encode($input),
base64_encode(bin2hex($input)),
bin2hex(base64_encode($input))
);
输出:
string(3) "abc"
string(6) "616263"
string(4) "YWJj"
string(8) "NjE2MjYz"
string(8) "59574a6a"
无论如何,如果随机 ID space 足够大,则更务实的做法是对值设置 UNIQUE
约束,并在尝试插入重复值时让进程失败。您可以放入一些重试逻辑,但很可能它永远不会 运行 除非有人专门利用漏洞 使 您自己通过重试生成重复项和 DoS。 [是的,这是一件事]
我是 php 的新手,我正在自学,通常我创建我的标记并将它们插入 table 中,如下所示:
private function create_token($reference, $bytes, $slice)
{
$key = substr(preg_replace('/\W/', "", base64_encode(bin2hex(random_bytes($bytes)))), 0, $slice);
return $reference . $key;
}
function create_token('token_B8', 34, 22); //token_B8eEr32EEddDsfSDGRGgHHhg
这可能是创建令牌的正确方法,但我怀疑这是否真的是正确的方法,我在想,显然在相同的 table 中有 2 个令牌和 1到 1000000000 正确吗?或者有没有办法创建一个令牌,上面写着:
Under no circumstances create an equal token
无需创建函数来检查 table 中的令牌是否已经存在。
我相信我应该做的是创建一个令牌,我创建它的方式是创建一个函数来检查这个令牌是否已经存在于 table,如果存在,它会生成另一个令牌,如果不是,则将其插入 table。这似乎是一种正确的方法,但由于我是新手,我不知道是否有更合适的方法,有人可以让我摆脱这种怀疑吗?谢谢
random_bytes()
生成的字符串具有最大的随机性,从字面上看,您之后对它所做的一切都会减少字符串中的随机性,从而减少它可能的值的数量。
random_bytes()
每字节8位随机。bin2hex()
将输入的每个字节扩展为两个字节。 [x0.5]base64_encode()
在 4 个输出字节上扩展 3 个输入字节。 [x0.75]preg_replace('/\W/', "", $input)
有效地从 base64 编码更改为 base62,再次稍微减少 space。 [X??? < 1]
所以大家都说你生成的 22 字节令牌代表 22 * 8 * 0.5 * 0.75 * ??? <= 66
位随机数据。所以 <= 73,786,976,294,838,206,464 种可能性。
男孩你好,看起来确实很多,对吧?好吧,不是真的。由于 Birthday Paradox 碰撞的可能性可能会进入导致问题的范围,而您距离填充范围仍有几个数量级的距离。
我想如果我们删除那个毫无意义的 bin2hex()
我们可以挤出另外 66 位总共 132 位?但这 真的 还能给我们带来多少?
5,444,517,870,735,015,415,413,993,718,908,291,383,296
很多。 手。我什至不关心那个 preg_replace()
了。
为了完整起见,只 random_bytes(22)
怎么样? 176 位?
95,780,971,304,118,053,647,396,689,196,894,323,976,171,195,136,475,136
我猜要点是:
- 不要仅仅因为输出 看起来 乱码就将数据 编码 与“随机化”混淆。 [注意:哈希函数也是如此]
- 如果您不知道他们实际在做什么,请不要随意应用functions/encodings。
在代码中:
$input = 'abc';
// all of these outputs contain the SAME amount of entropy, some of them are just longer representations
var_dump(
$input,
bin2hex($input),
base64_encode($input),
base64_encode(bin2hex($input)),
bin2hex(base64_encode($input))
);
输出:
string(3) "abc"
string(6) "616263"
string(4) "YWJj"
string(8) "NjE2MjYz"
string(8) "59574a6a"
无论如何,如果随机 ID space 足够大,则更务实的做法是对值设置 UNIQUE
约束,并在尝试插入重复值时让进程失败。您可以放入一些重试逻辑,但很可能它永远不会 运行 除非有人专门利用漏洞 使 您自己通过重试生成重复项和 DoS。 [是的,这是一件事]