2017-08-18 66 views
1

我有一個整數列表(emplyoee的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 

我需要生成算法,將生成的密鑰,但我想,以避免可能的話,記錄鍵針對員工。我越想我遇到的問題就越多。

如果我能避免它,我不想生成所有的密鑰,並將它們存儲的地方 - 我寧願他們是實時計算

允許我藏在我的系統中一個祕密,我可以除非你知道祕密,否則確保密鑰不確定。

我想過使用標準哈希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

對於密碼編碼部分:取自[A-Z]的第一個字符,取自[0-9]的第二個字符和整個集合中剩下的三個字符。這給你26 * 10 * 62 * 62 * 62(= 61,965,280)的可能性。這並不完全覆蓋8位數字,而是接近 - 所以你可能不需要改變[A-Z]和[0-9]的位置。有了一些數學,你可以在密碼和[0-61,965,279]之間轉換。 –

+0

如果您確實需要覆蓋整個8位數範圍,請將50,000,000以下的地圖數字映射到[AZ] [0-9] [?] [?] [?]以及上面的[0-9] [AZ] [? ] [?] [?]。字符串模式不重疊。字符串生成和解析的決定很簡單:數字低於50,000,000,而第一個字符是字母。 –

+0

我很高興我在這裏發佈拉爾夫,那個答案是1號的路要走。從員工ID到密鑰的確定性,唯一性和祕密映射函數的任何想法? – Robert3452

回答

1

正如Ralf所提到的,實現所需密鑰變化的最簡單方法是可能更改大寫字母和數字的位置,從而爲您提供2 * 26 * 10 * 62 * 62 * 62>120000000可能的組合。

爲了使密鑰不能直接從員工ID推導出來,我建議使用另一個祕密8位數的簡單XOR。然後使用一個簡單的模數,然後對每個字符進行除法。

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

例如在javascript:

function ID2Key(id, secret) { 
    var table = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
    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這樣已經很好建立的加密算法,所產生的強度也不會比最多的暴力破解嘗試更好,這對於計算來說是微不足道的。考慮到這一點,唯一具有某種安全外表的方法是祕密該算法保持祕密。在這種情況下,試圖從ID和密鑰派生密鑰的人不知道他們是正確的,除非他們能夠訪問多個ID密鑰對。

+0

兩個「隨機」8位數字的XOR可能會導致9位數字(最多134,217,727),這比我們的編碼方案可以覆蓋的2 * 61,965,280範圍略高。因此,我們可以添加第三個編碼範圍[A-Z] [A-Z] [0-9] [?] [?],給出另外26 * 26 * 10 * 62 * 62的可能性,但不與前兩個範圍重疊。 –

+0

@RalfKleberhoff不錯的一點是,不幸的是,做出這樣的改變會將所得密鑰的加密「強度」從「308873088」降低到「179345664」,所以對於有效機密的範圍可能更好,因爲這在理論上是更好的[一次性填充](https://en.wikipedia.org/wiki/One-time_pad),因此祕密即使非常短也不可破解。如果我找不到更好的方法 – Joel

+0

另外每個員工都會知道他們的ID和他們的密鑰,所以如果我明白你說的話可以計算出這個祕密 – Robert3452