Generating X.509 Certificates and sign emails with this certificate - java

I have successfully generated a root certificate, by this commandline under windows
openssl req -config openssl.conf -new -x509 -days 1001 -key keys/ca.key -out certs/ca.cer
My question to you is the following:
How can I generate certificates from this root certificate in java, and sign mails with this certificate? I am currently using the JavaMail library.

You need the Java Crypto API and a crypto provider.
This is a well-known Java crypto provider: http://www.bouncycastle.org/java.html
There are classes for generating and handling X509 certificates and signing content.
Here are several examples for creating signed e-mails with BouncyCastle.
http://www.docjar.org/docs/api/org/bouncycastle/mail/smime/examples/package-index.html
This example also generates keys/certificates:
http://www.docjar.org/html/api/org/bouncycastle/mail/smime/examples/CreateSignedMultipartMail.java.html
Good luck!

Related

Using SHA512 but signature algorithm is SHA1 with spongycastle

I am using the CsrHelper class from here:
Certificate enrollment process
but my default_signature_algorithm is sha512withrsa. Although, when I put the csr in a file to analyse it using openssl's tool to analyze the csr: openssl req -in file.txt -noout -text
The subject, public key algorithm are all fine. The issue is in the signature algorithm where it is sha1withrsaencryption It should be sha512withrsa.
What am I doing wrong? Is there a config file somewhere to modify. I have java 1.8.0_144

Generating SSL keys for MySQL command-line client encrypted connection

I have started a project using MySQL in the cloud and I need to set up an SSL connection to it for the MySQL command line client.
I received the ca.pem file from the MySQL server which has a ton of certificates in there.
I already sorted out the SSL connection in MySQL Workbench and in Java, after a certain amount of trying different things. I've all the certificates now in my Java installation's cacerts trust store, and I've configured Java and Workbench to find my public / private SSL keys in my client.jks store.
None of that though helps with the command line MySQL client. According to the MySQL docs Configuring MySQL to use Secure Connections, this is the way to launch it:
mysql --ssl-ca=ca.pem \
--ssl-cert=client-cert.pem \
--ssl-key=client-key.pem
and these params can be put in my.cnf to make the command line easier.
And this told me some of what I needed to know: MySQL on Amazon RDS i.e. how to point mysql on the command line to the server certificate. That was easy, considering the Java procedure required me to import the whole lot into the Java certificate store using a command line tool that only reads the first certificate and silently ignores the remainder.
So after all faff with Java, and from the beginning having a public/private key pair for ssh, it occurred to me it would be sensible to keep all my keys together and in fact even re-use the same key to create the other formats I need.
According to Converting a Java Keystore into PEM Format I should be able to do that, or maybe I should instead use the SSH keys? They all share the same Country/State/Locality/Org/Unit/Name/Email.
The MySQL docs Creating SSL Certificates and Keys Using OpenSSL says I need to do this:
openssl req -newkey rsa:2048 -days 3600 \
-nodes -keyout client-key.pem -out client-req.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -req -in client-req.pem -days 3600 \
-CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem
openssl verify -CAfile ca.pem server-cert.pem client-cert.pem
This is problematic because I didn't generate the AWS certificates and I only got one pem file from there. Maybe the AWS ca.pem and server-cert.pem are both in the one pem file - guess I could check but I'll have to go and dig out the info about which CA signing authority they use so I could recognise the CA cert. And I guess the 'server-cert' is the public key from the actual host I've got.
But it doesn't work, I get the following error:
$ openssl.exe x509 -req -in client-req.pem -days 3600
-CA rds-combined-ca-bundle.pem -CAkey rds-combined-ca-bundle.pem
-set_serial 01 -out client-cert.pem
Signature ok
subject=/C=UK/ST=LN/L=LN/O=X/OU=XYZ/CN=xyz/emailAddress=adam#me.com
Getting CA Private Key
unable to load CA Private Key
4294956672:error:0906D06C:PEM routines:PEM_read_bio:no start
line:pem_lib.c:707:Expecting: ANY PRIVATE KEY
Turns out the SSL certificates are a red herring. You don't need them. All you need is this:
mysql -h myinstance.c9akciq32.rds-us-east-1.amazonaws.com
--ssl-ca=[full path]rds-combined-ca-bundle.pem --ssl-verify-server-cert
It's Cygwin and the standard Windows MySQL client don't play well together, hence the hanging when trying to start: connecting to mysql from cygwin

HAProxy SSL termination + client certificate validation + curl / java client

I would like to have SSL termination on HAProxy, using my own self-signed certificates, and to validate client access using client certificates I create.
I create the server (which is also the CA) certificates the following way:
openssl genrsa -out ca.key 1024
openssl req -new -key ca.key -out ca.csr
openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt
and:
cat ca.crt ca.key > haproxy.pem
at HAProxy, I configure:
bind *:443 ssl crt /path/server.pem ca-file /path/ca.crt verify required crt-ignore-err all
I create the client certificates in a similar way:
openssl req -new -key client.key -out client.csr
openssl x509 -req -days 365 -in client.csr -signkey ca.key -out client.crt
cat client.crt client.key > client.pem
My logic is: I'm creating a client key, a certificate signing request for it, and then I sign it using the CA (which is also the server certificate, so there's a simple chain that the server would recognize).
To test, I first try with the server certificate as the client cert:
curl https://my.service:443/ping -E ./haproxy.pem -k
pong
ok, it works. Now I try with the client certificate as the client certificate:
curl https://my.service:443/ping -E ./client.pem -k
curl: (58) unable to set private key file: './client.pem' type PEM
My question:
1) I would like to create a client certificate that this server will accpet, and test it using curl.
2) I would like to import this certificate and the CA into a new java keystore / truststore using keytool, so that Java (Jersey client) code could access the same content.
I have spent 2 days on 1/2.
I'm pretty sure someone that's done this before could answer this in 5m. Or so I hope. :)
Thanks!
1. create client cert
wrong: openssl x509 -req -signkey creates a self-signed cert, which by definition means the key in the cert (the subject key) is the public half of the same key whose private half signs the cert. The documentation for the cert (not req) case is clear that it replaces the key previously in the cert with the signing key. The -req doc is less clear, but it does the same thing; it puts in the cert the subject name from the CSR, also as the issuer, and the key from -signkey. You have used a CSR containing the client name, but a -signkey containing the CA key, producing an unusable chimera.
right: to sign a "child" (not self-signed) cert with x509, use -CA and possibly -CAkey as described in the documentation https://www.openssl.org/docs/apps/x509.html#SIGNING-OPTIONS (or man [where] x509 on any Unix with openssl doc installed). If there is or ever will be more than one child cert for a given CA (defined by its DN), either use the serial-number file scheme to automatically and conveniently assign sequential serial numbers, or use -set_serial to manually assign unique serial numbers (sequential is the easiest way to do unique, but if you a prefer another way that's okay).
aside: for the self-signed CA (and server?!) cert, you don't need separate req -new and x509 -req -signkey steps, you can do it in one req -new -x509. See the doc/manpage for req. In fact you don't need a separate genrsa step, req -newkey [-nodes] -x509 can do that as well. One note: in OpenSSL 1.0.0+ this generates the generic PKCS#8 format keyfile instead of the "legacy" PKCS#1 format used by genrsa (and rsa); all OpenSSL functions can accept either, but some other things might not. In particular last I checked (a while ago) the Wireshark option to decrypt SSL/TLS using server key for akRSA (there are other options too) accepted only PKCS#1 not PKCS#8.
2. use in Java (Jersey). Note that any SSL/TLS client doing client authentication, including Java, needs both the certificate and the privatekey, and in most cases the certificate uses "chain" or "intermediate" certs which you need also. Some people (cough) Microsoft (cough) encourage you to misunderstand and ignore this important distinction, but if you try to use only a certificate it won't work at all. On the other hand a truststore entry needs only the certificate, almost always only the root (CA) certificate, and usually must have only the certificate. Your situation where the same person operates the CA and server and client(s) is somewhat unusual for PKC.
2a. maybe just convert to pkcs12. Java does not directly support the openssl format(s) for keys, but both Java and openssl support PKCS#12 (and so do Microsoft, Mozilla, Apple, and probably others). Since you combined client key and (leaf) cert in client.pem do
openssl pkcs12 -export <client.pem -CA ca.crt [-name whatever] >client.p12
# if you use separate key,cert files see the doc about -in and -inkey
Java crypto (JCE and JSSE) can use this PKCS#12 as a keystore, if you can configure the keystore "type" (as pkcs12). The default SSLSocketFactory supports this, and so do other apps I've used, but I don't use Jersey and don't know what it does here. PKCS#12 isn't generally supported to carry "separate" certs (without privatekey), but in your case the CA cert for the client is also the cert for the server, so it will happen to work as your truststore as well; otherwise you would need to import the server CA or server selfsigned cert (only cert not privatekey) into a JKS truststore (which might be the default truststore in JRE/lib/security/[jsse]cacerts).
2b. maybe further convert to JKS. If Jersey cannot use PKCS#12 directly, Java can convert it to JKS which any sane Java code can use, like:
keytool -importkeystore -srckeystore client.p12 -srcstoretype pkcs12 -destkeystore client.jks
UPDATE 2018: after this answer was written Java support of PKCS12 increased, making it less often necessary to convert to JKS. 8u60 released fall 2017 and up still defaults to keystore type JKS, but as a special feature(?) type JKS can actually read (though not write) PKCS12; see the release notes and item keystore.type.compat in file JRE/lib/security/java.security. Java9 released 2017 makes the default keystore type PKCS12 which (as expected) reads and writes PKCS12, although explicit JKS no longer reads PKCS12. But if you do need to convert with Java9 for some reason, you now need to specify -deststoretype jks but no longer need to specify -srcstoretype pkcs12.

Installation of WildCard SSL certificate (By Comodo) on Tomcat Apache Web Server

I am installing a wild Card SSL certificate to my keystore which will be used for Apache Tomcat web server.
Description :
My Tomcat Server is installed on windows 2012 server.
And I have certificates provided from COMODO.
The wildcard cert I'm using has already been used previously on a few servers. so I am directly installing same on my apache tomcat server .
so what I've generated a public keystore using keytool providing the same information used while purchasing the certificate using following tool command.
keytool -keysize 2048 -genkey -alias tomcat -keyalg RSA -keystore tomcat.keystore
Then I have attached my certificates to the generated keystore using following commond
For "Comodo" certificates
i.keytool -import -trustcacerts -alias root -file AddTrustExternalCARoot.crt -keystoreselfservice.keystore
And I have used correct chain of installation of certificate like root , all intermediate, primary from above command.
And while installing each certificate i received the following message
"Certificate added to keystore"
Though I have not got any error .
And when i have opened my keystore there were no certificate chain , means there is individual entry of each certificate . but there is no chain hierarchy of certificates like Root then intermediate then primary.
And in my final PI or certifcate, i am getting provider as local first name instead of Comodo .
EXAMPLE :
CN=nims.ABC.com,OU=abcCommunications,O=abc Group LLC, L=Roseville,ST=Minnesota,C=US
Provider must be
CN=COMODO RSA Organization Validation Secure Server CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
So I would like to know which steps I have missed or used any extra steps .
Please provide a solution to install a wild card certificate .
Thanks in advance
You did everything correctly. The trust chain is important for another aspect. If you trust one 'certificate' of the chain, you trust the following 'certificates' of the chain too. So to trust all certs of a CA you just have to trust the root CA's cert.
What you realy need to make the wild card certificate work on you server is to import the private key part of it.
I assume you mean Tomcat using Java SSL (JSSE) not APR/Native (OpenSSL). If you want Tomcat-APR, change your question.
If the cert you want to use is already in use on other servers, and you "generated a public keystore using" the keytool command you showed on the NEW server, you generated a NEW KEY which is different from the key the other servers used and different from the key included in the certificate, thus the certificate DOES NOT MATCH that new key and cannot be used with that new key. You also implicitly generated (and have not replaced) a self-signed cert, with both subject and issuer (what you call provider) identifying you rather than a CA like Comodo. This certificate is not good for general use but can be useful for some testing, which is why keytool does it implicitly.
You need to get the certificate, the ALREADY EXISTING private key that MATCHES the certficate, and the needed chain cert(s) into your JKS as a privateKey entry. If an existing SSL server is Java (using JSSE), just copy its JKS. If you want or need to change the password(s) on the copy for your new server, see keytool -storepassword and keytool -keypasswd.
If an existing server is OpenSSL (including Apache httpd and nginx), convert the OpenSSL PEM format to PKCS#12 (preferably on the old server); depending on that server's file layout this is something like
openssl pkcs12 -export -in certfile -inkey keyfile -certfile chaincert -out xxx
and then use keytool to convert PKCS#12 to JKS (preferably on the new server)
keytool -importkeystore -srckeystore xxx -srcstoretype pkcs12 -destkeystore yyy
Note you must use a password on the PKCS#12. This does not need to be the same as the old server keyfile (if any) or the new server JKS, but it's usually more convenient if it is.
If an existing server is IIS, you should be able to export the cert WITH private key AS PFX/PKCS#12 from the Certificate snapin of mmc, and then convert the PKCS12 to JKS as just above.
If an existing server is something else, add it to the question.

java.net.SocketException: Connection reset

I am coding an application where I control the code of both the client and the server.
I am using SSLSockets to implement it.
I have the protocol already running with normal unsecured sockets, but when I try to switch to SSLSockets (using exactly the same protocol), I keep getting the following stack trace:
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293)
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:331)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:782)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:739)
For some reason, the exact same code works perfectly with unsecured sockets. Why could this be?
Any feedback would be appreciated. Thank you.
Pablo
From your post it is not possile to detect the problem.
When you switch to secure sockets the most secure ciphers are used by default.
If you have not configured your truststore/keystore correctly (or have not enabled the non-authenticated suites) then the SSL handshake will fail.
The exception seems to indicate that.
What you can do is run your program using javax.net.debug=ssl,handshake to enable SSL debugging info and post the debugging info and your code if you expect someone to help you.
Depending on what OS you are using, it may require admin/root priveledges to bind to or listen to the SSL port. Trying running your application with admin rights (in Windows) or sudo'd (on Linux).
Reasons can vary, -Djavax.net.debug=ssl is your friend, as suggested by Vladimir Dyuzhev.
Anyway, it may be a certificate problem -- make sure you have correct keystore and trustore. You will require one entry in keystore with:
private key
certificate
complete chain of issuer of the certificate
And a truststore:
complete chain of certificates for server certificate
I have problems generating proper keystore (trustore is easy -- just use keytool). For keystore you need st like this (Linux with openssl + java):
# convert all to PEM
openssl x509 -in ${ca}.der -inform DER -outform PEM -out ${ca}.pem
openssl x509 -in ${subca}.der -inform DER -outform PEM -out ${subca}.pem
# create one large PEM file containing certificate chain
cat ${ca}.pem ${subca}.pem > tmp_cert_chain.pem
# generate PKCS#12 BUNDLE
openssl pkcs12 -export -in ${cert}.pem -inkey ${key}.pem -certfile tmp_cert_chain.pem -out tmp_pkcs12.pfx
# convert PKCS#12 bundle to JKS
keytool -importkeystore -srckeystore tmp_pkcs12.pfx -srcstoretype pkcs12 -srcstorepass ${storepass} -destkeystore $keystore -deststoretype jks -deststorepass ${storepass}
# print out JKS keystore
keytool -list -keystore $keystore -storepass $storepass

Categories

Resources