Create PKCS12 certificate in JAVA - java

so here's what I'm trying to do:
I connect to my SSL server
It sends me two certificates, and one of them is self-signed
At this stage, there are no problems, I've:
X509Certificate[] myTwoCerts;
// with 2 certificates in there, and I'm sure it's there because, I print them in my console.
Now I want to create .p12 file with 2 certificates inside.
Until now, I've tried something like this:
KeyStore pkcs12Store = KeyStore.getInstance("PKCS12");
pkcs12Store.load(null, null);
X509Certificate cert1 = myTwoCerts[0];
X509Certificate cert2 = myTwoCerts[1]
String alias1 = "FIRST";
String alias2 = "SECOND";
pkcs12Store.setCertificateEntry(alias1, cert2);
pkcs12Store.setCertificateEntry(alias2, cert2);
But I'm getting the following Exception:
Exception in thread "main" java.security.KeyStoreException: TrustedCertEntry not supported
Can anybody help me plz??

The PKCS12 keystore in Java cannot be used to store certificates or certificate chains without their private keys.
See this note in the JCA reference guide:
"pkcs12" is another option. This is a cross platform keystore based on the RSA PKCS12 Personal Information Exchange Syntax Standard. This standard is primarily meant for storing or transporting a user's private keys, certificates, and miscellaneous secrets. As of JDK 6, standards for storing Trusted Certificates in "pkcs12" have not been established yet, and thus "jks" or "jceks" should be used for trusted certificates.
(Despite mentioning JDK 6, this still is in the JDK 7 documentation.)
If you want to store a private key + certificate (chain) in a PKCS#12 store in Java, there needs to be a private key and you need to use the setKeyEntry method.

keytool -trustcacerts -keystore keystore.p12 -storetype pkcs12 -alias root -genkeypair
KeyStore pkcs12 = KeyStore.getInstance("PKCS12");
String filename = "/tmp/keystore.p12";
keyStore.load(
new FileInputStream(/*"myKeyStore.jks"*/filename),
password);

Related

web-service client - with keystore

I need to create a web service client with a keystore. But this is the error:
sun.security.provider.certpath.SunCertPathBuilderException: unable to
find valid certification path to requested target
My code:
private SSLSocketFactory getFactory() throws Exception {
File pKeyFile = new ClassPathResource("jks/dex-client-issuer-wss.jks").getFile();
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("PKIX");
KeyStore keyStore = KeyStore.getInstance("JKS");
InputStream keyInput = new FileInputStream(pKeyFile);
keyStore.load(keyInput, pass.toCharArray());
keyInput.close();
keyManagerFactory.init(keyStore, pass.toCharArray());
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
return context.getSocketFactory();
}
this is the http conection:
URL url = new URL("https://dexxis-demo1.gemalto.com/DEX/communication/issuer-interface");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setSSLSocketFactory(getFactory());
I only have a dex-client-issuer-wss.jks file which works with soap ui, how can I create a connection with this certificate file?
'unable to find valid certification path' (during SSL/TLS handshake) has nothing to do with your keystore -- it means that the server cert does not validate against your truststore, which since you passed null as the 2nd arg to context.init is the JRE's default, which is the file specified by sysprop javax.net.ssl.trustStore if set otherwise JRE/lib/security/cacerts (or .../jssecacerts if it exists).
That server is using a cert issued under the root cert Gemalto Business Root Certificate Authority which is not included in the cacerts supplied with Oracle Java packages, or any other established truststores I know, and is not known by the public transparency logs (per https://crt.sh). SoapUI, presumably because it is designed as a development, test and debug tool, ignores invalid or suspect certs, but a browser or curl or wget on that URL should fail unless the truststore(s) on your system(s) have been modified or are otherwise unusual.
OTOH openssl s_client which is also primarily a debug tool reports an error but makes the connection anyway.
If you do want to trust that CA, or one of its (two) intermediates, or the site anyway, you need to have the appropriate cert in your truststore. The usual practice is to trust the root CA cert, but Java supports using any cert in the chain, including the EE cert, as an anchor. Since you are already creating your own context, and keymanager, you might as well create your own trustmanager rather than modifying the JRE default, which is (usually) platform/environment dependent and sometimes tricky. You could fetch the desired cert and put it in a separate keystore file (see below), load that and use it to create a trustmanager. Or since you already have a keystore file for your own key+cert(s), Java supports having both a privateKey entry or entries and a trustedCert entry or entries for other party/parties in the same file, so you could just add their cert to your existing JKS and use the same KeyStore object in a TrustManagerFactory just like you have for KeyManagerFactory to create the trustmanager array for your context.
Easy ways to get the cert are:
openssl s_client -showcerts -connect host:port </dev/null (on Windows <NUL:) -- with port 443; many servers nowadays need the Server Name Indication extension (aka SNI) and for OpenSSL below 1.1.1 you must add -servername host to provide it, but this server doesn't. This outputs a PEM block for each cert from the server, with labels before each showing s: (subjectname) and i: (issuername). Note that after the first cert, which is as required the EE cert, this server sends the CA certs in top-down order not bottom-up. This is technically in violation of RFC 5246 (or earlier 4346 or 2246); RFC 8446 for TLS1.3 allows it because it was already a common extension, and Java JSSE in particular supports it.
keytool -printcert -rfc -sslserver host -- also supports host:port but the default is 443 which is okay for you. This outputs only the PEM blocks, so if you didn't already know from my previous item about the order, you would have to decode each one to find out which is which, or just experiment until you found the correct one.
In either case take the desired PEM block and put it in a file, and do
keytool -importcert -keystore jksfile -alias somealias -file thecertfile
somealias is only required to be unique within the file (which is trivial if you put it in its own file) and case-insensitive (conventionally lowercase), but should be descriptive or mnemonic, and alphanumeric only if possible. Then use the resulting file as above.

Websphere keyset not get the latest key

I have a problem with a Websphere keyset. I create a keystore using a public key that was generated on another computer with keytool using this command:
keytool -import -noprompt -alias eeccstore -keystore eeccstore.jks -file D:\Keys\eecc_public.key -storepass password
After that, in Websphere Server I create the KeyStore as follows in the next image:
Keystore usages: Key set keystores
Create keystore in Websphere Server
I use the same password that I use to create the KeyStore with Keytool.
Then I create the keySet in WebSphere Server as follows in the next image:
Create keyset in Websphere Server
In my java code I use the keyset as follows:
KeySetHelper ksh = KeySetHelper.getInstance();
KeyPair key = (KeyPair)ksh.getLatestKeyForKeySet("eeccKeySet");
And the console shows me this:
java.lang.NullPointerException
com.ibm.ws.crypto.config.WSKeySet.getLatestKey(WSKeySet.java:257)
com.ibm.websphere.crypto.KeySetHelper.getLatestKeyForKeySet
I understand that the server can not find any key in the KeySet but I don't know what I could be doing wrong.
Thank you in advance for your support.
Reggard!
After days of searching, I found a solution. Instead to access a KeySet, I access to KeyStore directly and get not the key, but the X509 certificate with wich can create the public key and use it to encrypt any text.
char [] passch = password.toCharArray();
com.ibm.crypto.provider.JavaKeyStore keystore = new JavaKeyStore();
keystore.engineLoad(new FileInputStream(new File(pathKeyFileJKS)), null);
KeyStore.TrustedCertificateEntry privKeyEntry = (TrustedCertificateEntry)
keystore.engineGetEntry("eecc-KeyStore", new KeyStore.PasswordProtection(passch));
X509CertImpl cert = (X509CertImpl) privKeyEntry.getTrustedCertificate();
cert.checkValidity();
PublicKey publicKey = cert.getPublicKey();
Where password variable contains the password that I use to create the eecc_public.key file, pathKeyFileJKS contains the path where create the jks file and "eecc-KeyStore" is the name that I use to create my keyStore in WebSphere Server.

KeyStore and TrustStore mismatch

I have a customer who replaced the keystore and truststore of our product components. After replacement the components can't communicate with each other (2 way SSL).
On SSL logs I see:
http-nio-8100-exec-2, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain
%% Invalidated: [Session-6, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]
http-nio-8100-exec-2, SEND TLSv1.2 ALERT: fatal, description = bad_certificate
http-nio-8100-exec-2, WRITE: TLSv1.2 Alert, length = 2
http-nio-8100-exec-2, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: null cert chain
They have configured the same keystore and truststore files on both sides.
I've opened their keystore and truststore and this is how they are built:
keystore
entry1 - server
cert[1] MD5: X
cert[2] MD5: Y
cert[3] MD5: Z
truststore
entry1 - root
cert[1] MD5: Z
entry2 - intermediate
cert[1] MD5: Y
It seems to me that the fact that cert[1] in the keystore (with MD5 X) is missing from the truststore is problematic.
Am I right?
Can you see any other problem with the way their keystore and truststore was built?
It looks like your problem is related to some missing certificates either in your keystore and/or truststore.
Generally speaking, when the client sends a request to the server, the server presents its certificate chain which must include the server's certificate as the first entry followed by its issuer and other issuers. Each following certificate must directly certify the one preceding it unless it is present in the truststore on the client-side.
You need to check whether your cert[1] in keystore is a self-signed certificate. You can achieve this in the following way:
For .jks Java keystore type:
keytool -list -v -keystore [keystore-file-name].jks
-For #PKCS12 keystore type:
keytool -list -keystore [keystore-file-name].p12 -storetype PKCS12 -v
When the certificate is printed, check the 'Issuer' attribute.
If it matches the 'Owner' attribute, it means it's a self-signed certificate and you need to add the 'cert[1]' into the truststore.
If they don't match, try one of the following alternatives:
Generate a new 'cert[1]' signed by either 'Y' or
'Z' and add it into the keystore or replace the existing one. The decision whether to replace it or add depends how your code reads the certificate. A replacement might be a better option.
Add the current 'Issuer' of 'cert[1]' of the keystore into the
truststore.
If the certificate of the 'Issuer' of 'cert[1' in the keystore is already present in the truststore, I would've expected the SSL handshake to be successful.
Here is how you add an issuer to a truststore:
1) Get hold of the Public Certificate of the issuer, which is stored in .cer file. If the issuer is self-generated and you've got access to its keystore, the certificate an be exported from there using the following command:
keytool -export -keystore [issuer-keystore].jks -alias [alias]-file [output-file-name].cer
2) Import the .cer file into the truststore:
keytool -importcert -file [output-file-name].cer -keystore [truststore-file-name].jks -alias [alias]
Am I right?
No. As long as the truststore contains one of the certificates in the keystore's certificate chain, it should trust the certificate in the KeyStore.

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'.

Categories