2010-07-27 51 views
4

我有一個應用程序生成SecretKeys,每個客戶端一個。這些需要保存在我們的數據庫中。我真的不熟悉常見的安全模式或實現,我正在尋求建議。密鑰庫使用的基本問題

KeyStore類似乎被廣泛使用,尤其是爲了保護SecretKeys。然而,我幾乎沒有提及使用KeyStore和數據庫,我試圖弄清楚是因爲它是基本的用法(因此沒有提及),或者是因爲這是一種糟糕或冗餘的方法,而且我應該真的正在使用不同的技術。我認爲每個用戶都有自己的keystore,它將通過轉換爲字節(使用load()和store()來保存/加載到數據庫和從數據庫加載)。

到目前爲止這個設計有什麼問題嗎?我也在想我應該如何處理KeyStore的密碼。我們正在考慮只對所有KeyStore使用單一密碼,但是如何在沒有密鑰存儲的情況下安全地存儲此密碼?

這意味着要在後端應用程序中使用,客戶端永遠不會向我們傳輸密碼,服務器端也不會有人工操作員提供密碼。

回答

4

在現實世界中,如果需要長時間(從幾小時到幾年不等)的安全存儲,祕密密鑰是安全地存儲在(強調我的)HSM。有一個PKCS#11標準可以幫助與這些系統連接,但我會說最少的 - 大多數HSM都有自己喜歡的與HSM接口的機制,並且PKCS#11接口通常變成了殘缺一。

密鑰也可以安全地存儲在其他設備中,如智能卡和USB令牌,但是這意味着在大衆化羣體中進行密鑰分發,而不是用於後端系統的密鑰存儲。

然而,並不是每個人都可以獲得HSMs的預算,還有很多其他不太安全(並且更便宜)的替代品。一些系統(我將採用Glassfish應用程序服務器的情況)存儲一個主密碼,用於保護其他密碼。這同樣適用於密鑰 - 將會有一個用於保護其他密鑰的主密鑰(在某種程度上,這與HSM的內部工作方式類似)。當然,然後你堅持保護主密鑰。在某些環境中,這很容易,因爲您可以將密鑰放在限制系統管理員和應用程序的文件中,而不是其他人。

免責聲明:這些都不應被視爲盲目攝入的建議:-)。如果您的鑰匙需要不惜一切代價得到保護,請投資HSM。

3

所以你使用的是java和keystores。

你有2個問題我沒有理解錯?:

1)你需要一些建議

2)你想知道如何將這種東西存儲到數據庫

回答問題1: 所以當使用java時,你需要使用SSL。 Java已經實現了可以通過https進行通信的類,它將爲您執行SSL握手和一切!你需要做的唯一事情就是爲這個實現提供java.security.KeyStore。

有basicly 2種類型的密鑰庫:

  • 第一是存儲所有信任的(多個證書)=> Keystore.getInstance( 「JKS」)

  • 第二證書是保留您的客戶端證書(只有一個)與它的私鑰=> Keystore.getInstance(「PKCS12」);

你如何製作你的私鑰和證書,我不會在這裏討論。我假設你已經在那裏..(如果沒有,你可以找到)。但KeyStore受密碼保護。所以一般來說它們是安全的,如果沒有人能夠破解你的數據庫。如果您在相同的表中存儲密碼以打開密鑰存儲庫,那麼請小心注意sql注入! 但是,讓我們假設這是安全的。密鑰庫使您可以使用現有的實現來處理SSL握手。所以基本上使用密鑰庫不是一件壞事。注意順便說一句,當需要相互認證時(意味着你也需要識別你自己),你將只使用PKCS12密鑰庫。

回答問題2: 是,你可以在數據庫中存儲密鑰庫,這是一個有點棘手。由於密鑰庫只允許他們使用他們的存儲和加載方法。但是你可以像這樣實現:

@Entity 
public class MyKeyStoreClass { 
private Long id; 
@Transient 
private KeyStore keystore; 
private String passwordForKeyStore; 
private Byte[] keyStoreAsBytes; 

@PreUpdate 
@PrePersist 
public void concertKeyStoreToBytes() { 
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
     keystore.store(byteArrayOutputStream, 
       passwordForKeyStore.toCharArray()); 
    keyStoreAsBytes = byteArrayOutputStream.toByteArray(); 
} 

@PostLoad 
public void getKeyStore() { 
    if (keystore == null && keyStoreAsBytes != null) { 
     keyStore = KeyStore.getInstance(getKeystoreType().getType()); 
     keyStore.load(new ByteArrayInputStream(keystoreAsBytes), passwordForKeyStore.toCharArray()); 
    }  
} 

上面的代碼可能不是100%正確的,因爲我寫在這裏(無編輯)。但它通常是你如何能做到這一點,我以前做過和它的工作這麼好運氣;) 注意之前或之後持續或更新我的Spring配置進行註解的方法。如果您不使用註釋和彈簧,則可以通過另一種方式實現此目的。