我有一个生成SecretKeys的应用程序,每个客户端一个。这些需要保存在我们的数据库中。我真的不熟悉常见的安全模式或实现,我正在寻求建议。
KeyStore类似乎被广泛使用,尤其是保护SecretKeys。但是,我看到很少提及将KeyStore与数据库一起使用,我试图弄清楚它是否是因为它是基本用法(因此没有提及),或者是因为这是一个糟糕或冗余的方法,我应该真的使用不同的技术。
基本设计是每个用户都有自己的密钥库,通过转换为字节来保存/加载到数据库中(我认为使用load()和store())。
到目前为止,这个设计有什么问题吗?我也想知道如何处理KeyStore的密码。我们只考虑对所有KeyStore使用单个密码,但是如何在没有密钥库的情况下安全地存储这个密码?
这适用于后端应用程序,客户端永远不会向我们传输密码,服务器端也没有人工操作员提供密码。
答案 0 :(得分:4)
在现实世界中,秘密密钥安全地存储(强调我的)HSM如果它们要安全存储,则需要延长一段时间(从几小时到几年)。有PKCS#11标准旨在帮助与这些系统连接,但我会说最少 - 大多数HSM都有自己的首选机制来连接HSM,而PKCS#11接口通常都是成为一个残废的人。
秘密密钥也可以安全地存储在其他设备中,如智能卡和USB令牌,但这是用于大众的密钥分发,而不是后端系统的密钥存储。
然而,并非每个人都获得HSM的预算,并且使用了许多其他不太安全(并且明显更便宜)的替代方案。某些系统(我将以Glassfish应用程序服务器为例)存储主密码,用于保护其他密码。这同样适用于密钥 - 会有一个主密钥用于保护其他密钥(在某种程度上,这类似于HSM在内部的工作方式)。当然,您仍然坚持使用主密钥。在某些环境中,这很容易,因为您可以将密钥放在仅限于系统管理员和应用程序的文件中,而不是其他任何人。
免责声明:这些都不应被视为盲目摄取的建议:-)。如果需要不惜一切代价保护您的密钥,请投资HSM。
答案 1 :(得分:3)
所以你使用的是java和keystore。
我有2个问题,我理解正确吗?:
1)你需要一些建议
2)你想知道如何将这些东西存储到数据库中
回答问题1: 所以当使用java时你需要使用SSL。 Java已经有类的实现,它们将通过https进行通信,它将为您执行SSL握手和一切!您需要做的唯一事情是将java.security.KeyStore提供给此实现。
基本上有两种类型的密钥库:
第一个是存储您信任的所有证书(多个证书)=> Keystore.getInstance( “JKS”)
第二个是用它的私钥=>来保存你的客户证书(只有一个) Keystore.getInstance( “PKCS12”);
如何制作私钥和证书,我在此不再讨论。我假设你已经在那里..(如果没有,你可以找到)。但KeyStores受密码保护。所以一般来说,如果没有人可以破解你的数据库,它们是安全的。如果您存储密码以在同一个表中打开您的密钥库,那么请注意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配置在持久化或更新之前或之后执行带注释的方法。如果你不使用注释和弹簧,你可以通过另一种方式实现这一目标。