如何以一致的方式加密主键

时间:2011-03-11 22:43:51

标签: php mysql encryption

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

例如,如果某人检索到具有任意ID 88gh344r的记录,则再次进行搜索并再次检索记录88gh344r,他们需要能够说“那是同一个人”。由于人们需要能够识别从一次搜索到下一次搜索的标识符,因此ID不能长而复杂。

我想到了三种方法:

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

  2. 使用MySQL的SHA2或AES加密主键,但这些主键产生长字母和数字序列。

  3. 使用PHP中的Base64加密等方式在查询中动态加密主键。

  4. 哪一种最好,或者我错过了更好的方法?

7 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

如果您这样做是为了保护隐私,那么您将前往主要的fsckup。最蹩脚的脚本小子写一个简单的程序,只是尝试每一个可能的“哈希”,下载你的整个列表不会很久。

您应该查看正确的访问控制,以便人们只能看到他们可以看到的内容。

答案 2 :(得分:1)

如果我理解正确,你的主要目标不是揭示主键,而是在与用户沟通时使用别的东西。

最简单的方法:

在表格中添加一个CHAR列,并选择一些您想要其他标识符的长度,例如CHAR(16)。

为该列提供UNIQUE索引,以便您不会有任何重复项。

每行

生成一个长度为16的安全 * random *字符串并更新该行。

请勿散列普通主键。如果键从1,2,3开始,那么每个人都可以通过计算1,2,3等的哈希值来匹配idhash

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

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

答案 3 :(得分:0)

不要太复杂。

考虑一下:

  1. 为用户提供备用映射密钥。这可以是临时会话映射和/或辅助唯一密钥(但 PK,并且可能在同一个表中,也可能不在同一个表中),并且当然应该与域唯一。

  2. 访问令牌,每个项目随机生成但不必是唯一的,它与暴露的id的简单PK结合使用。如果需要,可以通过适当的转换使其看起来非常漂亮。访问令牌也可以视为单独的值。

  3. 我喜欢第二种方法。在这两种情况下,尽管在第二种形式中存在更多偶联,但它并不是暴露的“直接PK”。

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

    快乐的编码。

答案 4 :(得分:0)

例如,

你可以在用户ID * 100或其他东西上做基数36编码。

用户ID 26 = 208 userid 3 = 8C

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

答案 5 :(得分:0)

您可以将散列值或加密值截断为所需的长度,但两者都可能会发生冲突。如果你有200万条记录,那么你有8个基数为36的数字,大约有50%chance of a collision。如果你没有转换为base-36并且只取八个十六进制数字,你只需要8万条记录。

对于随机数,您没有此问题,因为您可以在列上放置唯一性约束,并在发生碰撞时生成新数字。

答案 6 :(得分:0)

经过 2 个月的搜索,我找到的简短答案是 hashids,您可以为 https://hashids.org/ 中的每种语言安装它。其选项是:

  1. 从名为 salt 的密钥生成加密字符串。
  2. 为您的字符串定义最小长度,例如 8 位数字,它不适用于 base64_encode() 等函数
  3. 反向解码你的字符串
  4. 仅定义所需的字母,例如 a-z。(请注意,必须至少定义 16 个字母)

注意:对于 php,建议为您的网站主机激活 bcmathGMP 扩展,但无需GMP