2009-10-05 69 views
1

我需要生成一個隨機密鑰,在Java中,我將能夠在未來的某個點再生。這個想法是,這個密鑰對於它所創建的機器是獨一無二的,並且不存儲在任何地方。我試圖這樣的事情:生成相同的隨機密鑰兩次

KeyGenerator keyGen = KeyGenerator.getInstance("DESede"); 

String hostname = InetAddress.getLocalHost().getHostName(); 
SecureRandom random = new SecureRandom(hostname.getBytes()); 
keyGen.init(random); 

secretKey = keyGen.generateKey(); 

顯然,這不起作用,因爲設置一個SecureRandom的種子不會在我以爲它做的方式工作,每一次我得到一個不同的SecretKey的。也許我試圖做的事情永遠不會奏效(我知道它看起來像是一件奇怪的事情,想要做......)但如果有辦法,我會真的很感激它,如果有人能告訴我這是什麼方式!

+1

你想做什麼?什麼是關鍵?你能解釋一下你的整個環境嗎?可能有更好的方法來解決這個問題。 – 2009-10-05 11:14:16

回答

3

有兩種方法以編程方式確保關鍵:

  • 保持密鑰本身的祕密,或
  • 保持算法的祕密。

密碼學家(和常識)會告訴你,在這兩者中,第二種安全性要差得多,因爲反向工程代碼相對容易。所以你留下了第一種方法。

如果我正確地讀你的要求,你需要一個關鍵就是

  1. 保證是唯一的每臺機器。
  2. 隨機。
  3. 不存儲在任何地方。
  4. 可複製(通過您的軟件)。

但是不可能滿足所有這些。例如,一個真正隨機的密鑰不能存儲在任何地方(無論是作爲數據還是嵌入算法中)都不能隨意複製。所以,如果我可以採取一些迴旋餘地,我會讀入你的使用情況,並替換這些不太嚴格的要求:

  1. 綁主機:從一臺機器的密鑰無法被另一個使用。
  2. 安全:不可能被複制,猜測,反向工程,
  3. 安全:不可能在您的程序中被發現。
  4. 可重複性:您的應用程序必須能夠根據需要重新生成密鑰。

所有這些新的要求,用#3之外,能滿足此程序:


  1. 生成祕密隨機種子將每臺機器上使用。
  2. 選擇一個機器相關的簽名,它對每個主機都是唯一的,並將其附加到種子。典型的例子是一個MAC地址,但在具有兩個或更多NIC的機器上,每次必須小心使用相同的NIC!
  3. Hash結果與算法(如SHA),將產生一個合理的獨特和不可逆的結果。

現在,所有剩下的就是通過使合理的攻擊者難以猜測的一個項目必須是祕密的,以滿足第三個要求:種子。而這正是這個過程變得更像是一場宗教爭論而不是技術爭論的地方,因爲「相當困難」取決於攻擊者想要發現密鑰的嚴重程度以及如果他/她成功的話會面臨風險。

爲了儘可能安全,密鑰必須存儲在應用程序外部,例如在你的大腦中,並在每次需要時提供。但通常一些形式較爲薄弱的安全通過默默無聞的機制是可以接受的;我最喜歡的一種是使用類似0x%-6.2d這種可能被忽略的格式爲printf()格式。如果你偏執狂,將其存儲在一塊,並將其重新創建在應用程序的一部分中,而這部分應用程序與密鑰處理模塊沒有關聯。

如果您需要更具體的建議,請告訴我們更多關於您的應用程序及其使用案例。

祝你好運!

+0

非常感謝,這看起來像我需要的那種信息。請放心,我知道我正在做的事情很容易妥協,但我被要求找到一種方法來保護用於保護訪問其他密鑰的密碼,要求它不應該是「平凡的」可發現的 - 即不可能偶然以純文本形式偶然發現密碼。 – AndyB 2009-10-05 13:34:45

+0

然後你正在尋找一個KeyStore。 (沒有雙關語意) – 2009-10-15 02:22:23

3

即使它確實爲工作,你不會真的有一個「祕密」鍵 - 你有一個密鑰是完全可以從主機名導出。這不是一個祕密 - 它就像每個人使用他們的名字作爲他們的密碼。任何想要攻擊加密數據的人都必須知道創建密鑰的機器的名稱,然後才能訪問。

密鑰的最終形式幾乎與您需要重新創建的信息無關。要使密鑰有效,基本上這些信息必須是祕密的。

+0

但他可以使用一些鹽來使它私密?或者這不是一個好主意? – codevour 2009-10-05 11:13:27

+0

chrsk:好的,但是每個機器上的密鑰都會有所不同。即便如此,這仍然不是一個好主意,因爲如果你知道關鍵的模式,你就可以蠻橫地強制它。 – 2009-10-05 11:17:44

3

您無法生成兩次隨機密鑰,因爲它是隨機的。

如果InetAddress.getLocalHost()。getHostName()對於您的目的而言足夠獨特,則計算一個散列值並將其用作關鍵字。正如喬恩所說,關鍵是任何知道實現的人都可以推導出來。