2012-04-16 119 views
2

我試圖在Android上使用Java確定性地生成RSA密鑰對。我的要求是,我不能存儲密鑰對,並且它必須在運行時生成,與之前/未來的運行相同。確定性生成RSA加密密鑰對

我的過程是,我會確定性地播種一個隨機數字生成器並傳遞該生成器以創建密鑰。我的代碼是:

SecureRandom random=SecureRandom.getInstance("SHA1PRNG"); 
random.setSeed(1234); //something device specific will be used to set this 
KeyPairGenerator keyGen=KeyPairGenerator.getInstance("RSA"); 
keyGen.initialize(1024, random); 

KeyPair pair=keyGen.generateKeyPair(); 
PublicKey pub=pair.getPublic(); 
PrivateKey priv=pair.getPrivate(); 

生成的密鑰與運行不同。但是,從運行到運行SecureRandom數字是相同的,甚至在不同設備上相同。

我錯過了什麼?我怎樣才能重複生成這些密鑰?

謝謝

+0

你爲什麼要這樣做?當然,如果你不想存儲RSA密鑰對,那麼你也不想存儲用來生成RSA對的隨機種子?奇怪的是,這段代碼並沒有按照你想要的那樣做,但對我來說,似乎你可能會這樣做,而沒有想到它通過 – 2012-04-16 06:00:09

回答

8

你在做什麼?即使這樣做,這段代碼也會依賴Android上的SHA1PRNG實現,所以它可能隨時崩潰。一般來說,setSeed()增加了熵,所以即使您使用相同種子種子SecureRandom,也不能保證獲得相同的數字。如果您在桌面Java上嘗試此代碼,它很可能會失敗。到目前爲止,它適用於大多數(全部)當前的Android版本,但不能保證。

如果您需要可預測的密鑰,則可能需要爲每個設備配置預先生成的密鑰。如果您需要安全地存儲它們,請在ICS上使用KeyChain API,或者在ICS前設備上使用密碼保護的密鑰庫。即使你沒有存儲真正的密鑰,如果有人知道密鑰是如何生成的(種子),它們可以生成相同的密鑰,並且你的密鑰只與種子一樣安全。如果它是特定於設備的,那麼很可能不難找到。

至於爲什麼這不起作用,RSA密鑰生成器基本上在循環中生成隨機BigIntegers,測試素數。主要測試是概率性的,所以你可能會在每次運行中選擇不同的素數。你可能想要得到SpongyCastle,在模擬器上運行它並在RSAKeyPairGenerator.java中設置斷點來檢查究竟發生了什麼。

+0

感謝關於密鑰生成器如何工作和SpongyCastle實現的詳細解釋。這是(誤導)嘗試最大限度地減少應用內購買內容盜版的一部分。我的希望是我可以加密服務器上的內容,並在沒有密鑰交換的情況下將其交付給客戶端,並即時解密內容。我必須在服務器上生成密鑰對,將私鑰傳輸給客戶端,然後使用KeyStore(如您所建議的)以及一些算法生成的密碼來增加難度。 – Aaron 2012-04-17 02:57:00

+0

我看到(種)。您正在嘗試實施各種DRM。 RSA可能不是最好的。如果您將密鑰傳輸給客戶端,您自然需要確保安全地發生這種情況,這可能並不容易。在想法是將一些設備特定位(IMEI等)放入IAB developerPayload中,並在驗證服務器上的簽名時獲取它。然後使用它來生成綁定到該特定設備的對稱(AES)密鑰,對內容進行加密並將其發送到設備。設備然後生成相同的對稱密鑰,並解密內容。 – 2012-04-17 03:35:48

+0

當然,您可能需要散列IMEI等,以便您不收集實際的設備識別信息。 – 2012-04-17 03:42:40