I've built a Java app that exposes web-services to external authorized clients. The Web-services use WS-security with Certificate Authentication. Basically we act as custom Certificate Authority - we maintain a java truststore on our server and sign and add clients' certificate to it. Currently we have manual registration process that requires WS clients to upload their certificate signing request. We sign the CSR, add the certificate to our java truststore using keytool from the command line and return signed certificate along with our CA certificate to client. In turn clients use their private key to sign their soap message payload and embed signed certificate in the message. Server side decrypts the digital signature and verifies that the embedded certificate is signed and one matches our truststore before fulfilling client request.
Though little painful (because of manual labor) this setup is working fine. Now I've realized that our root CA certificate is about to expire soon and hence I'm looking to setup maintenance policy. how should I go about renewing the self-signed root CA certificate? Looks like I will have to create new and replace original. And that will impact all clients having to receive new certificate and import new CA certificate. Is that correct understanding or if there is better way to handle the situation?
If it matters, I have used openssl to generate original key-pair.
openssl req -x509 -newkey rsa:1024 -keyout cakey.pem -out cacert.pem -config openssl.cnf
Keeping the same private key on your root CA allows for all certificates to continue to validate successfully against the new root; all that's required of you is to trust the new root.
More info
Related
I have a Java program that connects to an https remote webservice which exposes a TLS certificate of this structure:
Webservice certificate
Signed with some certificate
Signed with some corporate certificate
Now, when my Java app makes a https request to that webservice it fails due to invalid certificate. This is normal, so I added the webservice direct certificate to the Java/lib/security/cacerts file.
But this didn't work, I still had the certificate exception.
After a long debugging session and hours wasted, I tried to add all three individual certificates, and this time it worked. But why ?
Why does Java checks the full certificate path even though the direct certificate is made trusted ?
Is this behavior as per SSL/TLS RFCs ? Will this behavior occur with other tools/languages like curl ?
Thanks.
... so I added the webservice direct certificate to the Java/lib/security/cacerts file
The webservice certificate is not a CA certificate, so it does not belong in cacerts in the first place (as the name indicates). A CA certificate is a certificate which is used to sign other certificates, a webservice certificate is a leaf certificate which cannot be used to sign other certificates.
Will this behavior occur with other tools/languages like curl ?
This is a common behavior. With OpenSSL based tools one usually needs to provide the root CA (and of course the chain to it), only with X509_V_FLAG_PARTIAL_CHAIN it will accept when parts of the chain a specified as trusted.
I have been practicing creating self-signed certificates and making a request to an api over https.
I used webclient and netty ssl context, I imported the certificate into cacerts and a keystore in resources, and it worked.
But if a third party app uses a certificate signed by a CA, do I need to do this? Can I simply use webclient.baseUrl(https://....), and then make requests? Will the OS and Java handle the rest?
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.
Some quick background on what I'm trying to do: a client is using a third party web service that requires mutual authentication. The service requires the client certificate be signed by a public certificate authority (ie: not self-signed). The client has some software written in Java that connects to the service, hence they used Java keytool to generate the original signing request and the key/certificate are stored in a jks keystore.
Our software that the client is going to be using is written in C#/.NET and will need to connect to the third party web service. As such we will we need to be able to access the client certificate.
I can't seem to find any way to export the certificate (along with private key) to either the Windows Certificate Manager or some other format that can be opened by .NET security libraries.
Exporting to a PKCS12 file does not work because keytool does not support it for trusted certificates (not sure if that is a keytool limitation or a limitation of the format).
I also found some Java code for getting the private keys, but I can't seem to figure out how I can get that into Windows Certificate Manager and associate it with the certificate. (How do I list / export private keys from a keystore?)
As a side note, the client doesn't want to generate a new certificate as there is a whole process involved in sending it to and getting it approved by the third party service they are connecting to.
Ultimately I'm hoping there are some commands I can run with keytool/openssl/etc that will allow the certificate & key to be exported/transferred into the Windows Certificate Manager (or some format that it can import).
(Sorry if my terminology is off or if some of this doesn't make sense. I kind of got stuck supporting this despite not being all that familiar with managing certificates.)
This seems to work for exporting the certificate but not the entire chain, the trick is to specify the srcalias:
keytool -v -importkeystore -srckeystore .keystore -srcalias mykey -destkeystore myp12file.p12 -deststoretype PKCS12
Thanks to Warren for pointing me to this: How to export private key from a keystore of self-signed certificate
I hope this isn't a duplicate.
I'm currently working on client server game based on netty with a client on Android. I'm trying to make a secure login process so I tryed using ssl on top of java socket.
I managed to create a self-signed certificate and to use SSL. The problem is that the example source code i found use à custom TrustManagerFactory which doesn't make any check upon certificate validity. Since I don't wan't to allow Man In The Middle attack i searched for more information on SSL handshake and here is what i understood:
To initiate SSL session, the client send a request to the server.
The server which own the certificate(.jks or .bks) extract public informations into a X509 certificate and send it to the client.
The client check for the validity of the certificate ( In my current solution do nothing)
If check succed retrieve the server's public key from the certificate, generate a random key, encrypt it with the public key and sends it to the server.
The server use his private key to decrypt the randomly generated key.
Both client and server now share the same random key and they start a comunication using this key for symetric encryption ( like AES ).
I don't need to accept certificate from anyone else than my own server so i thought about 2 solution:
Save the X509 on client side and create à custom TrustManager witch only accept this certificate. This solution seems easy to implement but rather hard to maintain since every certificate change on server side would need to update X509 certificate on every client.
Create my own CA certificate sign my ssl certificate with this certificate and manage somehow to tel my client to only trust all certificate signed with my CA.
What i understood about CA authentification is this :
A CA root certificate is a normal certificate that contain a key pair.
signing a certificate with a CA mean adding at the end of the being-signed certificate a hash of the whole certificate encrypted with the CA private key.
this signature is contained in the X509 certificate along with some informations about CA.
To check certificate validity, the client generate certificate hash and compare it to the decrypted hash (using CA public key) contained in the X509 certificate.
So if i'm not mistaking in all of this, if i want to implement my second solution, I need to provide a CA certificate to the client so that he can check certificates. I've seen that it is possible to init à TrustManager with a truststore. I asume it must be a different certificate from the root CA one since the whole security of this depends on my CA private key 's confidentiality. So my questions are :
What should this client truststore contain and how to generate if from my root CA ??
I have red that ssl engine is broken for self signed certificate. So is my second solutions viable on android?
If this can work, how can i invalidate my certificate if i see that someone manage to get my private key somehow? I have red things about crl but i don't know how to generate/use them in my truststore?
thanks in advance.
I can only answer part of your questions:
The truststore should contain your CA, you can generate it with keytool:
http://docs.oracle.com/cd/E19509-01/820-3503/6nf1il6er/index.html
No problem you can implement this in android in the same way than in java using java.security.* and org.apache.http.* classes. One warning, for android versions <=2.3, you could need to implement a workaround as some public CA are missing and it doesn't support miss-ordered certificates chains. I can give you more details if needed.
I don't know
Edit:
A good turorial:
http://nelenkov.blogspot.com/2011/12/using-custom-certificate-trust-store-on.html