PHP:使用盐生成类似于Youtube的短ID

6

我需要对数据库id进行编码/加密,并将其附加到我的URL中。我不是在处理安全问题,但我正在寻找具有适度安全性的解决方案。主要目标是拥有短且唯一的、安全的URL id。

以下代码段似乎可以满足我的需求(来自http://programanddesign.com/php/base62-encode/

function encode($val, $base=62,  $chars='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
    // can't handle numbers larger than 2^31-1 = 2147483647
    $str = '';
    do {
        $i = $val % $base;
        $str = $chars[$i] . $str;
        $val = ($val - $i) / $base;
    } while($val > 0);
    return $str;
}

function decode($str, $base=62, $chars='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
    $len = strlen($str);
    $val = 0;
    $arr = array_flip(str_split($chars));
    for($i = 0; $i < $len; ++$i) {
        $val += $arr[$str[$i]] * pow($base, $len-$i-1);
    }
    return $val;
}

echo encode(2147483647); // outputs 2lkCB1

我可能会稍微修改一下这些函数:

  1. 删除$base参数;可以通过strlen($chars)计算出来
  2. 从字符集中排除那些容易混淆的字母/数字(例如0,O,o)

如果我想在脚本中使用盐,该如何更改?这样做明智吗?会不会无意中增加碰撞的几率等等?


你所做的是基础转换。如果你想要一个“盐”,你可以在之前使用参数化整数混淆。例如,(new Id())->encode($id) 可以通过一次调用完成所有操作。盐可以通过构造函数进行配置。 - caw
2个回答

10
如果您希望将数字ID从字符串中隐藏起来,可以使用盐值。您应该能够在没有冲突的情况下获取ID。Kevin van Zonneveld的文章使用PHP创建短ID-类似于Youtube或TinyURL是一个很好的开始。无论如何,请检查唯一性。

这是一个非常棒的函数。但是,如果我的ID不仅仅是数字而是包含字母和数字,该怎么办? - axel
@axel,你可能可以使用pack/unpack,例如这个十进制版本:https://dev59.com/9Gw15IYBdhLWcg3w0e8V#6382880 但要注意以下两点:1)大数字,正如KVZ在上面的alphaID函数的评论中所指出的那样;2)长度:如果源字符串已经很短(例如由其生成算法产生),则您可能无法获得更短的ID。 - Halil Özgür
我不明白pack/unpack链接的意义。例如,我需要将“PRV_IDPreventivoAuto”这样的字段翻译成缩写“n8nXn_ah5”,并且我还需要能够回溯。 - axel
@axel,可能“PRV_IDPreventivoAuto”不能缩短为“n8nXn_ah5”(或任何相同长度的字符串),因为输入和输出的字符空间相同。你最好的选择是使用zip/gzip,但它们无法很好地压缩任意随机字符串(根据它们的定义)。 - Halil Özgür
@axel,我所说的是关于以下代码行的问题:http://codepad.viper-7.com/ZmDwup 请注意,在第16行中,我们直接使用了源十进制数(而不是第15行的ID)。这是因为alphaID无法处理超过某个值的数字(请参见注释)。您可能可以使用bc math获得可行的解决方案,但生成的ID可能仍然比输入更长。 - Halil Özgür

2

您可以使用PHP的uniqid函数从当前时间戳生成伪随机字符串,然后在上传时将此字母数字字符串保存在视频记录中。


我认为@StackOverflowNewbie并没有进行视频上传,他只是想要像YouTube一样的短唯一标识符。 - Jakub
原则仍然适用。只需使用 uniqid 并将其存储到记录中。 - Martin Bean
1
我更倾向于使用我的数据库ID并对其进行加密/编码。使用uniqid会得到类似于4b3403665fea6的结果。它相当长;我正在寻找一些短的东西(例如,易于通过电话告诉别人等)。 - StackOverflowNewbie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接