【问题标题】:How to shorten UUID V4 without making it non-unique/guessable如何缩短 UUID V4 而不使其不唯一/可猜测
【发布时间】:2022-02-16 03:16:15
【问题描述】:

我必须生成唯一的 URL 部分,这将是“不可猜测的”和“抵抗”暴力攻击的。它还必须尽可能短:) 并且所有生成的值必须具有相同的长度。我正在考虑使用 UUID V4,它可以用 32 个(不带连字符)十六进制字符 de305d5475b4431badb2eb6b9e546014 表示,但它有点太长了。所以我的问题是如何生成 unqiue,可以用 url charcters 表示,每个生成的值具有相同的 lengthshorter超过 32 个字符。 (在 node.js 或 pgpsql 中)

【问题讨论】:

标签: node.js postgresql cryptography probability uuid


【解决方案1】:

v4() 将生成一个大数字,该数字被翻译成十六进制字符串。在 Node.js 中,您可以使用 Buffer 将字符串转换为更小的 base64 编码:

import { v4 } from 'uuid';

function getRandomName() {

    let hexString = v4();
    console.log("hex:   ", hexString);
    
    // remove decoration
    hexString = hexString.replace(/-/g, "");
    
    let base64String = Buffer.from(hexString, 'hex').toString('base64')
    console.log("base64:", base64String);
    
    return base64String;
}

产生:

hex:    6fa1ca99-a92b-4d2a-aac2-7c7977119ebc
base64: b6HKmakr

hex:    bd23c8fd-0f62-49f4-9e51-8b5c97601a16
base64: vSPI/Q9i

【讨论】:

  • hexString.replace("-", "") 上面的代码中有一个错误,它没有正确删除连字符,因此Buffer.From 函数会截断输出,你会得到一些奇怪的缩短 base64。应该改用uuid.replace(/-/g, '');
【解决方案2】:

UUID v4 本身实际上并不保证 唯一性。两个随机生成的 UUID 发生冲突的可能性非常非常小。这就是为什么他们需要这么长 - 这减少了冲突的机会。 所以你可以让它更短,但你做的越短,它就越有可能实际上不是独一无二的。 UUID v4 的长度为 128 位,因为这通常被认为是“足够独特的”。

【讨论】:

  • 嗯,它可以更短但额外使用(不知何故)postgres sequence 吗?它必须仅在单个数据库中是唯一的。
  • 你想让它变得不可猜测。如果你在那里添加一个序列并缩短它,你就会让它更容易猜测两次。你基本上有相互冲突的目标。
【解决方案3】:

这完全取决于它的可猜测性/独特性。

我的建议是生成 128 个随机位,然后使用 base36 对其进行编码。这会给你一个“不错”的 URL,它会是独一无二的,而且可能足够令人猜不透。

如果您希望它更短,您可以使用 base64,但 base64 需要包含两个非字母数字字符。

【讨论】:

    【解决方案4】:

    short-uuid 模块就是这样做的。

    “生成标准 UUID 并将其转换为更短的(或只是不同的)格式并返回。”

    它接受自定义字符集(并提供一些)来来回转换 UUID。

    您还可以对 uuid 进行 base64 处理,将其缩短为 22。这是playground

    【讨论】:

      【解决方案5】:

      这是一个相当古老的线程,但我想指出最佳答案不会产生它声称的结果。它实际上会生成大约 32 个字符长的字符串,但示例要求 8 个字符。如果您想要更多压缩,请使用此函数将 uuid 转换为 base 90。

      使用 Base64 每 3 个字节占用 4 个字符,而 Hex (Base16) 每字节占用 2 个字符。这意味着 Base64 的存储大小将比十六进制大 67%,但如果我们可以提高字符/字节比率,我们可以获得更好的压缩。因此,Base90 提供了稍微多一点的压缩。

      const hex = "0123456789abcdef";
      const base90 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&'()*+-./:<=>?@[]^_`{|}~";
      
      /**
       * Convers a Base16 (Hex) represented string to a Base 90 String.
       * @param {String} number Hex represented string
       * @returns A Base90 representation of the hex string
       */
      function convertToBase90(number) {
          var i,
              divide,
              newlen,
              numberMap = {},
              fromBase = hex.length,
              toBase = base90.length,
              length = number.length,
              result = typeof number === "string" ? "" : [];
      
          for (i = 0; i < length; i++) {
              numberMap[i] = hex.indexOf(number[i]);
          }
          do {
              divide = 0;
              newlen = 0;
              for (i = 0; i < length; i++) {
                  divide = divide * fromBase + numberMap[i];
                  if (divide >= toBase) {
                      numberMap[newlen++] = parseInt(divide / toBase, 10);
                      divide = divide % toBase;
                  } else if (newlen > 0) {
                      numberMap[newlen++] = 0;
                  }
              }
              length = newlen;
              result = base90.slice(divide, divide + 1).concat(result);
          } while (newlen !== 0);
      
          return result;
      }
      
      /**
       * Compresses a UUID String to base 90 resulting in a shorter UUID String
       * @param {String} uuid The UUID string to compress
       * @returns A compressed UUID String.
       */
      function compressUUID(uuid) {
          uuid = uuid.replace(/-/g, "");
          return convertToBase90(uuid);
      }
      

      超过几百万个随机 uuid,这不会产生重复项和以下输出:

      Lengths:
      Avg: 19.959995 Max:  20 Min:  17
      
      Examples:
      Hex:      68f75ee7-deb6-4c5c-b315-3cc6bd7ca0fd
      Base 90:  atP!.AcGJh1(eW]1LfAh
      
      Hex:      91fb8316-f033-40d1-974d-20751b831c4e
      Base 90:  ew-}Kv&nK?y@~xip5/0e
      
      Hex:      4cb167ee-eb4b-4a76-90f2-6ced439d5ca5
      Base 90:  7Ng]V/:0$PeS-K?!uTed
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-14
        • 1970-01-01
        • 2012-03-29
        • 1970-01-01
        • 2019-09-05
        • 1970-01-01
        • 1970-01-01
        • 2021-02-17
        相关资源
        最近更新 更多