0

我需要在客户端机器上对数据进行签名和加密。之后,我将使用 SFTP 将文件发送到服务器计算机。在服务器上,我想验证签名并解密数据。

这个方案安全吗?我应该怎么做才能提高安全性?

我正在执行以下步骤:

  1. 创建 Java 密钥库;
  2. 创建自签名 X509 v3 证书并将其插入 JKS 密钥库;
  3. 将此 JKS 密钥库提供给客户端和服务器;
  4. 签名数据:从 JKS 密钥库中获取私钥和​​证书,并使用CMSSignedDataGeneratorand对数据进行签名CMSSignedData
  5. CMSEnvelopedDataGenerator使用;加密上一步的有符号字节

在服务器端,我执行以下步骤:

  1. 加载 JKS;
  2. 从 JKS 检索私钥;
  3. 检索 CMSEnvelopedData 并获取 Content;
  4. 加载 X509 证书并使用 CMSSignedData 验证签名并恢复数据;

我只有一个公私钥对。我正在使用 Bouncy Castle 和 PKCS 7。


JKS的创建:

public static KeyStore createKeyStore() throws Exception {
         KeyStore keyStore = KeyStore.getInstance("JKS");
         keyStore.load(null, null);

    X500PrivateCredential rootCredential = createRootCredential();
    X500PrivateCredential interCredential = createIntermediateCredential(
            rootCredential.getPrivateKey(), rootCredential.getCertificate());
    X500PrivateCredential endCredential = createEndEntityCredential(
            interCredential.getPrivateKey(),
            interCredential.getCertificate());

    keyStore.setCertificateEntry(rootCredential.getAlias(),
            rootCredential.getCertificate());
    keyStore.setKeyEntry(
            endCredential.getAlias(),
            endCredential.getPrivateKey(),
            ConfigurationClass.PRIVATE_KEY_PASSWORD.toCharArray(),
            new Certificate[]{endCredential.getCertificate(),
                interCredential.getCertificate(),
                rootCredential.getCertificate()});

    keyStore.store(new FileOutputStream(ConfigurationClass.JAVA_KEY_STORE_PATH), ConfigurationClass.KEY_STORE_PASSWORD.toCharArray());
    return keyStore;
}
4

2 回答 2

2

不要这样做。只需通过 SFTP 传输数据,但使用证书(由服务器颁发)进行身份验证。根据这篇文章,这可以通过JSch 库来完成。

如果您在发送数据之前对数据进行了加密,然后在之后立即对其进行解密,那么您所做的是传输安全,而不是静态数据安全。

滚动你自己的加密,即使你是用好的原语组装它,也是不好的,而且通常会失败。就你正在做的事情而言,你至少有两个问题:

  1. 您需要对加密数据进行加密然后签名,以防止诸如 Padding oracle 攻击之类的事情
  2. 您的密钥管理可能会出现问题:

    1. 你如何处理新客户的到来?
    2. 是什么阻止了攻击者将他们的密钥添加到服务器?

      这似乎是一个愚蠢的问题,但实际上,如果您有一个外部服务提供服务器密钥,那么服务器如何验证该服务?正确的方法是让服务器发出在其(自签名)“root”权限下签名的密钥(这也可能是您拥有的其他一些受信任的服务器)。

于 2012-08-22T15:02:00.973 回答
1

你所描述的肯定是不安全的。私钥不应该旅行;密钥对通常在需要它们的位置生成。

您需要做的是使用自签名证书创建某种基础架构 CA。您应该为此非常安全地保存私钥(实际上,由于私钥仅用于签署其他证书,您可以将其存储在保险箱中)。

现在,您在客户端和服务器上都生成了两个密钥对和两个证书请求。将两个证书请求都发送到基础架构 CA。该 CA 应签署请求(并添加数据),生成证书。证书被发送到客户端和服务器,将它们添加到它们自己的(受密码保护的)JKS 存储中。

现在要传输数据,您应该使用服务器的公钥加密,然后使用客户端的私钥签名。服务器应首先验证客户端的签名,然后使用自己的私钥解密。如果你不这样做,你很容易受到填充 oracle 攻击。为此,它需要 CA 证书来验证证书链。

在继续之前,请尝试尽可能多地了解 PKI。请记住,您的方案仅与您的私钥(以及 JKS 密码)一样安全。我描述的只是大体结构,还有很多实现细节。

注意:我忽略了 SFTP,因为您也没有扩展到它。严格来说,你应该不需要它。

于 2012-08-26T00:04:00.920 回答