关于PHP:如何以一致的方式加密主键

How to encrypt primary keys in a consistent way

我有一个数据库表,它有一个简单的递增整数作为主键(1、2、3等)。这些数字代表的是一所大学的校友,个人信息记录在案。当显示给用户(在他们查询数据库之后)时,我被要求给每个记录一个唯一的ID,但是ID不能是主键,而且必须是一致的。

例如,如果有人检索到一个具有任意ID 88GH344R的记录,然后再次进行搜索并检索到记录88GH344R,他们需要能够说"这是同一个人"。因为人们需要能够识别从一个搜索到下一个搜索的标识符,所以ID不能长且复杂。

我想到了三种方法:

  • 创建一个包含主键和随机数字序列的额外表,并获取查询以检索与主键等效的随机数字。

  • 使用mysql的sha2或aes加密主键,但它们会产生长的字母和数字序列。

  • 在查询中使用类似于php中的base64加密的方法动态加密主键。

  • 哪一个是最好的,或者我错过了一个更好的方法?


    如果我正确理解你,你的主要目标就是不暴露主键,而是在与用户通信时使用其他东西。

    最简单的方法:

    向表中添加一个char列,并选择其他标识符的长度,例如char(16)。

    为该列提供唯一索引,这样您就不会有任何重复项。

    对于每一行,生成长度为16的安全*随机*字符串并更新该行。

    不要散列普通主键。如果键从1、2、3开始。然后,每个人都可以通过计算1、2、3……的散列值,将idhash进行匹配。等

    另一个问题是,例如,如果表中已经有200行,并且添加了1,那么攻击者可以自动将主键201与刚刚出现在列表中的随机字符串相关联。

    另一方面,为什么首先需要隐藏主键。也许您应该加密列中的个人用户数据?


    如果你这样做是为了保护隐私,那你就要去做一个重大的调查。对于最蹩脚的脚本孩子来说,编写一个简单的程序,只需尝试所有可能的"散列",下载整个列表就可以了。

    你应该研究适当的访问控制,这样人们才能看到他们被允许看到的东西。


    实际上,我只是在一个网址缩短器上写了一个简短的tut,在这个基础上工作,使用recid作为种子。您可以使用该函数创建查找键,并将其作为"引用"键存储在数据库中。代码在这里


    您可以将哈希或加密值截断到所需的长度,但两者都存在冲突的风险。如果你有200万条记录,那么8个36位的数字有50%的可能会发生碰撞。如果不转换为base-36,只需要八个十六进制数字,那么只需要8万条记录。

    对于随机数,您没有这个问题,因为您可以对列施加唯一性约束,并在发生冲突时生成一个新的数字。


    例如,您可以在userid*100或其他东西上执行基36编码。

    用户标识26=208用户标识3=8C

    http://www.translatorscafe.com/cafe/units-converter/numbers/calculator/decimal-to-base-36


    别把事情搞得太复杂。

    考虑一下:

  • 给用户一个可选的映射键。这可以是临时会话映射和/或辅助唯一密钥(但不是pk,可能在同一个表中,也可能不在同一个表中),当然,对于域来说应该是唯一的。

  • 访问令牌,每个项目随机生成,但不必是唯一的,它与用于公开ID的简单pk结合在一起。如果需要,可以通过适当的转换使其在值之间看起来非常漂亮。访问令牌也可以作为单独的值处理。

  • 我喜欢第二种方法。在这两种情况下,虽然在第二种形式中有更多的耦合,但不是暴露的"直接pk"。

    这两种方法都将阻止基于序列的"知道"下一个密钥,但猜测/暴力与域的大小有关:正如其他人所说,这不应该被用作主安全层。

    快乐编码。