首页 文章

我的签名和加密方案是否安全?

提问于
浏览
0

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

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

我正在执行以下步骤:

  • 创建Java密钥库;

  • 创建自签名X509 v3证书并将其插入JKS密钥库;

  • 将此JKS密钥库提供给客户端和服务器;

  • 签名数据:使用 CMSSignedDataGeneratorCMSSignedData 从JKS密钥库获取私钥和证书并签署数据;

  • 使用 CMSEnvelopedDataGenerator 加密上一步的有符号字节;

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

  • 加载JKS;

  • 从JKS检索私钥;

  • 检索CMSEnvelopedData并获取内容;

  • 使用CMSSignedData加载X509证书并验证签名并恢复数据;

我只有一对公钥 - 私钥对 . 我正在使用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;
}

2 回答

  • 2

    不要这样做 . 只需通过SFTP传输数据,但使用证书(由服务器发出)进行身份验证 . 根据this帖子,这可以用JSch library来完成 .

    如果您在发送之前对数据进行了加密,然后在之后立即对其进行解密,则表明您正在进行传输安全性,而不是安全数据 .

    滚动你自己的加密,即使你是用好的原语组装它,也很糟糕,一般都会失败 . 在您正在做的事情中,您至少有两个问题:

    • 您需要对加密数据进行加密然后签名,以防止像Padding oracle攻击这样的事情

    • 您的密钥管理可能会出现问题:

    • 您如何处理新客户的问题?

    • 是什么阻止攻击者将其密钥添加到服务器?

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

  • 1

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

    您需要做的是使用自签名证书创建某种基础架构CA.您应该保持私钥非常安全(实际上,因为私钥只需要签署其他证书,您可以将它真正存储在保险箱中) .

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

    现在要传输数据,您应该使用服务器的公钥进行加密,然后使用客户端的私钥进行签名 . 服务器应该首先验证客户端的签名,然后用它解密's own private key. If you don'你可以成功填充oracle攻击 . 为此,它需要CA证书来验证证书链 .

    在继续之前尽可能多地尝试和理解PKI . 请记住,您的方案只能与您的私钥一样安全(因此也就是JKS密码) . 我所描述的只是一般结构,有很多实现细节 .

    注意:我没有忽略SFTP,因为你没有扩展到那个 . 严格地说,你不需要它 .

相关问题