我有一个整数列表(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个字符。
任何人都可以建议一些简单易用的东西,避免我必须记录所有生成的结果以进行独特的检查吗?
答案 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密钥对。