It's confusing that keystore generated by keytool contains a self-signed certificate using following command:
keytool -genkey -keyalg RSA -keysize 1024 -keystore bob.keystore
It doesn't make sense to generate self-signed certs because you want a trusted CA to sign your cert request. How to generate a non self-signed keystore?
keytool -genkey is a dual operation: it generates a key-pair, and wraps it in a self-signed certificate.
Having this self-signed certificate really is just a convenience, partly linked to the storage format, that is just temporary if you want to use that key-pair for a CA-issued certificate.
You'll need to extract the certificate request from that key-pair, using the information you've entered when using -genkey (this information ended up in the self-signed cert). Re-use the alias name you've used with -genkey:
keytool -certreq -alias somename -file somename.csr -keystore mykeystore.jks
Send the CSR to your CA and, when you get the certificate back, re-import it against the same alias. This will overwrite the self-signed certificate that was generated initially, using keytool -importcert. Beware you may need to import the whole chain at once, if there are intermediate certificates, as described at the end of this answer.
Self-signed certs are valuable in many contexts, such as communications between instances of an application. It can be prohibitively expensive to pay a CA to sign certs in that situation.
If you want a recognized CA's signature, though, you will need to get your cert from the CA. You can't create a cert signed by a recognized CA simply using keytool. Search the search engine of your choice for "SSL certificate." Most certs are paid, like GeoTrust. Others, like StartSSL or the forthcoming LetsEncrypt, either are free or have a free option.
Related
we run a standard web API over https with a regular purchased SSL certificate. Our clients just access it via https, the certificate is trusted via default system RootCA.
A new client is using a Java communication server that requires the certificate in a PKCS12 keystore. How can we generate the PKS12 keystore from our key/csr/crt/pem files?
I did some research, most examples are requiring a private key. Of course I do not want to share our private key with the client.
Can a PKCS12 keystore be created without private key, similar to standard RootCA in browsers?
Thanks, bluepuma
YES-ish.
Although PFX-now-PKCS12 was designed primarily to store or transfer a privatekey and cert and chain cert(s) as a clump, and most commonly is used for that, it is capable of storing one or more 'lone' cert(s) not matched to any privatekey. And you are correct the client wanting to connect to you should have in their truststore ideally the root cert for your server cert's chain, or alternatively your server cert itself, but decidedly not your privatekey.
openssl can actually create such a PKCS12:
openssl pkcs12 -export -in certfile.pem [-name $name] -nokeys -out blah.p12
# if you don't specify -name it defaults to 1 (the digit one) which can be mildly confusing
# instead of being prompted for the password you can use -passout with several forms
# described on the openssl man page, but consider the warning below
But the result won't work in Java if they use the standard (Sun/Oracle/OpenJDK) cryptoproviders, which (in 8+) support lone cert(s) in a PKCS12 as 'trustedCert' entries in Java only if the(each) certbag has a special Sun-defined attribute which the Java providers write when they create such a file, but OpenSSL doesn't.
Instead use Java's keytool in 8:
jre8/bin/keytool -importcert -keystore blah.p12 -storetype pkcs12 -file $certfile [-alias $name]
or in 9+ where pkcs12 is now the default:
jre9+/bin/keytool -importcert -keystore blah.p12 -file $certfile [-alias $name]
If you don't specify the alias it defaults to mykey. In both cases you can add -storepass $pw to avoid being prompted for it, but as a result the password will be visible on your screen, in the command history of your shell or other command processor it is has one, and in most cases to other processes run on your system concurrently, (any of) which may be a security issue or not. You can also add -noprompt to avoid the confirmation prompt.
But user207421 is (roughly) correct that using such a truststore can break other SSL/TLS connection(s) made from their system, at least from the same JVM, unless the individual calls specify individual, separate truststores, and if they had coded that they would know how to handle (and ask for) a simpler certificate format, such as PEM.
Reading through some URLs and it fairly common for stating that the following command is used to create a public/private key pair.
keytool -genkey -alias mydomain -keyalg RSA -keystore keystore.jks -storepass password
Then it continues on and indicates the following command is used to create a self signed certificate.
keytool -genkey -alias selfsigned -keyalg RSA -keystore keystore.jks -storepass password -validity 360
From what I see, the only difference is adding "-validity 360".
Question 1 - Does simply adding "-validity 360" change from generating a key pair to a self-signed certificate?
Question 2 - Are "key pairs" and "self-signed certificate" essentially synonymous?
Question 3 - could either the key pair or "self-signed certificate" be used for an official CSR?
Question 1 - Does simply adding "-validity 360" change from generating a key pair to a self-signed certificate?
No. -genkeypair (the official name since about 2005) or the less accurate synonym -genkey always generates a keypair and a selfsigned certificate, and stores the privatekey and the cert (together) in the keystore. The only difference -validity 360 makes is whether the specified value or the default value is used for the validity period.
Question 2 - Are "key pairs" and "self-signed certificate" essentially synonymous?
No. In this situation they are linked, but they are different things. A keypair, and separate privatekey and publickey, can be used for some things without any certificate (selfsigned or otherwise) using storage other than a Java keystore, and a selfsigned cert (which includes the publickey) can be used for some things without the privatekey. For example SSH normally uses the 'bare' keypair for server authentication and frequently for client authentication. PGP uses a signed-publickey format that functions as a kind of certificate but very much unlike the X.509/PKIX certificates used in a Java keystore, and in SSL/TLS/HTTPS/etc and codesigning (and SMIME).
As an analogy that comes up frequently on travel.SX, consider an airline ticket and a suitcase of clothes. When you buy an airline ticket traditionally it included the ability to have a certain amount of luggage, often a few suitcases up to a weight limit, carried with you on your flight -- though nowadays this varies in widely disliked and contentious ways. It is possible to ride an airplane flight without taking a suitcase if you want, although it means at your destination you may not have any clothes to wear. It is also possible and fairly common to use a suitcase to carry clothes without an airline ticket in many places other than an airplane, such as a car, cab, bus, train, or relative's or friend's house.
Question 3 - could either the key pair or "self-signed certificate" be used for an official CSR?
A key pair could be used to generate a CSR(*) if you provided the subject name from another source. But Java keystore doesn't actually store key pair plus self-signed cert, but rather private key plus self-signed cert (or other cert); the public key is accessibly stored only in the cert, and the public key (from the cert) is needed and used to generate the CSR.
A self-signed cert, or any other cert, by itself cannot be used to generate a CSR(*) because the CSR must be signed using the private key.
(*) Actually CSR is a generic concept and there are many kinds of CSR with varying rules. I am talking here about only the kind of CSR specified by PKCS10 aka RFC2986 et rel, which is the (only) one generated by Java and most other common tools, and the one required by practically all Internet CAs.
You're quite right, the self-signed certificate and a CSR request both start with the keytool -genkey command. The difference is what you do with it next.
For a self-signed certificate there's not much more to do. You might to export it, to install as a trusted certificate at the client end, with keytool -export:
keytool -export -alias selfsigned -file selfsigned.cer -keystore keystore.jks -storepass password
For the CSR request, you would then create this with keytool -certreq:
keytool -certreq -alias mydomain -file mydomain.csr -keystore keystore.jks -storepass password
Up to you with the validity period. It's not crucial for either route, though with a self-signed certificate you'll typically want more than the default of 90 days.
We are at a big organization with a several applications that are developed for internal and external use. One of those application is distributed as Java Webstart application and after a lot of trial and error we now have proper signing and packaging in place.
The only problem: we use a self-signed certificate. Users see a warning about an unknown/unverified vendor and this is just not nice.
Fortunately, the IT department of the organization has one certificate that is accepted on all workstations (via a site-wide policy, I assume). If we use this accepted certificate to sign the JARs and create the Webstart archive, everything should be fine. Naturally, the IT department does not want to distribute the accepted certificate to all developers or put it on the build server, because this would be against the purpose and introduce a lot of vulnerabilities.
What would be the right way to generate a code-signing certificate signed by this accepted certificate?
My assumption, based on what I know from normal openssl procedures to generate certificates used in web servers:
Generate a CSR with
Send CSR to IT security
IT generates a certificate from the CSR with accepted certificate. This certificate should have a short validity (1 week / 1 month / 1 quarter ?)
Import into java keytool for signing
Make sure keytool is only available to authorized users
Would this work? Are there any objections in terms of security or organizational obstacles?
If the above is correct, I would need some pointers especially with item 3. I found a somewhat related question: How do you sign Certificate Signing Request with your Certification Authority?.
Any help is appreciated.
If the corporation has its own CA root cert, which yes had to be pushed to every client/relier by some means such as GPO or installing all systems (or maybe their JREs?) from a customized image, then your approach is almost correct:
generate keypair and CSR
send CSR to corporate CA, they send you back cert
combine cert with keypair in keystore and use keystore
You can do all steps but the last with OpenSSL, but it's extra work:
1: openssl req -newkey or openssl genpkey|genrsa|etc then openssl req -new
3: openssl pkcs12 -export plus keytool -importkeystore -srcstoretype pkcs12
Since you want to end up with a Java keystore it's easier to just use Java throughout:
1: keytool -genkeypair then keytool -certreq
3: keytool -importcert
keytool is a program available on every machine that has any JRE installed; you can't effectively restrict it. It is the keystore file containing your keypair (and specifically your privatekey) that must be protected. Use a strong password; set file/dir permissions/ACL; keep a secure backup; all the usual.
On the other hand, if the corporation has a code-signing cert (and key) which is trusted because the cert was obtained from (issued by) a well-known CA like Verisign, they almost certainly cannot issue you a subordinate certificate. Only a CA cert (with its key) can issue subordinate certs, and while technically it is possible for a trusted CA to issue your corporation a CA cert, if you then issue any bad certs it reflects on them and can put them out of business (see DigiNotar) and they don't want that.
Current situation:
We do a POST to a certain url using HTTPS/SSL. For this to work my (former) colleague posted this question: Java HTTPS client certificate authentication
So basicly we have a keystore in .p12 format and the truststore is a .jks file.
We have no control over the server that receives our POST request.
Issue:
The server admins have provided us with some new .der files because their old certificate was about to expire.
As I'm fairly new to SSL certificates and keytool- and openssl-commands I have no idea how to proceed from here.
1) Is it necessary to generate new .p12 and .jks files? Or do I only need to generate a new .jks file?
2) How do I generate these files from a .der certificate? I have found some websites with the most keytool/openssl commands but I haven't been able to successfully generate what I need.
The last command I tried (to no avail) was:
keytool -storepass dsmserver -keystore c:\temp\newkeystore.jks -importcert -alias "c:\temp\newcert.der" -trustcacerts
Wait, which certificate expired? If it was theirs, there shouldn't have been any need to send you a new file (after all, you don't have to update your browser when, say, stackoverflow.com's SSL certificate expires and they install a new one). If you're doing mutual authentication (client certificate authentication), then there are four certificates involved: your certificate, their certificate, the certificate of the authority that signed your certificate, and the certificate of the authority that signed their certificate. They send you their certificate and you check to see that it was properly signed by a certificate authority that you trust (that's what the truststore is for - it's a list of the certificate authorities that you trust to sign certificates from their side). Subsequently, you send your certificate and they check to see that it was properly signed by a certificate authority that they trust. (Of course, all of this is automatically done for you behind the scenes in JSSE by the SSL handshake procedure)
Remember, a certificate is a (signed) assertion that such-and-such name is identified by a particular public key. So if their certificate expired, they'll generate a new one, get it signed by a CA that you already trust, and replace the old one with this one. When your software (automatically, as part of the behind-the-scenes SSL handshake) gets the new one, it will check to see who the signer ("issuer") was and if it's in your list of trusted authorities (and properly signed). If this checks out, you'll accept it automatically. They don't need to send you anything out-of-band to make this happen, unless they're changing certificate authorities and you don't already trust the new one. If so, you can use
keytool -import -keystore <truststore> -file <certificate file> -alias <someca>
If, on the other hand, your certificate is the one that expired, then they shouldn't be sending you anything unrequested. Instead, you should be generating a CSR via:
keytool -genkey -alias <myalias> -keystore <keystore>.p12 -storetype pkcs12
keytool -certreq -alias <myalias> -file request.csr -keystore <keystore>.p12 -storetype pkcs12
This will update the keystore with a new private key and create a file named "request.csr" which you should then send to them (or to a CA that's in their truststore) for a signature. They will respond with a signed certificate which you will then import back into your keystore using:
keytool -import -alias <myalias> -file <signed certificate>.cer
If I had to guess, it looks like they tried to perform these three steps for you, and tried to send you the certificate and the corresponding private key, which is invalid - Java will (rightly!) try its best to stop you from importing that because the private key itself was tainted when they sent it over an untrusted channel (e-mail, I presume?) This defeats the purpose of PKI - nobody should ever have access to your private key except for you.
Download the file from the below link:ImportKey.Java
Run the following commands:
javac ImportKey.java
java ImportKey key.der cert.der
- arg1 is your key and arg2 iscertificate.
Commands will put your keys to Java Key Store.
I am confused on the process to create a valid certificate,signed by a CA, in java.
I know that java has the tool keytool to create public-private keys and certificates.
Also it supports JKS and PKCS#12.
So one can create a keystore with a public-private key pair and a certificate e.g.
keytool -genkey -keyalg RSA -alias aCert -keystore someKeystore.keystore
This will create a keystore with a certificate (self-signed).
So far I understand.
I can export the certificate for a csr request to send to a CA e.g. Verisign, without the private key of course.
After this part I am lost.
The CA will sign it and I will have to re-import it to my keystore?This will replace the original certificate already in keystore?
It will still be self-signed though.
Shouldn't the issuer be the CA itself?But then how is this possible?I just send the public key only and not a certificate?
Any help on clearing the process please?
UPDATE:
Is the CA signing the certificate (e.g. Verisign) also the issuer?Or it can sign a certificate that the issuer==subject?
Thanks
You're correct up to the point of CSR creation. You'll use something like this:
$ keytool -certreq -alias myalias -file myalias.csr -keystore keystore
to generate a CSR, which contains:
your public key (extracted from the self-signed cert)
the Distinguished Name (i.e. the name of the entity for whom the cert is requested)
and is signed with your private key. The CA then generates a new certificate with:
subject = your DN (either from the CSR or auto-generated using details you supplied during the application process)
issuer = the CA's DN
public key = from the CSR
which you need to import back into your keystore, replacing the original self-signed cert:
$ keytool -import -alias myalias -keystore keystore -file myalias.crt
Often CAs will sign your new certificate using an intermediate certificate which is in turn signed by a trusted root; in this case you should import the intermediate certificate before your own:
$ keytool -import -trustcacerts -alias intermediate -file intermediate.crt -keystore keystore
Edit: this obscure section from keytool's documentation is surprisingly clear (where it talks about a 'chain' of certificates, this just refers to the intermediate certificates that link yours to the root):
keytool can create and manage keystore "key" entries that each contain a private key and an associated certificate "chain". The first certificate in the chain contains the public key corresponding to the private key.
When keys are first generated (see the -genkey subcommand), the chain starts off containing a single element, a self-signed certificate. A self-signed certificate is one for which the issuer (signer) is the same as the subject (the entity whose public key is being authenticated by the certificate). Whenever the -genkey subcommand is called to generate a new public/private key pair, it also wraps the public key into a self-signed certificate.
Later, after a Certificate Signing Request (CSR) has been generated (see the -certreq subcommand) and sent to a Certification Authority (CA), the response from the CA is imported (see -import), and the self-signed certificate is replaced by a chain of certificates. At the bottom of the chain is the certificate (reply) issued by the CA authenticating the subject's public key. The next certificate in the chain is one that authenticates the CA's public key.
After the CA signs the cert it ceases to be self-signed. A self-signed certificate has issuer == subject. When the CA signs it, issuer becomes the CA, which corresponds to the subject in the CA's own certificate, which in turn is signed by another issuer, ... so you have a certificate chain, that terminates in a trusted root that is already in your truststore.