keytool: import certificate chain from several .cer files - java

Our IT dept gave me 4 .cer files, that constitute certificate chain: thawte_root.cer->intermediate1_pem.cer->intermediate2_pem.cer->our_company.cer.
I need to sign some code (via jarsigner) using our_company.cer.
Therefore, I have to create a keystore, containing our_company.cer and the chain-to-the-root.
I've tried to simply concatenate these 4 files into one using notepad and then import the resulting file, but keystore imports only the first one and when I try to launch jarsigner, I get
"jarsigner: Certificate chain not found for: our_company. our_company must reference a valid KeyStore key entry containing a private key and corresponding public key certificate chain."
I get the same message when I import only our_company.cer or when I import each certificate one-by-one.
So the question is: how can I import 4 certificates as one chain?
Thanks in advance. Vitaly.

Chain all certificates into one file (order is sub to root)
cat intermediate2_pem.cer intermediate1_pem.cer thawte_root.cer > chain.cer
Run this openssl command
openssl pkcs12 -export -in our_company.cer -inkey private.key -out company.p12 -name company -CAfile chain.pem -caname sub2 -caname sub1 -caname root -chain
Create keystore
keytool -importkeystore -destkeystore company.keystore -srckeystore company.p12 -srcstoretype PKCS12 -alias company
Your keystore will be ready (pick a password and type it in for all circumstances). You will also need to have your private.key ready.
See this link for more detailed information.

As you probably know, code signing works using public-key encryption. To sign code you need to have a private key, and clients wanting to use your code must trust the corresponding public key.
The CER files that you have are certificate files corresponding to the public keys. When you import them with keytool -importcert without the corresponding private keys, they are imported as trusted certificates. (See the documentation for more details. Depending on your system setup, you probably don't need to import them all - you probably already trust the Thawte certificate, for example.)
Since you want to sign code as YourCompany, you will need the private key corresponding to our_company.cer - I suppose your IT department can provide this, since it will have been used to generate the Certificate Signing Request sent to Thawte. If they are not willing to pass this on to you you will need to generate your own private/public key pair using keytool -genkeypair, generate a CSR with keytool -certreq and send it to your IT department who can then issue you a certificate. The final chain of trust in this case would be thawte_root.cer->intermediate1_pem.cer->intermediate2_pem.cer->our_company.cer->your_department.cer

Related

java ssl certificate & CA

How does my java application get a public key, for example the google or facebook domains WITHOUT THE NEED to add their .cer files in cacerts keystore?
I suspect that the reason is that such domains use well-known Certification authority, CA, that may already be in java cacerts keystore file (depending on version java? I tried to see if there are certificates up to 2030-2040 validity, or I'm wrong in my theory). But if I guess correctly, then where are the public keys from these domains stored? I would like an expert opinion on this matter.
You are correct - if a cert provided by a server is not signed by recognised CA then the cert that signed the provided cert needs to be added to CACERTS. By recognised CA I mean one that is the CACERTS of the default Java install.
Strictly speaking it's a bit more complicated. A cert will be trusted if it's signing path (signed-by, signed-by...) can be traced back in the cert chain provided by the server to one in CACERTS.
The public keys are part of the certs. If you want to see all the public keys in CACERTS run the following from your JAVA_HOME with bin on the path:
keytool -list -rfc -keystore jre/lib/security/cacerts
password is changeit
This will give you lots of output that will include the actual certs, eg:
-----BEGIN CERTIFICATE-----
MIICsDCCAhmgAwIBAgIQZ8jh6OO+HL38kTuOpiOHSTANBgkqhkiG9w0BAQUFADCB
izELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxML
RHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENl
cnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcN
OTcwMTAxMDAwMDAwWhcNMjEwMTAxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTAT
BgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzANBgNV
BAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAdBgNV
BAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
MIGJAoGBANYrWHhhRYZT6jR7UZztsOYuGA7+4F+oJ9O0yeB8WU4WDnNUYMF/9p8u
6TqFJBU820cEY8OexJQaWt9MevPZQx08EHp5JduQ/vBR5zDWQQD9nyjfeb6Uu522
FOMjhdepQeBMpHmwKxqL8vg7ij5FrHGSALSQQZj7X+36ty6K+Ig3AgMBAAGjEzAR
MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAS+mqF4EF+3kKMZ/F
QfRWVKvpwuWXjhj+kckMPiZkyaFMJ2SnvQGTVXFuF0853BvcSTUQOSP/ypvIz2Y/
3Ewa1IEGQlIf4SaxFhe65nByMUToTo1b5NP50OOPJWQx5yr4GIg2GlLFDUE1G2m3
JvUXzMEZXkt8XOKDgJH6L/uatxY=
-----END CERTIFICATE-----
Then use a site like this to inspect the public key - it is under 'RAW OUTPUT"
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:d6:2b:58:78:61:45:86:53:ea:34:7b:51:9c:ed:
b0:e6:2e:18:0e:fe:e0:5f:a8:27:d3:b4:c9:e0:7c:
59:4e:16:0e:73:54:60:c1:7f:f6:9f:2e:e9:3a:85:
24:15:3c:db:47:04:63:c3:9e:c4:94:1a:5a:df:4c:
7a:f3:d9:43:1d:3c:10:7a:79:25:db:90:fe:f0:51:
e7:30:d6:41:00:fd:9f:28:df:79:be:94:bb:9d:b6:
14:e3:23:85:d7:a9:41:e0:4c:a4:79:b0:2b:1a:8b:
f2:f8:3b:8a:3e:45:ac:71:92:00:b4:90:41:98:fb:
5f:ed:fa:b7:2e:8a:f8:88:37
Exponent: 65537 (0x10001)

Spring Boot - Enable SSL (HTTPS) with CA certificate

Maybe I will find help here. I want to enable SSL on Spring Boot application. I have a configuration like:
server: port: 8999 ssl:
enabled: true
key-store: classpath:keystore.jks
key-store-password: mypass
key-password: mypass
The problem is my keystore. I've imported *crt file into keystore with alias 'tomcat':
keytool -importcert -file certificate.crt -keystore native.jks -alias tomcat
However, I still can't properly access my rest api. It vomits with error in firefox:
SSL_ERROR_RX_RECORD_TOO_LONG
it doesn't work. How can I make proper keystore to make it work? I'm issuing with CA certificate, NOT self-signed. I have files like:
certificate.crt, certificate.p12, certificate.pk, privkey.pem and
three files root_ca_1.ca-bundle, root_ca_2.ca-bundle,
root_ca_3.ca-bundle
. That's all I have. I'm very fresh with ssl topic, just read some tutorials and tried few keytool commands to make it work. I'd be grateful for help. Thank You in advance.
I just spent the afternoon figuring out this exact problem, so I'll share my process here.
Each of the references below provides instructions on how to generate and use a self-signed certificate. That's not exactly what I'm trying to do, but these each contain some useful background information.
REFERENCES:
https://www.baeldung.com/spring-boot-https-self-signed-certificate
https://mkyong.com/spring-boot/spring-boot-ssl-https-examples/
https://dzone.com/articles/how-to-enable-the-https-into-spring-boot-applicati
I have already purchased a real CA-issued SSL certificate for the *.jimtough.org 'wildcard' domain. I purchased the certificate from http://www.namecheap.com/, but the actual Certificate Authority (CA) is Comodo.
As part of the purchase/activation procedure with the CA, I needed to follow these instructions:
https://www.namecheap.com/support/knowledgebase/article.aspx/9592/14/generating-a-csr-on-amazon-web-services-aws/
Note that I opted to follow their AWS instructions because I am an AWS user and have an EC2 server readily available with OpenSSL and Java already installed on the server. There are lots of other alternatives to do the same procedure, so search further to find the 'generating a CSR' instructions that are right for you.
At the end of this step, I have the following two files:
csr.pem - This is used as part of the SSL cert request/activation process
private.key - This is the private key part of my SSL cert, which I will need later to install the cert on my servers. Keep it secret. Keep it safe.
After I completed the purchase and verification procedure for my SSL cert, the CA sent me back a .zip file that contained a .p7b, .crt, and .ca-bundle file.
One of the reference links below explains the difference between these certificate file types:
.p7b - This type should be compatible with Java-based applications (PKCS#7 format)
.crt - This type should be compatible with most everything else - the link above suggests this is PEM format
.ca-bundle - Not sure when to use this - the link above suggests this is PEM format
REFERENCES:
https://www.ssls.com/knowledgebase/what-are-certificate-formats-and-what-is-the-difference-between-them/
Next I need to figure out how to use the files that I listed above to configure my Spring Boot application for HTTPS.
I will follow the relevant parts of the below tutorials to get what I need:
https://www.baeldung.com/spring-boot-https-self-signed-certificate
https://www.baeldung.com/x-509-authentication-in-spring-security
NOTE: In both tutorials, I will NOT follow their sections on creating a self-signed certificates, since I already possess a real certificate that was issued by a real CA.
The first relevant step in their instructions is to create a new Java keystore. The requirements are:
Must have Java installed, so I have access to the 'keytool' utility
Must have the 'openssl' utility installed, so I can create a .p12 file using my .key and .p7b files as input
I will use my AWS EC2 Linux server to do this. My server already has the Java/keytool and OpenSSL utilities installed.
First I need to use the OpenSSL utility to create a .p12 file that (if I understand correctly) will contain both my
private key, and the CA-issue certificate. Second, I need to create a new Java keystore that will contain an imported
copy of the .p12 file.
openssl pkcs12 -export -out jimtough-dot-org.p12 -name "jimtough-dot-org" -inkey private.key -in __jimtough_org.crt
IMPORTANT: You need to provide a password at the 'export password' prompt, otherwise the keytool import in the next step will fail
keytool -importkeystore -srckeystore jimtough-dot-org.p12 -srcstoretype PKCS12 -destkeystore jimtough-dot-org-keystore.jks -deststoretype JKS
You will need to provide the password you used in the 'openssl' command
You will also need to provide a new password for the keystore that you are creating
(OPTIONAL) keytool -importkeystore -srckeystore jimtough-dot-org-keystore.jks -destkeystore jimtough-dot-org-keystore.pkcs12 -deststoretype pkcs12
I received a warning from 'keytool' about JKS being a proprietary format, and a suggestion that I convert my keystore to PKCS12 format, so I did so with this optional command
Finally, I need to package my newly created Java keystore with my Spring Boot application and configure the application to use it.
REFERENCES:
https://www.baeldung.com/spring-boot-https-self-signed-certificate
https://www.baeldung.com/x-509-authentication-in-spring-security
I referred back to the two Baeldung tutorials above, and was able to get the details I needed to make my Spring Boot (with Spring Security enabled) to work.
I created a new 'keystore' folder under the existing 'src/main/resources', and copied both of my newly created keystore files there (I kept both formats).
I added the block below to my Spring Boot application's application.properties file.
#--------------------------------------------------------------------------------------------------
# SSL CONFIGURATION
# The format used for the keystore. It could be set to JKS in case it is a JKS file
#server.ssl.key-store-type=JKS
server.ssl.key-store-type=PKCS12
# The path to the keystore containing the certificate
#server.ssl.key-store=classpath:keystore/jimtough-dot-org-keystore.jks
server.ssl.key-store=classpath:keystore/jimtough-dot-org-keystore.pkcs12
server.ssl.key-store-password=mykeystorepassword
server.ssl.key-alias=jimtough-dot-org
server.ssl.enabled=true
server.port=8443
#--------------------------------------------------------------------------------------------------
As expected, I get a bunch of warnings from my browser when I attempt to connect to a locally running instance of the Spring Boot application using https://localhost:8443/ as the URL. This happens because the browser correctly identifies the mismatch between 'localhost' and the expected 'jimtough.org' domain that my SSL certificate was created to run on. There shouldn't be any warnings when I deploy the application to a server whose hostname is 'anything.jimtough.org' (or just www.jimtough.org).
That's it! Happy HTTPS'ing!
Don't use spring-boot for SSL-connections. Let a reverse proxy handle the SSL-termination.
So it is possible, that a tool can automatic renew your certificates (like the certbot).
And you don't need to put a (sercret) private-key to your application.
It is simpler to share your application. A server-admin needs only to setup reverse proxy (or have something familar already in cloud-systems like kubernetes) and can scale up your application.
Benefits
Scalable application
Simpler spring-setup
No secrets in your application
Simpler use of application (#cloudSystems)
Most reverseProxies are compatible with certbot
Well, you require few more properties to be added in ssl configuration
server:
ssl:
key-store: classpath:config/tls/keystore.p12
key-store-password: password ##this will be your certificate password
key-store-type: PKCS12
ciphers: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
enabled-protocols: TLSv1.2
http2:
enabled: true
Make sure that the p12 keystore file is present under classpath (src/main/resources) in config/tls
But to generate keystore file use the below openssl command where you
will use .crt and .key file to generate .p12 file.
.crt and .key are present under Folder CA and file p12 file will be
generated under CA
Please note that you will asked for the certificate password after
running the below command
openssl pkcs12 -export -in CA/certificate.crt -inkey CA/certificate.key -name certificate -out CA/certificate.p12
If you want to add this certificate to your local cacert then use the
below command
under jre\lib\security
keytool -importcert -noprompt -trustcacerts -alias ca.certificate -file CA/certificate.crt -keystore cacerts -storepass changeit

Issuing PKCS11 token from PKCS12 keystore

I'm having trouble issuing certificate to a hard token, What I have is a PKCS12 keystore I have created and want to move it to a hardtoken as a PKCS11.
I can successfully generate keys and certificate and save them in a p12 keystore and can import the p12 file to hardtoken using admin console of this device.
But when I try to do the final step programatically I have different result.
Imported p12 file using admin tool what I have in device is
-Serial number
-Signature and key exchange usage
Certificate
Private Key
Public key
Imported all steps programatically
-Serial number
-Signing &encryption
Certificate
Private Key
and the final result is that end user can't use the device for signing.
I'm using SunPKCS11.
Edit: Code used for importing the key:
KeyStore.PrivateKeyEntry priEntry =
new KeyStore.PrivateKeyEntry(keys.getPrivate(), certificateArray);
KeyStore.PasswordProtection password =
new KeyStore.PasswordProtection(pass.toCharArray());
store.setEntry("Entry", priEntry, password);
EDIT 2 keytool -list
The funny thing is that when I use the following command output is the very same
keytool -keystore NONE -storetype pkcs11 -list

Lost Code Signing Certificate Alias

Our company purchased a code signing certificate from Thawte a few weeks ago. When we finally received the certificate from the purchasing team they didn't know the alias for the certificate!
I don't seem to be able to import the cert without the alias and they have no clue at all what it is. Is there a way of retrieving the alias? Has anybody else run into this problem? Is there any way of importing without the alias?
The alias is specified during the creation of the private key of the RSA certificate. It is not decided by the certificate signing authority, rather by the person creating the private and public keys.
I can't speak on whether your purchasing department ought to know this, but you'll need to check with the person/department who generated the CSR to determine the toolkit used to generate the CSR, and the key store format.
Now, assuming that the Java keytool utility was utilized to create the CSR, and that the private key is managed in a JKS keystore, you can utilize the keytool command to determine the contents (and hence the alias) of the keystore. This can be done using the keytool -list as indicated in the other answer. A sample run is demonstrated below, with the alias appearing in the output:
keytool -list -v -keystore foo.jks
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: foo
Creation date: Sep 1, 2010
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=foo, OU=foo, O=foo, L=foo, ST=foo, C=foo
Issuer: CN=foo, OU=foo, O=foo, L=foo, ST=foo, C=foo
Note that you do not need to know the keystore password to read the contents of the keystore, in which case a warning will be displayed.
In case you are using another toolkit and/or keystore format, you'll need to adopt a similar approach to determine the contents of the keystore, for the alias is not bound to appear in the CSR.
Try with:
keytool -list -keystore certificate.jks
(Note that if your keystore isn't JKS, for example, PKCS12, you can add an optional -storetype option to change the keystore type:)
keytool -list -keystore certificate.p12 -storetype PKCS12
You'll have something like:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
mykey, Feb 1, 2010, trustedCertEntry,
Certificate fingerprint (MD5): 0F:73:59:5C:35:8C:F2:F0:27:7E:F7:B7:AF:0A:95:B4
Your certificate alias is shown on the first line of the certificate description, here 'mykey'.

Can a Java key store import a key pair generated by OpenSSL?

I generate a certification key with openssl. Here is my command:
openssl genrsa -des3 -out enc_key.pem 1024
I export into cer file, then with java keytool I import into java keystore (jks).
The keystore sounds good. I can load the keystore from my java app.
The problem is when client connect to the server (In this case is FTP server, not web server, and I use apache mina), the exception occured:
javax.net.ssl.SSLHandshakeException: SSL handshake failed.
at org.apache.mina.filter.ssl.SslFilter.messageReceived(SslFilter.java:433)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:434)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$5(DefaultIoFilterChain.java:429)
...
Caused by: javax.net.ssl.SSLHandshakeException: no cipher suites in common
at com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.writeAppRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.wrap(Unknown Source)
at javax.net.ssl.SSLEngine.wrap(Unknown Source)
...
Caused by: javax.net.ssl.SSLHandshakeException: no cipher suites in common
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(Unknown Source)
There is a few things that I want to ask:
What is the cipher of certification that I generate with openssl? How can we know? maybe by command line openssl xxx?
I go to http://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#AppA. And I put SSL_RSA_xxx to enabled cipher suites, but still can't work (I put SSL_RSA because it the SSL is using ssl implisit, and genrsa, just my opinion genrsa is generate RSA). Is it correct?
Anybody knows the solution?
Or, anybody knows how to generate the standard keystore from openssl command line until can be used in java app (off course with the cipher). Because right now I can generate the certification from openssl and export keystore java, but I don't know what is the cipher that I used and how I use in the java app. Note: I can run if the keystore is generate directly FROM java. Right now the problem is if the keystore generated by java keytool from certification like openssl (and other maybe).
Any help will be appreciated! Thanks
Why are you using OpenSSL to generate the keypair? Why not just use keytool?
The genrsa tool just generates a private key. How are you creating a corresponding certificate? How are you importing the private key into your Java keystore? (I ask, because keytool can only import a private key from an existing key store, and only from Java 6 onward.)
I suspect that your problem is that your key store doesn't contain a key entry (private key and corresponding certificate). When you list the keystore contents with keytool, how many entries are there? Are they key entries or trusted entries?
The server needs access to the private key in order to authenticate itself. To import a private key, use Java 6's enhanced keytool.
After creating the key and the certificate with OpenSSL, use OpenSSL to create a PKCS #12 key store:
openssl pkcs12 -export -in cert.pem -inkey key.pem > server.p12
Then convert this store into a Java key store:
keytool -importkeystore -srckeystore server.p12 -destkeystore server.jks -srcstoretype pkcs12
Now use server.jks in your SSL-enable server, which contains the certificate and the private key.

Categories