【问题标题】:openssl der files importing into java keystoreopenssl der 文件导入到 java 密钥库
【发布时间】:2020-04-08 14:28:24
【问题描述】:

我使用 openssl 创建了一个密钥对,并希望将它们导入 java-keystore:

1) openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out my_privatekey.pem
2) openssl rsa -pubout -outform DER -in my_privatekey.pem -out mypublic_key.der
3) openssl pkcs8 -topk8 -nocrypt -outform DER -in my_privatekey.pem -out my_privatekey.der

首先,我创建一个私钥(.pem 格式),然后我创建一个公钥,最后我将私钥转换为可以在 java (pkcs8) 中使用的格式。

现在,我想在我的 java 应用程序中以安全的方式使用这些密钥,所以我做了一些研究,解决方案似乎是使用 java-keystore。

但是,如果我是正确的,您无法将公钥直接存储到密钥库中,因为您必须先创建证书:

将您的证书转换为 DER 格式:

openssl x509 -outform der -in certificate.pem -out certificate.der

导入密钥库

keytool -import -alias your-alias -keystore cacerts -file certificate.der

这让我现在提出我的问题。是否可以在没有证书的情况下将私钥和公钥导入密钥库?我不需要证书,因为我只想安全地存储我的密钥,因此它们受密码保护。

如果这是不可能的,那么您可以创建并签署您自己的证书。 但是,证书可能会过期,所以一段时间后我必须总是更新它还是我错了?

我与第三方共享此公钥(他们需要此密钥来验证我用我的私钥签名的数据),我还从他们那里获得了一个公钥来加密一些数据。所以我需要在最后存储 2 个公钥(我的密钥和我收到的公钥)。

我该怎么做? 我是否需要创建 2 个证书作为 hack,以便能够将它们存储到 java-keystore 中?

【问题讨论】:

    标签: java openssl public-key-encryption


    【解决方案1】:

    除此之外:对于不需要genpkey 然后是pkcs8 -topk8 -nocrypt -outform der 的密钥对; genpkey ... -outform der (without -$cipher) 将创建 PKCS8-clear DER,JCE 直接支持的格式。就此而言,即使是 PKCS8-clear PEM 也可以通过剥离标题和结尾行并解码 base64 来轻松处理。对于 2010 年 1.0.0 之前的 OpenSSL 所需的 其他 命令(genrsa;gendsa;ecparam -genkey),情况并非如此,这是您会发现很多关于这一切的错误建议的部分原因在全球范围内复制。

    java.security.KeyStore API 仅支持将 PrivateKey 值与证书链(可以是单个证书)一起存储。它还支持存储单独的证书(以验证来自其他人的签名或加密数据),但不支持单独的公钥。所以是的,您必须创建(或以其他方式获得)证书

    如果您不想要真实证书的安全功能,通常的约定是创建一个“自签名”证书——遵循标准 X.509v3 格式并包含公钥的证书,但由其自己的 密钥(特别是与证书中的公钥匹配的私钥)而不是任何 CA 的密钥签名。 OpenSSL 可以通过几种方式做到这一点,比如通常推荐的

    openssl genpkey ... -out priv.pem 
    openssl req -new -key priv.pem -x509 ... -out cert.pem
    

    或者您可以将密钥生成和证书创建与更简单的结合起来

    openssl req -newkey rsa:2048 -keyout priv.pem -nodes -x509 ... -out cert.pem
    # this doesn't support all the options of genpkey 
    # but it does support the simple case you are using
    

    也可以拆分'req'和'sign'步骤:

    openssl genpkey ... -out priv.pem
    openssl req -new -key priv.pem ... -out csr.pem
    openssl x509 -req -in csr.pem -signkey priv.pem ... -out cert.pem
    # or
    openssl req -newkey rsa:2048 -keyout priv.pem ... -out csr.pem
    openssl x509 -req -in csr.pem -signkey priv.pem ... -out cert.pem
    

    然后,您可以编写(简单)代码来读取私钥和证书并创建一个 KeyStore 条目——如果您愿意(您可能会这样做)并坚持下去。然而keytool 不能直接这样做。您可以改为使用openssl pkcs12 -export 将两个 OpenSSL 文件组合成一个 PKCS12 文件,该文件是密码加密的,可直接用作当前支持的 Java 中的密钥库。对于真正的旧 Java,您可能需要使用 keytool -importkeystore -srcstoretype PKCS12 [-deststoretype JKS] ... 将 PKCS12 文件转换为 JKS 文件,这是您会发现被广泛复制的另一条建议。

    或者,除非您需要 OpenSSL 文件来做其他事情,否则keytool 可以一次完成整个工作;只需根据需要执行keytool -genkeypair -keyalg rsa -keysize 2048 -keystore $file 以及-validity-dname 等其他选项,它将为其生成密钥对自签名证书并将私钥与自签名证书一起存储在受密码保护的密钥库文件中。 (通过 j8 默认为 JKS,但您可以另外指定;j9+ 默认为 PKCS12。)

    但是,证书可能会过期,所以一段时间后我必须总是更新它,还是我错了?

    过了一段时间,是的,但那个时间可能是几千年。我怀疑到那时您和第三方都将不复存在,而且可能 Java 将不再存在,因此 Java API 施加的要求将不再重要。请注意,在 32 位系统上的旧版本 OpenSSL——今天每个都很少见,并且组合更罕见——有时会受到“Y2038”问题的影响,而现在只有 18 年的未来——很多 em> 今天使用的系统到那时可能会过时,但不是全部。 Java 使用自己的时间戳格式,从来没有这个问题。

    CA 颁发的证书的生命周期通常要短得多,很少超过 1-2 年,有时甚至更短(例如,LetsEncrypt 为 90 天),但这不是证书固有的规范和代码。

    我需要创建 2 个证书作为 hack,以便能够将它们存储到 java-keystore 中吗?

    是的。确切地说,您当然需要为自己的密钥创建一个(虚拟)证书。对于对方的密钥,如果 他们 创建(虚拟)证书会更容易。你不能为他们创建一个自签名证书,因为你没有他们的私钥——或者至少你不应该。您可以创建一个稍微复杂的结构,在其中创建一个虚拟 CA 并使用它为它们签署证书,然后导入并使用该证书。如果需要,我会扩展,但这正如我所说的更复杂,而设置了许多常用工具来让他们很容易地做到这一点。

    【讨论】:

      【解决方案2】:

      “keytool -importcert”命令可以轻松读取 PEM 和 DER 格式的证书。

      keytool -importcert -file <openssl_crt.pem> -keystore <jks-file-name.jks> -storepass jkspass -alias <alias-name> -keypass <keypass>
      

      keytool Importing Certificates in DER and PEM

      【讨论】: