哈希创建唯一的URL,以便猜测有效的URL代替身份验证

Kii*_*ani 7 security url hash

我正在考虑写一个网页,为客户提供反馈表.
我希望客户能够使用任何特定订单的唯一URL访问此表单; 一个简单的例子是http://www.example.com/feedback/012345格式.

旁注:我已经熟悉URL重写.在给定语言或给定服务器上创建/重定向URL超出了本问题的范围

客户必须进行身份验证(或者,就此而言,甚至拥有帐户)才能访问反馈表单,这是不可接受的.但是,出于对统计正确性的关注,我对example.com/feedback/[order_id]上面的明显解决方案不满意.这允许任何人更改URL中的ID并访问另一个订单的反馈.

另一方面,我希望能够从打印输出(例如收据)输入这些URL,因此在许多"重置密码"链接上提供长哈希不是有效选项.

基于此,我有以下标准:

  1. 每个订单都应存在唯一的URL
  2. 此URL应该是相对人类可输入的,现在将其称为"短"
  3. 不应该更改URL中的字符并访问其他订单(在合理的概率范围内)

我的想法是我应该在URL中放入两个数据.客户记录中有很多人类可读的数据可以帮助解决这个问题,例如客户ID,订单的联系电话号码,姓氏......虽然这样就无法更改一两个数字,但我没有看到它显着改善了给无聊攻击者的给定URL的"可猜测性".

以/ feedback/[surname]/[id]的简单示例为例,您可以通过简单的字典攻击页面来接收一组有效的URL:

for x in range(00000,99999):
    for name in ["jones","smith", ....]:
        url = "http://www.example.com/feedback/"+name+"/"+x
        if exists(url):
            print(url)
Run Code Online (Sandbox Code Playgroud)



我考虑的下一件事,就像tinyurl这样的服务,是散列ID号并以/ feedback/[hash]/[id]的形式提供一个URL
我已经做了一些研究并且实际上了解到URL缩短服务可能使用自动增量ID记录而不是实际的数学哈希.这种方法可能没用

如果使用实际的散列函数,则重要的是散列不明显地从ID号导出.提供像/ feedback/trpxq/53192这样的URL是没用的,因为在看到其中的一个或两个后,您可以轻松地拉出以前的记录:/ feedback/trpxp/53191

我当时正在考虑,如果散列包含一个salt,那么即使知道使用了什么散列函数,也不可能散列任何旧的有效订单ID并调出有效的URL.

所以,最后,这是实际的问题:

什么函数最好用于创建基于7-10位整数ID和任意盐的哈希的短,非显而易见,相对独特的字母数字表示?

这不是URL缩短问题本身,所以如果散列部分与ID部分的长度相同,我会感到满意:减少到10个字母数字字符是可以接受的.

此外,每次访问URL时都不一定需要计算哈希值.无论是在创建订单记录时,还是在首次访问该订单ID的页面时,都可以对其进行计算.这意味着散列函数不一定非常快.

虽然有可能基本上为查找目的创建哈希表,但是这个问题与哈希表没有相同的限制:查找是基于已经唯一的值完成的,因此冲突解决并不是绝对必要的,只要它足够难以找到具有给定哈希的相同哈希的另一记录.



我们现在已经完全超出了确保反馈形式需要做的实际领域 - 这些数据实际上并不重要 - 但是幽默我,这是一个有趣的问题,我想知道是否有一个最好的安全性和可读性的解决方案.

Cel*_*ada 9

从根本上说,这归结为一个非常简单的情况.

  • 您有一个标识符的命名空间,每个标识符有n位.此命名空间的大小为2ⁿ.
  • 在此命名空间之外,您实际上只发出了v个有效标识符.
  • 用户偶然猜测一个有效标识符的概率是p = v /2ⁿ.

你必须做出妥协.较大的n意味着较小的p但标识符更难以键入/复制/记忆.较小的n将使标识符更短但增加p.

如果标识符仅在有限的时间内有效,那么有一点是有帮助的.这允许您在不增加p的情况下发出大量标识符,因为只有一小部分已发布的标识符实际上同时有效.您的使用案例可能会或可能不会规定标识符的某个最小合理生命周期.

在任何情况下,标识符当然应该基于随机数或包括秘密密钥在内的若干事物的加密散列,以便与诸如订单号或序列/序列号之类的有意义的信息片段没有可辨别的关系.如果使用散列并且选择n小于散列输出的长度,则截断散列完全可以.

将标识符编码为URL的最紧凑方式类似于base64.base64的缺点当然是编码的字符串对人类没有意义.您可以使用各种编码方案,例如生成可发音词或词典中的单词序列.这些对人类来说可能更难忘,但是对于相同数量的熵,它们实际上要长得多,因此它可能不值得(特别是如果URL通常被点击,复制和粘贴,或扫描为QR码) .