2010-07-27 52 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配置进行注解的方法。如果您不使用注释和弹簧,则可以通过另一种方式实现此目的。