I try to get Key from KeyStore.
I created a keystore by Keytool:
keytool -genkeypair -dname "cn=Mark Jones, ou=JavaSoft, o=Sun, c=US" -alias business2 -keypass abcdtest -keystore C:\workspace\XMLSample\keystore\mykeystore.jks -storepass 123456
And the following is GenerateXML.java
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import javax.xml.crypto.dsig.XMLSignContext;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
public class GenerateXML {
public static void main(String[] args) throws Exception {
try {
char[] passwd = "123456".toCharArray();
//Load the KeyStore and get the signing key and certificate
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("C:\\workspace\\XMLSample\\keystore\\mykeystore.jks"), passwd);
KeyStore.PrivateKeyEntry keyEnt = (KeyStore.PrivateKeyEntry)ks.getEntry("business2", new KeyStore.PasswordProtection(passwd)); // -> ERROR IN THIS ROW
X509Certificate cert = (X509Certificate)keyEnt.getCertificate();
//Create a DOMSignContext
XMLSignContext context = new DOMSignContext(keyEnt.getPrivateKey(), doc.getDocumentElement()) ;
//Create a DOM XMLSignatureFactory
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
} catch(Exception e) {
e.printStackTrace();
throw new Exception(e.toString());
}
}
}
I run on Java 1.6
But have error:
java.security.UnrecoverableKeyException: Cannot recover key
at sun.security.provider.KeyProtector.recover(KeyProtector.java:311)
at sun.security.provider.JavaKeyStore.engineGetKey(JavaKeyStore.java:121)
at sun.security.provider.JavaKeyStore$JKS.engineGetKey(JavaKeyStore.java:38)
at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:456)
at java.security.KeyStore.getEntry(KeyStore.java:1261)
at xml.generate.GenerateXML.main(GenerateXML.java:31)
I've run accross the similar issue. The root of the problem was that I used a different password for the key than for the whole keystore.
The code is similar to the one in the JSSE article. It looks like this:
serverKeyStore.load(new FileInputStream("resource/server.jks"), passphrase.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(serverKeyStore);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(serverKeyStore, keyphrase.toCharArray());
I use the keystore pass in the first line and the key pass in the last.
This basically means 2 things,
You had a bad password.
Your keystore is corrupted somehow.
I suspect it's #1. Double check your password. Try if you can list the key in keytool with the same password.
In the ks.getEntry line, you're giving it the store password. Should be the key password instead. Replace the line with this and it will work:
char[] keypwd = "abcdtest".toCharArray();
KeyStore.PrivateKeyEntry keyEnt = (KeyStore.PrivateKeyEntry) ks.getEntry("business2", new KeyStore.PasswordProtection(keypwd));
Related
I have created a keystore using the java keytool to store a passowrd using the following command
$ keytool -importpassword -alias myalias -keystore mykeystore.jceks -storetype jceks
Enter keystore password: keystore
Re-enter new password: keystore
Enter the password to be stored: testpassword
Re-enter password: testpassword
Enter key password for <myalias>
(RETURN if same as keystore password):
I want to retrieve this password in a java program. Here's what I have written so far.
InputStream is = new FileInputStream(new File("mykeystore.jceks"));
KeyStore ks = KeyStore.getInstance("jceks");
ks.load(is, "keystore".toCharArray());
PasswordProtection pp = new PasswordProtection("keystore".toCharArray());
SecretKeyEntry ske = (SecretKeyEntry) ks.getEntry("myalias", pp);
System.out.println(ske.toString()); // Outputs: "Secret key entry with algorithm PBEWithMD5AndDES"
How can I get back the password I store? Is it even possible?
Complete reference code below.
Required libraries:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStore.PasswordProtection;
import java.security.KeyStore.SecretKeyEntry;
import java.security.cert.CertificateException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.UnrecoverableEntryException;
Class:
class JCEKS
{
public static void main(String args[])
{
try{
InputStream is = new FileInputStream(new File("mykeystore.jceks"));
KeyStore ks = KeyStore.getInstance("jceks");
ks.load(is, "keystore".toCharArray());
PasswordProtection pp = new PasswordProtection("keystore".toCharArray());
SecretKeyEntry ske = (SecretKeyEntry) ks.getEntry("myalias", pp);
System.out.println(ske.toString());
}
catch(KeyStoreException e){
System.out.println("KeyStoreException:");
System.out.println(e);
}
catch(FileNotFoundException e){
System.out.println("FileNotFoundException:");
System.out.println(e.getMessage());
}
catch(IOException e){
System.out.println("IOException:");
System.out.println(e.getMessage());
}
catch(NoSuchAlgorithmException e){
System.out.println("NoSuchAlgorithmException:");
System.out.println(e.getMessage());
}
catch(CertificateException e){
System.out.println("CertificateException:");
System.out.println(e.getMessage());
}
catch(UnrecoverableKeyException e){
System.out.println("UnrecoverableKeyException:");
System.out.println(e.getMessage());
}
catch(UnrecoverableEntryException e){
System.out.println("UnrecoverableEntryException:");
System.out.println(e.getMessage());
}
}
}
The password entry you stored is stored as a SecretKeyEntry and its value can be retrieved using the getEncoded() method of the secretKey object.
System.out.println(new String(ske.getSecretKey().getEncoded()));
After some digging and some trial and error, it turns out you CAN retrieve a password that you store using keytool
For example, if you use the following command to store a password
> $ keytool -importpassword -alias my-alias -keystore my-keystore.jcek -storetype jceks
> Enter keystore password: keystorepassword
> Re-enter new password:keystorepassword
> Enter the password to be stored: thepassword
> Re-enter password: thepassword
> Enter key password for <my-alias>
(RETURN if same as keystore password): keypassword
> Re-enter new password: keypassword
To retrieve the password your stored (i.e. 'thepassword'):
InputStream is = new FileInputStream(new File("my-keystore.jceks"));
KeyStore ks = KeyStore.getInstance("JCEKS");
ks.load(is, "keystorepassword".toCharArray());
PasswordProtection pp = new PasswordProtection("keypassword".toCharArray());
SecretKeyEntry ske = (SecretKeyEntry) ks.getEntry("my-alias", pp);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHMD5ANDDES");
PBEKeySpec keySpec = (PBEKeySpec) factory.getKeySpec(ske.getSecretKey(), PBEKeySpec.class);
String password = new String(keySpec.getPassword());
System.out.println(password);
Output: thepassword
Note that when you store a string, it defaults to PBEWITHMD5ANDDES algorithm. So you will need to download the javax-crypto.jar and compile it along with your program javac -cp javax-crypto.jar your-program.java
I am trying to use keys and certificate generated using java keytool in python server and java client. I have created key & keystore, exported certificate, added certificate to truststore, converted keystore to standard pkcs format and then extracted key and certificate from pkcs to use in python server. (first three steps from here and last three steps from here) Here are the detailed steps:
Creating keystore, private key and certificate
keytool -genkey -alias ssl_key -keyalg RSA -keypass passwd123 -keystore keystore.jks -storepass passwd123
Exporting certificate out from keystore to .cer file
keytool -export -alias ssl_key -file ssl_key.cer -keystore keystore.jks -storepass passwd123
Exporting certificate from keystore to truststore
keytool -import -v -trustcacerts -alias ssl_key -keypass passwd123 -file ssl_key.cer -keystore truststore.jks -storepass passwd123
Exported keystore from keytool's proprietary format to standard format
keytool -importkeystore -srckeystore keystore.jks -destkeystore stdkeystore.p12 -deststoretype PKCS12 -srcalias ssl_key -deststorepass passwd123 -destkeypass passwd123
Exported certificate from standard format keystore using openssl
openssl pkcs12 -in stdkeystore.p12 -nokeys -out cert.pem
Exported unencrypted private key from standard format keystore using openssl as follows:
openssl pkcs12 -in stdkeystore.p12 -nodes -nocerts -out key.pem
My small python server and java client are as follows:
server.py
import socket
import ssl
def start_server_ssl():
socketObj = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('127.0.0.1', 6000)
socketObj.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
socketObj.bind(server_address)
socketObj.listen(10)
while True:
try:
print("Awaiting connection...")
data_socket, client_address = socketObj.accept()
ssl_socket = ssl.wrap_socket(socketObj,
server_side = True,
certfile="cert.pem",
keyfile="key.pem")
reading_status = True
data = bytearray()
data_decoded = ""
while(reading_status):
message_chunks = data_socket.recv(90000)
data.extend(message_chunks)
print(data)
data_decoded = str(data.decode("utf-8"))
#data_decoded = str(data.decode())
if(data_decoded.startswith("<<startMessage>>")):
if(data_decoded.endswith("<<endMessage>>")):
reading_status = False
print(data_decoded);
except socket.error as msg:
print (msg)
ssl_socket.shutdown(socket.SHUT_RDWR)
ssl_socket.close()
if __name__ == '__main__':
start_server_ssl()
Client4Py.java
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
public class Client4Py {
static KeyStore ks;
static KeyManagerFactory kmf;
static TrustManagerFactory tmf;
static SSLContext sc;
static TrustManager[] trustManagers;
static {
try {
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("D:\\javasslstores\\truststore.jks"), "passwd123".toCharArray());
kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "passwd123".toCharArray());
tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ks);
sc = SSLContext.getInstance("TLS");
sc.init(null, tmf.getTrustManagers(), null);
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.println(e.getStackTrace());
}
}
public static void main(String[] args) throws IOException {
SSLSocketFactory ssf = sc.getSocketFactory();
SSLSocket socket = (SSLSocket) ssf.createSocket("127.0.0.1", 6000);
socket.startHandshake();
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),StandardCharsets.UTF_8)));
//PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
out.println("<<startMessage>>");
out.println("Message from Client4Py");
out.println("<<endMessage>>");
out.flush();
if (out.checkError())
System.out.println(
"SSLSocketClient: java.io.PrintWriter error");
out.close();
socket.close();
}
}
The output on server's console after first running server and the client is as follows:
Awaiting connection...
bytearray(b'\x16\x03\x03\x00\xc1\x01\x00\x00\xbd\x03\x03["}o\x12\x01\xb2\xd4E\xa1\x1fy\xa8/d\x11\xd2\x00)\\t\x9a:\xb6\n\xcd\x03\x05\xbe\xe58\xd6\x00\x00:\xc0#\xc0\'\x00<\xc0%\xc0)\x00g\x00#\xc0\t\xc0\x13\x00/\xc0\x04\xc0\x0e\x003\x002\xc0+\xc0/\x00\x9c\xc0-\xc01\x00\x9e\x00\xa2\xc0\x08\xc0\x12\x00\n\xc0\x03\xc0\r\x00\x16\x00\x13\x00\xff\x01\x00\x00Z\x00\n\x004\x002\x00\x17\x00\x01\x00\x03\x00\x13\x00\x15\x00\x06\x00\x07\x00\t\x00\n\x00\x18\x00\x0b\x00\x0c\x00\x19\x00\r\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x02\x00\x12\x00\x04\x00\x05\x00\x14\x00\x08\x00\x16\x00\x0b\x00\x02\x01\x00\x00\r\x00\x18\x00\x16\x06\x03\x06\x01\x05\x03\x05\x01\x04\x03\x04\x01\x03\x03\x03\x01\x02\x03\x02\x01\x02\x02')
Traceback (most recent call last):
File "D:\Mahesh\workspaces\workspace6\PythonServer\server.py", line 44, in <module>
start_server_ssl()
File "D:\Mahesh\workspaces\workspace6\PythonServer\server.py", line 29, in start_server_ssl
data_decoded = str(data.decode("utf-8"))
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc1 in position 4: invalid start byte
I uncommented utf-8 encoding-decoding lines in client and server code and ended up getting following output on server's console:
Awaiting connection...
bytearray(b'\x16\x03\x03\x00\xc1\x01\x00\x00\xbd\x03\x03["\x7f>s\x04\x15S\x14\xb0\xa2\xa0\x7f\x90}#\xe8\xa3:\x15\x04z\xeb\x986\\b\xe9\xe0v=\x1f\x00\x00:\xc0#\xc0\'\x00<\xc0%\xc0)\x00g\x00#\xc0\t\xc0\x13\x00/\xc0\x04\xc0\x0e\x003\x002\xc0+\xc0/\x00\x9c\xc0-\xc01\x00\x9e\x00\xa2\xc0\x08\xc0\x12\x00\n\xc0\x03\xc0\r\x00\x16\x00\x13\x00\xff\x01\x00\x00Z\x00\n\x004\x002\x00\x17\x00\x01\x00\x03\x00\x13\x00\x15\x00\x06\x00\x07\x00\t\x00\n\x00\x18\x00\x0b\x00\x0c\x00\x19\x00\r\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x02\x00\x12\x00\x04\x00\x05\x00\x14\x00\x08\x00\x16\x00\x0b\x00\x02\x01\x00\x00\r\x00\x18\x00\x16\x06\x03\x06\x01\x05\x03\x05\x01\x04\x03\x04\x01\x03\x03\x03\x01\x02\x03\x02\x01\x02\x02')
Traceback (most recent call last):
File "D:\Mahesh\workspaces\workspace6\PythonServer\server.py", line 44, in <module>
start_server_ssl()
File "D:\Mahesh\workspaces\workspace6\PythonServer\server.py", line 30, in start_server_ssl
data_decoded = str(data.decode())
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc1 in position 4: invalid start byte
I feel I am missing something. Either some basics of SSL or encoding. Can I use pem file generated from java keystore as explained above directly with python SSLSocket? Or do I have to ensure something more like ciphers used to generate keys and certificate?
Any links/resources to dispel my ignorance are welcome...
I replaced your server.py with this example. There is nothing wrong with your server about keys and certificates.
server.py
import socket
from socket import AF_INET, SOCK_STREAM, SO_REUSEADDR, SOL_SOCKET, SHUT_RDWR
import ssl
KEYFILE = 'key.pem'
CERTFILE = 'cert.pem'
def print_data(s):
while True:
data = s.recv(8192)
print(data.decode("utf-8"))
if data == b'':
break
s.send(b'This is a response.')
print('Connection closed')
s.close()
def start_server_ssl(address):
s = socket.socket(AF_INET, SOCK_STREAM)
s.bind(address)
s.listen(1)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
ssl_socket = ssl.wrap_socket(s, keyfile=KEYFILE, certfile=CERTFILE, server_side=True)
print("Awaiting connection...")
while True:
try:
(c,a) = ssl_socket.accept()
print('Got connection', c, a)
print_data(c)
except socket.error as e:
print('Error: {0}'.format(e))
start_server_ssl((socket.gethostbyname('localhost'), 6000))
I have file.pfx file and also have a private key. How can I read the certificate in file.pfx in Java?
I have used this code:
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
import javax.crypto.SecretKey;
import javax.security.auth.callback.*;
//These packages I have used.
public String readFile(String fn) {
String thisLine, ret = "";
KeyStore ks = KeyStore.getInstance("pkcs12", "SunJSSE");
ks.load(new FileInputStream(fn),"password".toCharArray());
try {
Key key = ks.getKey("1", "password".toCharArray());
Certificate[] cc = ks.getCertificateChain("1");
X509Certificate certificate1 = (X509Certificate) cc[0];//Here it throws java.lang.NullPointerException
ret += certificate1.getNotAfter();
ret += certificate1.getNotBefore();
} catch(Exception e) {
ret = "Cannot load, exception!";
}
return ret;
}
Try This Code for Reading .pfx file:-
public void checkExpire() {
try {
KeyManagerFactory kmf = javax.net.ssl.KeyManagerFactory.getInstance("SunX509");
KeyStore keystore = KeyStore.getInstance("PKCS12");
char[] password= "yourfilepassword".toCharArray();
keystore.load(new FileInputStream("filepath\filename.pfx"),password);
//keystore.load(new FileInputStream(certificate), password);
kmf.init(keystore, psswd);
Enumeration<String> aliases = keystore.aliases();
while(aliases.hasMoreElements()){
String alias = aliases.nextElement();
if(keystore.getCertificate(alias).getType().equals("X.509")){
Date expDate = ((X509Certificate) keystore.getCertificate(alias)).getNotAfter();
Date fromDate= ((X509Certificate) keystore.getCertificate(alias)).getNotBefore();
System.out.println("Expiray Date:-"+expDate );
System.out.println("From Date:-"+fromDate);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
You are getting an exception because your keystore (i.e. the PKCS #12 file) does not contain a certificate chain with the alias you have provided.
Key key = ks.getKey("1", "shalimar1234".toCharArray());
Certificate[] cc = ks.getCertificateChain("1"); // this is returning null
It's quite plausible your key object is null too, but you don't appear to use the object at all.
To understand what aliases are available in your file, trying looking at the strings returned from KeyStore.aliases().
Here's a link to a forum question on the subject of opening and reading a .PFX file using Java code.
To summarize what's in the link, you should be able to open the Key-store as you would with a normal JKS, but with a slight difference, pass the Key-store type as pcks12 and the provider as SunJSSE.
try (FileInputStream stream = new FileInputStream("C:/store.pfx")) {
KeyStore store = KeyStore.getInstance("pkcs12", "SunJSSE");
store.load(stream, "password".toCharArray());
Enumeration<String> aliases = store.aliases();
while (aliases.hasMoreElements()) {
System.err.println(aliases.nextElement());
}
X509Certificate certificate = (X509Certificate)store.getCertificate("alias");
System.err.println(certificate.getNotAfter());
System.err.println(certificate.getNotBefore());
System.err.println(certificate.toString());
}
Another helpful note is that you might wanna consider using and referring to the BouncyCastle Provider, it is the most complete implementation out there in my humble opinion.
I'm trying to programmatically create a new keystore in Java. The following code:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.setCertificateEntry("alias", cert);
throws a Uninitialized KeyStore exception.
To create a new KeyStore in Java you first need to create the KeyStore file and then store it using the store(FileOutputStream, char[]) method:
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
char[] password = "some password".toCharArray();
ks.load(null, password);
// Store away the keystore.
FileOutputStream fos = new FileOutputStream("newKeyStoreFileName");
ks.store(fos, password);
fos.close();
I hope this helps, you can see more info here.
The KeyStore needs to be loaded after it has been created. The load method asks for a FileInputStream to read from but if you supply a null one, an empty KeyStore is loaded.
See this link
I use this code, it works, hope it can help.
public static KeyStore createKeyStore() throws Exception {
File file = new File("/Users/keyserverstore.keystore");
KeyStore keyStore = KeyStore.getInstance("JKS");
if (file.exists()) {
// if exists, load
keyStore.load(new FileInputStream(file), "123456".toCharArray());
} else {
// if not exists, create
keyStore.load(null, null);
keyStore.store(new FileOutputStream(file), "123456".toCharArray());
}
return keyStore;
}
// load the keystore
KeyStore p12 = KeyStore.getInstance("pkcs12");
p12.load(new FileInputStream("KEYSTORE.p12"), "passwd".toCharArray());
// load the private key entry from the keystore
Key key = p12.getKey("mykey", "passwd".toCharArray());
PrivateKey privKey = (PrivateKey) key;
If you want to use a bean (Spring Boot 2.4.x):
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
#Configuration
public class KeyStoreConfiguration {
private static final String KEY_STORE = "keystore.p12";
private static final String KEY_STORE_TYPE = "PKCS12";
private static final String KEY_STORE_PASSWORD = "password";
#Bean
public KeyStore keyStore() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
keyStore.load(new ClassPathResource(KEY_STORE).getInputStream(), KEY_STORE_PASSWORD.toCharArray());
return keyStore;
}
}
public static void main(String[] args) {
// Load the JDK's cacerts keystore file
String filename = System.getProperty("java.home") + "/lib/security/cacerts".replace('/', File.separatorChar);
FileInputStream is = new FileInputStream(filename);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
char[] password = "changeit".toCharArray();
//keystore.load(is, password.toCharArray());
keystore.load(is, password);
// This class retrieves the most-trusted CAs from the keystore
PKIXParameters params = new PKIXParameters(keystore);
// Get the set of trust anchors, which contain the most-trusted CA certificates
java.security.cert.Certificate sapcert = keystore.getCertificate("SAPNetCA");
PublicKey sapcertKey = sapcert.getPublicKey();
System.out.println(sapcertKey);
Enumeration<String> aliases = keystore.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
//System.out.println("alias certificates :"+alias);
if (keystore.isKeyEntry(alias)) {
keystore.getKey(alias, password);
}
}
I'm trying to do something like
URL clientks = com.messaging.SubscriptionManager.class.getResource( "client.ks" );
String path = clientks.toURI().getPath();
System.setProperty( "javax.net.ssl.keyStore", path);
Where client.ks is a file stored in com/messaging in the jar file that I'm running.
The thing that reads the javax.net.ssl.keyStore is expecting a path to the client.ks file which is in the jar. I'd rather not extract the file and put in on the client's machine if possible. So is it possible to reference a file in a jar?
This doesn't work as getPath() returns null. Is there another way to do this?
Still working on implementation, but I believe it is possible to load the keystore from the jar via InputStream and explicitly set the TrustStore programatically (vs setting the System properties). See the article: Setting multiple truststore on the same JVM
Got it working!
InputStream keystoreInput = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(<path in jar>/client.ks");
InputStream truststoreInput = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(<path in jar>/client.ts");
setSSLFactories(keystoreInput, "password", truststoreInput);
keystoreInput.close();
truststoreInput.close();
private static void setSSLFactories(InputStream keyStream, String keyStorePassword,
InputStream trustStream) throws Exception
{
// Get keyStore
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
// if your store is password protected then declare it (it can be null however)
char[] keyPassword = keyStorePassword.toCharArray();
// load the stream to your store
keyStore.load(keyStream, keyPassword);
// initialize a key manager factory with the key store
KeyManagerFactory keyFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, keyPassword);
// get the key managers from the factory
KeyManager[] keyManagers = keyFactory.getKeyManagers();
// Now get trustStore
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
// if your store is password protected then declare it (it can be null however)
//char[] trustPassword = password.toCharArray();
// load the stream to your store
trustStore.load(trustStream, null);
// initialize a trust manager factory with the trusted store
TrustManagerFactory trustFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(trustStore);
// get the trust managers from the factory
TrustManager[] trustManagers = trustFactory.getTrustManagers();
// initialize an ssl context to use these managers and set as default
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(keyManagers, trustManagers, null);
SSLContext.setDefault(sslContext);
}
Here's a cleaned-up version of user2529737's answer, in case it helps. It has removed unneeded trust store setup and added required imports, parameters for keystore type and key password.
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyStore;
public class PlainJavaHTTPS2Test {
public void setUp() throws Exception {
final String KEYSTOREPATH = "clientkeystore.p12"; // or .jks
// store password can be null if there is no password
final char[] KEYSTOREPASS = "keystorepass".toCharArray();
// key password can be null if there is no password
final char[] KEYPASS = "keypass".toCharArray();
try (InputStream storeStream = this.getClass().getResourceAsStream(KEYSTOREPATH)) {
setSSLFactories(storeStream, "PKCS12", KEYSTOREPASS, KEYPASS);
}
}
private static void setSSLFactories(InputStream keyStream, String keystoreType, char[] keyStorePassword, char[] keyPassword) throws Exception
{
KeyStore keyStore = KeyStore.getInstance(keystoreType);
keyStore.load(keyStream, keyStorePassword);
KeyManagerFactory keyFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, keyPassword);
KeyManager[] keyManagers = keyFactory.getKeyManagers();
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(keyManagers, null, null);
SSLContext.setDefault(sslContext);
}
}
You can get an InputStream to a resource in a jar file, but not a File. If the "thing" that ultimately reads the keystore expects a File or a path to a file, your only option is to extract it to the filesystem.