问题
I created a keypair with openssl and want them to import into the 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
First, I create a private-key (in .pem-Format), then I create a public key and at the end I convert the private key into a format that can be used in java (pkcs8).
Now, I want to use those keys in a secure way in my java application, so I did some research and the solution seems to be by using the java-keystore.
However, if I am correct, you are not able to store the public key directly into the keystore, because you must create a certificate first:
convert your certificate in a DER format :
openssl x509 -outform der -in certificate.pem -out certificate.der
import into the keystore
keytool -import -alias your-alias -keystore cacerts -file certificate.der
This brings me now to my question. Is it possible to import the private and public key into the keystore without a certificate? I don't need a certificate, as I only want to store my keys securely, so they are password-protected.
If this is not possible, than you could create and sign your own certificate. However, a certificate can be expired, so after some time I have to always renew it or am I wrong?
I share this public key with a third-party (they need this key to verify the data which I signed with my private key) and I also get a public key from them, to encrypt some data. So I need to store 2 public keys at the end (my key and the public key which I receive).
How do I do that? Do I need to create 2 certificates as a hack, in order to be able to store them into the java-keystore?
回答1:
Aside: for just the keypair you don't need genpkey
and then pkcs8 -topk8 -nocrypt -outform der
; genpkey ... -outform der
(without -$cipher
) will create PKCS8-clear DER, the format JCE supports directly. For that matter even PKCS8-clear PEM can be handled easily enough by stripping the header and trailer lines and decoding the base64. This was not the case for the other commands needed in OpenSSL before 1.0.0 in 2010 (genrsa; gendsa; ecparam -genkey) which is part of the reason you will find lots of wrong advice about it all over the World Wide Copying.
The java.security.KeyStore API supports storing PrivateKey values only in conjunction with a certificate chain (which can be a single certificate). It also supports storing a lone certificate (to verify signatures from or encrypt data to someone else) but not a lone publickey. So yes you must create (or otherwise obtain) certificates.
The usual convention, if you don't want the security features of real certificate(s), is to create a 'self-signed' certificate -- one which follows the standard X.509v3 format, and contains the publickey, but is signed by its own key (specifically, the privatekey matching the publickey in the cert) rather than any CA's key. OpenSSL can do this several ways, such as the commonly recommended
openssl genpkey ... -out priv.pem
openssl req -new -key priv.pem -x509 ... -out cert.pem
or you can combine key generation and cert creation with the simpler
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
It is also possible to split the 'req' and 'sign' steps:
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
You can then write (simple) code to read in the privatekey and certificate and create a KeyStore entry -- and persist if you wish (which you presumably do). However keytool
cannot do this directly. You can instead use openssl pkcs12 -export
to combine the two OpenSSL files into a single PKCS12 file, which is password-encrypted and is usable directly as a keystore in currently supported Java. For really old Java you may need to convert the PKCS12 file to a JKS file using keytool -importkeystore -srcstoretype PKCS12 [-deststoretype JKS] ...
, another piece of advice you will find widely copied.
Alternatively, unless you need the OpenSSL files for something else, keytool
can do the whole job at once; just do keytool -genkeypair -keyalg rsa -keysize 2048 -keystore $file
plus other options like -validity
and -dname
as desired, and it will generate the keypair and a self-signed cert for it and store the privatekey with the self-signed cert in a password-protected keystore file. (Through j8 defaults to JKS but you can specify otherwise; j9+ defaults to PKCS12.)
However, a certificate can be expired, so after some time I have to always renew it or am I wrong?
After some time, yes, but that time can be several thousand years. I suspect that both you and the third-party will be defunct by then, plus probably Java will no longer exist so the requirements imposed by Java APIs will no longer matter. Note that older versions of OpenSSL on 32-bit systems -- each rare today and the combination rarer -- sometimes were affected by the "Y2038" issue, and that is now only 18 years in the future -- many systems in use today will probably be obsolete by then, but not all. Java uses its own timestamp format and never had this problem.
CA-issued certificates usually have much shorter lifetimes, rarely more than 1-2 years and sometimes much less (as a notable example, 90 days for LetsEncrypt), but that's not inherent in the certificate spec and code.
Do I need to create 2 certificates as a hack, in order to be able to store them into the java-keystore?
Yes. To be exact, you certainly need to create a (dummy) cert for you own key. For the other party's key, it's easier if they create the (dummy) cert. You can't create a self-signed cert for them because you don't have their privatekey -- or at least you shouldn't. You can create a slightly more complicated structure where you create a dummy CA and use it to sign a cert for them, which you then import and use. I will expand if needed, but this is as I said more complicated, whereas many common tools are set up to allow them to do it very easily.
回答2:
The "keytool -importcert" command had no trouble reading the certificate in both PEM and DER formats.
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
来源:https://stackoverflow.com/questions/59351313/openssl-der-files-importing-into-java-keystore