【问题标题】:Generate a Random key based on Input Number根据输入数字生成随机密钥
【发布时间】:2018-01-27 04:40:10
【问题描述】:

我有一个整数列表(员工 ID) 它们是 8 位长(虽然几乎都是从 00 开始,但它们实际上是 8 位长)

我需要为每个员工生成一个密钥:

- 5 chars including [A-Z][a-z][0-9]
- Must include 1 of [A-Z]
- Must include 1 of [0-9]
- Generated key must be unique
- If I know an employees ID I should not be able to determine their key

我需要生成一个算法来生成密钥,但我希望尽可能避免记录员工的密钥。越想越遇到问题。

如果我可以避免它,我不想生成所有密钥并将它们存储在某个地方 - 我宁愿它们是即时计算的

我可以在我的系统中隐藏一个秘密,除非你知道这个秘密,否则我可以使用它来确保密钥是不确定的。

我曾想过使用标准哈希算法(含盐),但目标空间的限制以及包括 1 A-Z 和 1 0-9 的限制似乎阻止了这一点。

我想我可以用一种方法来解决问题:

1. Build a deteremnistic function that maps integers starting from 1 [1, 2, 3, ...] to every possible result value
2. Map integers [1, 2, ...] to random other integers in the desired range [324, 43565, ...] in a way that preserves uniqueness (based on a secret salt which if changed would result in a different order).

这将保证唯一性,但第 1 步很棘手。结果集不连续,某些值可能缺少大写字母,而其他值可能缺少数字。

我可以通过使用 A1 开始每个代码来解决这个问题,这在技术上可行但将结果空间从 5 个字符减少到 3 个字符。

任何人都可以提出一些简单的方法来避免我必须记录所有生成的结果以进行唯一检查吗?

【问题讨论】:

  • 密码编码部分:取[A-Z]的第一个字符,[0-9]的第二个字符,其余三个字符全集。这为您提供了 26*10*62*62*62 (= 61,965,280) 种可能性。这并没有完全覆盖 8 位数字,但很接近 - 所以你可能不需要改变 [A-Z] 和 [0-9] 的位置。通过一些数学运算,您可以在密码和 [0-61,965,279] 数字之间进行双向转换。
  • 如果您确实需要覆盖整个 8 位范围,请将低于 50,000,000 的数字映射到 [AZ][0-9][?][?][?] 并将高于的数字映射到 [0- 9][AZ][?][?][?]。字符串模式不重叠。字符串生成和解析的决定很简单:低于 50,000,000 的数字与第一个字符是字母。
  • 我很高兴我在这里发帖拉尔夫,答案是 1 号是要走的路。从员工 ID 到密钥的确定性、唯一性和基于秘密的映射函数有什么想法吗?
  • 抱歉,对于第二部分并不是一个真正的想法。我很想说“加密”,但是您可以将(大致)27.6 位输入加密为 27.6 位输出,然后再解密结果吗?我不知道。也许如果你能保证 24 位(16 兆)内的数字,即 3 字节的文本。我不是加密专家。

标签: algorithm math random hash


【解决方案1】:

正如 Ralf 所说,实现所需的键变化量的最简单方法是更改​​大写字母和数字的位置,为您提供 2 * 26 * 10 * 62 * 62 * 62>120000000 可能的组合。

为了使密钥不能直接从员工 ID 派生,我建议使用一个简单的 XOR 与另一个秘密 8 位数字。然后对每个字符使用简单的模数和除法。

char = x % 62
x = (x - (x % 62)) / 62

例如在 javascript 中:

function ID2Key(id, secret) {
    var table = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    var key = new Array(5); // Initialize the key
    // Changed XOR to a ROT10
    // var scrambled = id ^ secret; // "Encrypt" the employee ID with a secret
    var scrambled = 0;
    while (id) {
        var rotated = ((id % 10) + (secret % 10)) % 10;
        scrambled = (scrambled * 10) + rotated;
        id = Math.floor(id / 10);
        secret = Math.floor(secret / 10)
    }

    var capital_index = scrambled % 2; // Determine if the Capital letter should be first
    scrambled = (scrambled - capital_index) / 2;
    var capital = table[36 + (scrambled % 26)]; // Find the capital letter
    key[capital_index] = capital;
    scrambled = (scrambled - (scrambled % 26)) / 26;

    var num = scrambled % 10; // Find the number
    key[1-capital_index] = table[num]; // If the capital letter is first place the number second and visa versa
    scrambled = (scrambled - (scrambled % 10)) / 10;

    // Find the remaining 3 characters
    key[2] = table[scrambled % 62];
    scrambled = (scrambled - (scrambled % 62)) / 62;

    key[3] = table[scrambled % 62];
    scrambled = (scrambled - (scrambled % 62)) / 62;

    key[4] = table[scrambled % 62];
    return key.join("");
}

现场演示JS Bin

编辑解决 XOR 故障 - 为了解决 cmets 中出现的故障情况,我将加扰 ID 的方法更改为基于密钥的轮换,该密钥现在也可以是 8 位数字。

编辑澄清漏洞 - 由于我现在更好地理解要求,主要是员工会知道他们的 ID 和密钥,我应该澄清一些密码概念。考虑到相当小的输入范围和限制性的输出,不可能使密钥加密安全。即使使用完善的加密算法(如 128 位 AES),所产生的强度也不会比最多 100000000 暴力破解尝试更好,这对于计算来说是微不足道的。考虑到这一点,具有某种安全性的唯一方法是保密算法保持保密。在这种情况下,试图从 ID 和密钥中获取秘密的人无法知道它们是正确的,除非他们可以访问多个 ID 密钥对。

【讨论】:

  • 两个“随机”8 位数字的 XOR 可以得到一个 9 位数字(最多 134,217,727),这比我们的编码方案可以覆盖的 2 * 61,965,280 范围略大。所以我们可以添加第三个编码范围 [AZ][AZ][0-9][?][?],提供另外 26*26*10*62*62 的可能性,与前两个范围不重叠。
  • @RalfKleberhoff 好点,不幸的是,进行该更改会将生成的密钥的加密“强度”从308873088 降低到179345664,因此最好对有效范围进行更多限制秘密,因为这在理论上是一个One-time pad,所以即使它很短,这个秘密也是牢不可破的。我得再考虑一下,如果找不到更好的方法,我会进行编辑
  • 而且每个员工都会知道他们的 id 和他们的密钥,所以如果我明白你所说的,就可以计算出秘密
  • 我已编辑问题以解决这些问题。重要的是要注意这里受保护的数据范围足够小并且足够严格,据我所知,如果攻击者知道算法,甚至理论上都无法阻止真正的努力来破解“加密”。
  • 感谢您的回答。我有一种轻微的感觉,即 5 个字符的限制以及我们的支付提供商提供的各种限制很弱,但您已经能够非常清楚地解释原因。我认为我们最终将只是为人们分配随机密钥并通过存储我分配的每个密钥并进行数据库查找来手动检查唯一性。
猜你喜欢
  • 2015-09-27
  • 2020-04-17
  • 2014-07-20
  • 2018-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-15
相关资源
最近更新 更多