【问题标题】:How to obfuscate an integer?如何混淆整数?
【发布时间】:2015-01-26 09:42:03
【问题描述】:

从 C# 中的整数列表中,我需要生成唯一值列表。我想在 MD5 或类似文件中,但它们生成的字节太多。

整数大小为 2 个字节。

我想得到一个单向通信,例如

0 -> ARY812Q3
1 -> S6321Q66
2 -> 13TZ79K2

因此,证明哈希,用户无法知道整数或干扰哈希列表后面的序列。

目前,我尝试使用 MD5(我的号码),然后使用前 8 个字符。但是我在 51389 发现了第一次碰撞。我可以使用哪些其他替代方案?

正如我所说,我只需要一种方法。不必能够从散列计算整数。系统使用字典来查找它们。

更新:

回复一些关于使用 GetHashCode() 的建议。 GetHashCode 返回相同的整数。我的目的是向最终用户隐藏整数。在这种情况下,整数是数据库的主键。我不想将这些信息提供给用户,因为他们可以推断出数据库中的记录数或每周记录的增量。

哈希不是唯一的,所以也许我需要使用 TripleDes 之类的加密,但我想使用快速简单的东西。此外,TripleDes 返回的字节也太多。

更新 2: 我在谈论哈希,这是一个错误。实际上,我正在尝试对其进行混淆,并使用哈希算法进行了尝试,这不是一个好主意,因为它们不是唯一的。

【问题讨论】:

  • “还有哪些我可以使用的替代方案?”,HashCode 使用相同的数字???
  • 或 int.GetHashCode()?
  • 你想解决什么样的问题?
  • 您可以使用像 Skip32 这样的 32 位分组密码(简单,但不寻常的加密原语)。或者在 FFX 模式下使用格式保留加密(如 AES)(复杂)。或者接受更长的输出并使用 64 位分组密码。
  • Wat 字符编码?另一种选择:只需创建一个包含 64 Ki 价值的 8 个随机字符串的地图,测试其唯一性。

标签: c# encryption hashmap


【解决方案1】:

2017 年 5 月更新

随意使用(或修改)我开发的库,可通过 Nuget 安装:

安装包 Kent.Cryptography.Obfuscation

这会将诸如 127 之类的非负 id 转换为 8 个字符的字符串,例如xVrAndNb,然后返回(有一些可用选项可以在每次生成序列时随机化序列)。

示例用法

var obfuscator = new Obfuscator();
string maskedID = obfuscator.Obfuscate(15);

完整文档位于:Github


旧答案

我早早地遇到了这个问题,但在 StackOverflow 中找不到我想要的东西。所以我做了这个混淆类,只是在github上分享了。

Obfuscation.cs - Github

您可以通过以下方式使用它:

Obfuscation obfuscation = new Obfuscation();
string maskedValue = obfuscation.Obfuscate(5);
int? value = obfuscation.DeObfuscate(maskedValue);

也许对未来的访客有帮助:)

【讨论】:

    【解决方案2】:

    使用 Skip32 对其进行加密,生成 32 位输出。我找到了this C# implementation,但不能保证它的正确性。 Skip32 是一种相对不常见的加密货币选择,可能尚未进行太多分析。仍然足以满足您的混淆目的。

    最好的选择是在 FFX 模式下使用 AES 进行格式保留加密。但这对您的应用程序来说相当复杂,而且可能有点矫枉过正。

    使用 Base32(不区分大小写,字母数字)编码时,32 位值对应 7 个字符。十六进制编码时,对应8个字符。


    还有生成随机值、将其存储在数据库中并处理冲突的非加密替代方案。

    【讨论】:

      【解决方案3】:

      异或整数。也许使用每个用户生成的随机密钥(存储在会话中)。虽然它不是严格意义上的哈希(因为它是可逆的),但优点是您不需要将它存储在任何地方,并且大小相同。

      【讨论】:

      • 如何使用每个用户的随机密钥生成 唯一 值?在不知道用户获取密钥的情况下,您将如何反转它?
      • 您需要每个用户的唯一值。您不需要应用程序的唯一值,您已经拥有一个:您尝试加密的 ID。根据您的要求,以上实现了您的两点:用户无法知道整数,也无法干扰哈希列表后面的序列。您可以使用唯一密钥进行加密,但这会削弱加密,因为访问同一页面的两个用户将看到相同的 ID。
      • 这太弱了,甚至没有表现出 OP 想要解决的序列隐藏问题。
      • 您甚至可以在加密的 Id 中包含 xor 密钥,甚至不必将其存储在内存中。我只是试图给出一个易于实施的答案。您可以根据需要将其复杂化。如果您需要加密强度,请使用加密功能并付出代价。
      • 抱歉,我以为您是在建议 Alphonse 将他们的 ID (1) 与他们的每个用户的幻数 (8) 进行异或运算,从而得到混淆值 9。Gwendolyn 的 ID (7) 和幻数 ( 14) 将导致 9。OP 可以在 URL 中使用混淆值 (9),然后从中推断出正确的用户。
      【解决方案4】:

      对于您想要的,我建议使用GUIDs(或其他类型的唯一标识符,其中冲突的可能性很小或没有)并将它们存储在数据库行中,然后永远不要显示@987654323 @给用户。

      恕我直言,向用户显示数据库中的主键是一种不好的做法(更不用说让用户对其进行任何类型的操作了)。

      如果他们出于某种原因需要对数据库进行原始访问,那么就不要使用整数作为主键,而是将它们设为guids(但你的要求就失去了重要性,因为他们只能访问记录的数量)

      编辑

      根据您的要求,如果您不关心该算法的计算成本可能很高,那么您可以在每次添加新行时生成一个随机的 8 字节字符串,并继续生成随机字符串,直到找到一个尚未在数据库中。

      这远非最佳,而且 - 计算成本很高,但如果你使用 16 位 id 并且最大行数是 65536,我不会太在意它(可能一个 65536 可能性列表中的 8 字节随机字符串是最少的,所以如果你的伪随机生成器很好,你可能会在第一次或第二次尝试时表现良好)。

      【讨论】:

      • GUID 大小对我来说太长了。我正在寻找一种将 2 个字节转换为最多 8 个字符的字符串的算法。
      • GUID 通常为 16 个字节,我不会说这“太大”,但如果这些是您的大小要求,那么可以。如果需要,请检查此问题的一些答案以生成更小的 GUID:stackoverflow.com/questions/5678177/…
      • 顺便说一句,任何不容易找到的算法都不会从 32 字节 int 生成任何 unique id。您要么像 GUID 那样对它进行伪随机化(在这种情况下,我会说 8 个字节不足以保证低碰撞风险),要么在需要时忍受可以轻松逆向工程的东西(以及聪明人这样做)
      • 用可能的(但不是优雅或高效的)解决方案更新了答案
      猜你喜欢
      • 2011-07-03
      • 2012-12-29
      • 2014-12-30
      • 2011-02-03
      • 1970-01-01
      • 2016-03-19
      • 1970-01-01
      • 2011-11-27
      • 1970-01-01
      相关资源
      最近更新 更多