5

我有一个生成 SecretKeys 的应用程序,每个客户端一个。这些需要保存在我们的数据库中。我真的不熟悉常见的安全模式或实现,我正在寻找建议。

KeyStore 类似乎被广泛使用,尤其是用于保护 SecretKey。但是,我很少提到将 KeyStore 与数据库一起使用,我试图弄清楚这是因为它是基本用法(因此未提及),还是因为这是一种不好或多余的方法,我真的应该正在使用不同的技术。

基本设计是每个用户都有自己的密钥库,通过转换为字节(我认为使用 load() 和 store())将其保存/加载到数据库中或从数据库中加载。

到目前为止,这个设计有什么问题吗?我也想知道我应该如何处理 KeyStore 的密码。我们正在考虑只对所有 KeyStore 使用一个密码,但是我们如何在没有密钥库的情况下安全地存储这个?

这意味着在后端应用程序中使用,客户端永远不会向我们传输密码,服务器端也没有人工操作员提供密码。

4

2 回答 2

5

在现实世界中,如果密钥要安全存储很长时间(从几小时到几年),它们会安全地存储在HSM中(重点是我的)。PKCS#11标准旨在帮助与此类系统进行交互,但我至少要声明一下 - 大多数 HSM 都有自己首选的与 HSM 交互的机制,而 PKCS#11 接口通常是一个残废的。

密钥也可以安全地存储在智能卡和 USB 令牌等其他设备中,但这意味着在大众中分发密钥,而不是用于后端系统的密钥存储。

然而,并不是每个人都能获得 HSM 的预算,并且使用了许多其他不太安全(而且显然更便宜)的替代方案。一些系统(我会以 Glassfish 应用服务器为例)存储一个主密码,用于保护其他密码。这同样适用于密钥 - 将有一个用于保护其他密钥的主密钥(在某种程度上,这类似于 HSM 在内部的工作方式)。当然,您随后会被困在保护万能钥匙上。在某些环境中,这很容易,因为您可以将密钥放在一个文件中,该文件仅限于系统管理员和应用程序,而不是其他任何人。

免责声明:这些都不应该被视为盲目摄取的建议:-)。如果需要不惜一切代价保护您的密钥,请投资 HSM。

于 2010-07-27T00:39:35.583 回答
4

因此,您正在使用 java 和密钥库。

你有两个我理解正确的问题?:

1)你需要一些建议

2)你想知道如何将这些东西存储到数据库中

回答问题1:所以在使用java时需要使用SSL。Java 已经实现了将通过 https 进行通信的类,它将为您执行 SSL 握手和一切!您唯一需要做的就是为此实现提供 java.security.KeyStore 。

基本上有两种类型的密钥库:

  • 首先是存储你信任的所有证书(多个证书)=> 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 配置在持久或更新之前或之后执行带注释的方法。如果您不使用注释和弹簧,您可以通过另一种方式实现这一点..

于 2013-03-08T09:57:21.513 回答