JAVA SAML JKSKeyManager - java

I hope someone can help me.
I am trying to create a sample application to test connection to ADFS
I was able to run the sample SAML code using SSOCircle.
Not i am trying to use it with the other ADFS server
I have been given a cert file ADFS.cer and a metadata.xml
I used the following command
keytool -import -alias myalias -file ADFS.cer -keystore myfile.jks -storepass mypass -noprompt
#Bean
public KeyManager keyManager() {
DefaultResourceLoader loader = new DefaultResourceLoader();
Resource storeFile = loader
.getResource("classpath:/saml/myfile.jks);
String storePass = "mypass";
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("apollo", "mypass");
String defaultKey = "apollo";
return new JKSKeyManager(storeFile, storePass, passwords, defaultKey);
}
The file builds and when i run the file and hit the url http://localhost:8080/
java.lang.RuntimeException: Key for alias apollo not found
I have been reading few forums and read somewhere the Authenticated certs don't need password
I am not sure what i should be putting in place of defaultKey ("apollo")
Thanks
Regards

While working on this further , this is what i have found. Following the following steps, i was able to resolve the keystore related exceptions
generates a key pair
keytool -genkeypair -alias mykey -keypass mypass -keystore myJKSFile.jks
You can use the following command to list
keytool -v -list -keystore myJKSFile.jks
Add/import cert to the keystore file
keytool -importcert -alias differentAlias -file ADFS-CertFile.cer -keystore myJKSFile.jks
In the code (Spring configuration), use the following
#Bean
public KeyManager keyManager() {
DefaultResourceLoader loader = new DefaultResourceLoader();
Resource storeFile = loader
.getResource("classpath:/saml/myJKSFile.jks");
String storePass = " mypass";
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("mykey", " mypass");
String defaultKey = "mykey";
return new JKSKeyManager(storeFile, storePass, passwords, defaultKey);
}

Related

Java doesn't read DSA keys from Windows-MY

I have created two different DSA keys using java keytool (defaults to 2048 and SHA256, so the 2nd one is explicitly created with length 1024):
keytool -genkey -keystore c:\test\dsa2048.p12 -storetype pkcs12 -storepass password -keypass password -alias dsa2048
keytool -genkey -keystore c:\test\dsa1024.p12 -storetype pkcs12 -storepass password -keypass password -alias dsa1024 -keysize 1024
I then imported these keys into the windows keystore.
When I read the windows keystore, Keystore.aliases() does not return these ids. It works fine when I use RSA as the keyalg, but DSA doesn't work. I am also able to load these ids if I create the keystore from the file system, but I need to load them from the windows cert store.
Is this expected or is there something else I need to do to see them? Is it possible that keytool is creating invalid ids? When I try to sign with these ids in Acrobat I'm getting an error there as well...
import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.Enumeration;
public class WindowsKeyStoreTest
{
public static void main(String [] args) throws Exception
{
windowsKeystore();
}
public static void windowsKeystore() throws Exception
{
KeyStore keyStore = KeyStore.getInstance("Windows-MY");
keyStore.load(null, null);
Enumeration<String> aliases = keyStore.aliases();
while(aliases.hasMoreElements())
{
String alias = aliases.nextElement();
if(keyStore.isKeyEntry(alias))
{
System.out.println(alias);
}
}
}
}

Where to install Redis certificate

I have a certificate for Redis. Where do I install this certificate to connect to my Redis server?
I've tried to throw it into my java cacerts, but it doesn't work.
What is the proper way to do this?
I've also been trying to connect a Java app with Jedis 3.5.0 to a Redis cluster (6.10.0).
Build Redis with SSL
First of all, the redis binary must be built with the BUILD_TLS=yes flag as per https://redis.io/topics/encryption (if you are hosting yourself)
creating the redis_key_store
Will have to generate a redis.crt file to connect to redis and a redis-ca.crt file to verify the identity of your node/cluster.
Or you can use the files generate by "./runtest --tls" in ./tests/tls.
Create a p12 key store :
openssl pkcs12 -export -in redis.crt -inkey redis.key -out redis_key_store.p12 -passout pass:keystore_pwd
and save the resulting redis_key_store.p12 somewhere safe.
add the Redis instance to your trusted sources
find your trustStore and copy the redis-ca.crt and redis-ca.key files next to it.
Add the redis-ca to the trustStore :
keytool -import -file redis-ca.crt -alias redis-ca -keystore truststore.jks -storepass truststore_pwd
start your redis node/cluster
you must change/add to the configuration of the redis nodes the location of the certificates as per
https://redis.io/topics/encryption#certificate-configuration
Create a simple class to test the connection
Then I created a class like in step 3 from this page
public class SSLTest
{
private static final String HOSTNAME = "localhost";
private static final int PORT = 6379;
public static void main (String[] args) {
try {
System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
System.setProperty("javax.net.ssl.keyStore", "path/to/cert/redis_key_store.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "keystore_pwd");
System.setProperty("javax.net.ssl.trustStoreType", "JKS");
System.setProperty("javax.net.ssl.trustStore", "path/to/cert/truststore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "truststore_pwd");
Jedis jedis = new Jedis(HOSTNAME, PORT, true);
jedis.connect();
jedis.auth("redacted");
System.out.println(jedis.ping());
} catch (Exception e) {
e.printStackTrace();
}
}
}
==> The code should print out "PONG"

IBM Httpd server - Exporting p12 from kdb gives a corrupt p12 file

I am currently installing an SSL certificate on an IBM Httpd server's port using a code written by me. The code installs the certificate as follows:
Creates a password protected .p12 file containing the private key object and an end entity certificate (passed as an X509Certificate array of 1 element).
public static KeyStore createKeyStoreFromKeyAndCertChain(String encoding,
String friendlyName, X509Certificate[] certChain,
PrivateKey key, String password)
throws KeyStoreException, CertificateException,
NoSuchAlgorithmException, IOException {
KeyStore store = KeyStore.getInstance(encoding);
store.load(null, null);
store.setKeyEntry(friendlyName, key, password.toCharArray(), certChain);
return store;
This correctly generates a .p12 file which is parsable using openssl and keytool.
Uses the following commands to create a .kdb file, add issuer certs to the .kdb file and then add the .p12 file (containing the private key and end entity cert) created in Step 1.
"C:\Program Files (x86)\IBM\HTTPServer2\java\jre\bin\ikeycmd.exe" -keydb -create -db "C:\Work\Certs\IBM certs\test.kdb" -pw password -type cms -expire 60 -stash
"C:\Program Files (x86)\IBM\HTTPServer2\java\jre\bin\ikeycmd.exe" -cert -add -db "C:\Work\Certs\IBM certs\key1.kdb" -pw password -label icacert -file "C:\renewcert\ica.cer" -trust enable
"C:\Program Files (x86)\IBM\HTTPServer2\java\jre\bin\ikeycmd.exe" -cert -add -db "C:\Work\Certs\IBM certs\key1.kdb" -pw password -label rootcert -file "C:\renewcert\rootCert.cer" -trust enable
"C:\Program Files (x86)\IBM\HTTPServer2\java\jre\bin\ikeycmd.exe" -cert -import -db "C:\renewcert\certWithPvtKey.p12" -pw password -target "C:\Work\Certs\IBM certs\httpdkey.kdb" -target_pw password -target_type cms
This creates a .kdb file.
Updates the virtual host directive inside httpd.conf file to store information corresponding to the newly created .kdb file:
Listen 10.212.143.105:6042
<VirtualHost 10.212.143.105:6042>
SSLEnable
SSLProtocolDisable SSLv2
SSLServerCert ibmhttpdsslcert
KeyFile "C:\Work\Certs\IBM certs\key1.kdb"
SSLStashFile "C:\Work\Certs\IBM certs\key1.sth"
</VirtualHost>
The label used for tag SSLServerCert is same as the friendly name used to create .p12 in step 1.
The certificate is discoverable through our application (which uses Java based SSL certificate discovery) and through openssl also.
Problem
We need to now export the original .p12 out of the .kdb file. For the same, following command is used:
"C:\Program Files (x86)\IBM\HTTPServer2\java\jre\bin\ikeycmd.exe" -cert -export -db "C:\Work\Certs\IBM certs\key1.kdb" -pw password -label ibmhttpdsslcert -type cms -target "C:\Work\Certs\IBM certs\certChain.p12" -target_pw password -target_type pkcs12
What essentially happens is that the .p12 file that gets generated appears to be corrupted and is not parsable using the following code:
public static void main(String[] args) throws Exception {
String password = "password";
// Read the .p12 and convert it to Java objects
FileInputStream fm = new FileInputStream(new File("C:\\Work\\Certs\\IBM certs\\certChain.p12"));
KeyStore ks = KeyStore.getInstance("PKCS12");
try {
ks.load(fm, password.toCharArray());
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Size- " +ks.size());
Enumeration aliases = ks.aliases();
while(aliases.hasMoreElements()){
String param = (String) aliases.nextElement();
System.out.println("Param- " +param);
}
KeyStore.ProtectionParameter protParam =
new KeyStore.PasswordProtection(password.toCharArray());
// Retrieve the key using the alias "IBMHttpdSSLCert"
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
ks.getEntry("IBMHttpdSSLcert", protParam);
PrivateKey myPrivateKey = pkEntry.getPrivateKey();
Object pemObject = myPrivateKey;
// Write the key to file
JcaPEMWriter pemWriter = new JcaPEMWriter(new FileWriter(new File("C:\\Work\\pvtKey.pem")));
pemWriter.writeObject(pemObject);
pemWriter.close();
System.out.println("Pvt key- " +myPrivateKey);
fm.close();
}
What happens is that the size of the keystore is reported as zero (0) and the keystore file is not parsable using keytool also.
The same is however parsable using openssl but we cannot bundle openssl in out code binary.
Any idea if it is a known bug with IBM's implementation for keystore export ?

keytool - see the public and private keys

I created Java keystore programmatically of type jks (i.e. default type).
It is initially empty so I created a DSA certificate.
keytool -genkey -alias myCert -v -keystore trivial.keystore
How can I see the public and private keys?
I.e. is there a command that prints the private key of my certificate?
I could only find keytool -certreq which in my understanding prints the certificate as a whole:
-----BEGIN NEW CERTIFICATE REQUEST-----
MIICaTCCAicCAQAwZTELMAkGA1UEBhMCR1IxDzANBgNVBAgTBkdyZWVjZTEPMA0GA1UEBxMGQXRo
BQADLwAwLAIUQZbY/3Qq0G26fsBbWiHMbuVd3VICFE+gwtUauYiRbHh0caAtRj3qRTwl
-----END NEW CERTIFICATE REQUEST-----
I assume this is the whole certificate. How can I see private (or public key) via keytool?
You created a private (and associated public) key in your keystore. For it to be really usable, you can get it signed by a certification agency (CA) - for this is the -certreq command (you send the output to this certification agency, along with some other information and a bit of money, and they send back a certificate, which you can then import in your keystore.)
Viewing the private key is not intended ... you usually don't need this, since you use the keystore in your Java program, and this knows how to use it.
Edit: Since you want to look at your keystore, here a quick Java program which does this:
import java.io.*;
import java.security.*;
import java.security.cert.Certificate;
public class KeyPrinter {
/**
* to be invoked with these parameters:
*
* [0]: keystore-password
* [1]: filename
* [2]: alias
* [3]: entry-Password (if necessary)
*/
public static void main(String[] params)
throws IOException, GeneralSecurityException
{
char[] storePass = params[0].toCharArray();
String fileName = params[1];
String alias = params[2];
KeyStore.ProtectionParameter entryPass;
if(params.length > 3) {
entryPass=new KeyStore.PasswordProtection(params[3].toCharArray());
} else {
entryPass = null;
}
KeyStore store = KeyStore.getInstance("JKS");
InputStream input = new FileInputStream(fileName);
store.load(input, storePass);
KeyStore.Entry entry = store.getEntry(alias, entryPass);
System.out.println(entry);
}
}
First call keytool -list -keystore myStore to know which alias to look for, then call this program with the passwords and parameters. In case of a private key entry, it shows the key itself and additionally a self-signed certificate which contains the public key, in a readable form. In case of a "trusted certificate", it shows only the public key.
No, you cannot.
You can access the private key from code, but you cannot export it using the keytool.
Use OpenSSL if you need to export private key.
Another option: you can generate keystore in PKCS12 format. Then you can import it to a browser and then to export the private key.
(Portecle) is a very convenient GUI tool for managing keystores. And among other things it have an option to export private key and its associated certificate.
The common way to share your public key is to share a certificate for your keypair (it contains your public key inside)
keytool -list -v -alias myCert -storepass 123456 -keystore file.jks
or
keytool -list -rfc -alias myCert -storepass 123456 -keystore file.jks
as noted in
keytool -help
You can use keystore-explorer.

Can't sign a dig sig utilizing java / keytool

I have created a certificate basically straight from the keytool example page:
keytool -genkey -dname "cn=Anything, ou=Anything, o=Anything, c=US" -alias business -keypass kpi135 -keystore C:\mykeystore -storepass ab987c -validity 1095
I am trying to access this certificate and use the private key portion to digitally sign a portion of text to authenticate with a third party. Below is the code I'm attempting:
//Add bouncyCastle as a provider
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream("C:\\mykeystore"), "ab987c".toCharArray());
Signature sig = Signature.getInstance("MD5withRSA", "BC");
PrivateKey privateKey = (PrivateKey)keystore.getKey("business", "kpi135".toCharArray()); //Exception here
sig.initSign(privateKey);
sig.update("myUID__myNonce".getBytes());
byte[] digitalSignature = sig.sign();
System.out.println("Signature Formulated: " + digitalSignature);
I get the following exception:
java.security.InvalidKeyException: Supplied key (sun.security.provider.DSAPrivat
eKey) is not a RSAPrivateKey instance
at org.bouncycastle.jce.provider.JDKDigestSignature.engineInitSign(Unkno
wn Source)
at java.security.Signature$Delegate.engineInitSign(Signature.java:1095)
at java.security.Signature.initSign(Signature.java:480)
at MainClass.<init>(MainClass.java:15)
at MainClass.main(MainClass.java:28)
I assume it's because I've somehow created the certificate with the wrong type of key, but I'm not sure I'm finding what I need by digging through the keytool page. It does mention that you can apparently generate a key using -keysig RSA and -sigalg RSA however when I try those flags when creating a certificate I get:
keytool error: java.security.NoSuchAlgorithmException: RSA Signature not availab
le
enter code here
Actually it seems you can add "-keyalg RSA" to the keygen command which alleviates the mismatch issue. I was incorrectly trying both -keyalg and -sigalg in the same keygen command. The code above now executes without exceptions.

Categories