根据输入编号生成随机密钥

时间:2017-08-18 13:12:56

标签: algorithm math random hash

我有一个整数列表(emplyoee ID' s) 它们长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

我需要生成一个生成密钥的算法,但我想避免在可能的情况下记录密钥。我想的越多,遇到的问题就越多。

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

我被允许在我的系统中隐藏一个秘密,除非你知道秘密,否则我可以用来确保密钥是非确定性的。

我想过使用标准哈希algroythms(含盐),但目标空间的限制和包括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个字符。

任何人都可以建议一些简单易用的东西,避免我必须记录所有生成的结果以进行独特的检查吗?

1 个答案:

答案 0 :(得分:1)

正如拉尔夫所提到的,实现所需的密钥变化量的最简单方法是改变大写字母和数字的位置,为您提供2 * 26 * 10 * 62 * 62 * 62>120000000种可能的组合。

为了使密钥不能直接从员工ID中导出,我建议使用另一个秘密的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失败 - 为了解决评论中出现的失败案例,我改变了基于秘密将ID加密到轮换的方法,该秘密现在也可以是8位数字。

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