I am using socket.io-client-java library for socket in android app but in application some error occurred which is given below
Code:-
KeyStore keyStore = KeyStore.getInstance("BKS");
InputStream is = context.getResources().openRawResource(R.raw.bks);
keyStore.load(is, "Password".toCharArray());
is.close();
//create a factory
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
//get context
SSLContext mySSLContext = SSLContext.getInstance("TLS");
//init context
mySSLContext.init(
null,
trustManagerFactory.getTrustManagers(),
new SecureRandom()
);
HostnameVerifier myHostnameVerifier = SSLSocketFactory.STRICT_HOSTNAME_VERIFIER;
// set as an option
IO.Options opts = new IO.Options();
opts.sslContext = mySSLContext;
opts.hostnameVerifier = myHostnameVerifier;
socket = IO.socket("https://demo.in:9898", opts);
socket.connect();
Here is my Error:-
java.io.IOException: KeyStore integrity check failed.
at com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi.engineLoad(BcKeyStoreSpi.java:862)
at java.security.KeyStore.load(KeyStore.java:590)
at drawgraph.hospisoft.com.bluetootheds.SocketConnetion.ConnectSocket(SocketConnetion.java:46)
at drawgraph.hospisoft.com.bluetootheds.MainActivity.initSocket(MainActivity.java:1095)
at drawgraph.hospisoft.com.bluetootheds.MainActivity.onCreate(MainActivity.java:250)
at android.app.Activity.performCreate(Activity.java:6100)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1112)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2481)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2614)
at android.app.ActivityThread.access$800(ActivityThread.java:178)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1470)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5643)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
Github Link
I think its password problem but i check BKS password many time
The password is wrong or the keystore is corrupt.
Sorry for late answer but below code working fine for me.
try {
String sslCertificateString= context.getResources().getString(R.string.certifiacte);
InputStream certFile = new ByteArrayInputStream(sslCertificateString.getBytes(StandardCharsets.UTF_8));
java.security.cert.Certificate ca = CertificateFactory.getInstance("X.509").generateCertificate(certFile);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
//create a factory
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
//get context
SSLContext mySSLContext = SSLContext.getInstance("TLS");
//init context
mySSLContext.init(
null,
trustManagerFactory.getTrustManagers(),
new SecureRandom()
);
IO.Options opts = new IO.Options();
opts.sslContext = mySSLContext;
opts.secure = true;
socket = IO.socket("https://demo.com:3000", opts);
socket.connect();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
Related
since
sslSocketFactory(javax.net.ssl.SSLSocketFactory)' is deprecated, what should I use instead? Thanks in regards... Deprecated. SSLSocketFactory does not expose its X509TrustManager, which is a field that OkHttp needs to build a clean certificate chain. This method instead must use reflection to extract the trust manager. Applications should prefer to call sslSocketFactory(SSLSocketFactory, X509TrustManager), which avoids such reflection.
Sets the socket factory used to secure HTTPS connections. If unset, the system default will be used.
try {
client = new OkHttpClient().newBuilder()
.sslSocketFactory(trustCert().getSocketFactory())
.build();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = new FormBody.Builder()
.build();
Request request = new Request.Builder()
.url("https://example.com")
.method("GET", null)
.addHeader("auth-token", token)
.addHeader("Authorization", "Bearer"+" "+token)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
odgovor = response.body().string();
System.out.println(odgovor);
} catch (IOException e) {
e.printStackTrace();
}
private SSLContext trustCert() throws CertificateException,IOException, KeyStoreException,
NoSuchAlgorithmException, KeyManagementException {
AssetManager assetManager = getAssets();
InputStream is = getApplicationContext().getResources().openRawResource(R.raw.gdig2);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate ca = cf.generateCertificate(is);
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
return context;
}
Use, #sslSocketFactory(SSLSocketFactory, X509TrustManager)
client = new okHttpClient().newBuilder().sslSocketFactory(trustCert().getSocketFactory(), (X509TrustManager) tmf.trustManagers.get(0));
I have a microservice deploy in AKS plataform and this microservice has to connect an external API that uses a SSL certificates. My doubt if there's a way to configurates the SSL certificate without use a java Keystore, my project is develop in Java language using Spring boot with WebFlux.
I found a example that how can use a jks file and Webflux but not working.
I uses the next code to generates a SslContext:
public SslContext getSslContext(){
SslContext sslContext;
try {
KeyStore ks = KeyStore.getInstance("JKS");
try (InputStream is = getClass().getResourceAsStream("/my-
truststore.jks"))
{
ks.load(is, "truststore-password".toCharArray());
}
X509Certificate[] trusted =
Collections.list(ks.aliases()).stream().map(alias -> {
try {
return (X509Certificate) ks.getCertificate(alias);
} catch (KeyStoreException e) {
throw new RuntimeException(e);
}
}).toArray(X509Certificate[]::new);
sslContext = SslContextBuilder.forClient().trustManager(trusted).build();
} catch (GeneralSecurityException | IOException e) {
throw new RuntimeException(e);
}
}
And I uses the next to generate a WebClient:
public WebClient getSslWebClient (){
try {
sslContext = getSslContext();
} catch (Exception e) {
e.printStackTrace();
}
SslContext finalSslContext = sslContext;
TcpClient tcpClient = TcpClient.create().secure(sslContextSpec ->
sslContextSpec.sslContext(finalSslContext));
HttpClient httpClient = HttpClient.from(tcpClient);
ClientHttpConnector httpConnector = new
ReactorClientHttpConnector(httpClient);
return WebClient.builder().clientConnector(httpConnector).build();
}
I appreciate your support in advance.
Regards.
Well, after days of research, I found a way to use a certificate without using the Java KeyStore (JKS). For this, I need the certificate in PEM format, then copy this certificate as a property in the parameter file and then invoke it directly:
public class SslConfig {
#Value("${ocp.http-client.certificate}")
private String certificate;
private final static String certificateType = "X.509";
private final static String alias = "root";
private static SslContext sslContext;
public WebClient getSslWebClient (){
try {
sslContext = getSslContext();
} catch (Exception e) {
e.printStackTrace();
}
SslContext finalSslContext = sslContext;
TcpClient tcpClient = TcpClient.create().secure(sslContextSpec -> sslContextSpec.sslContext(finalSslContext));
HttpClient httpClient = HttpClient.from(tcpClient);
ClientHttpConnector httpConnector = new ReactorClientHttpConnector(httpClient);
return WebClient.builder().clientConnector(httpConnector).build();
}
//Se configura el contexto sobre el cual se trabajara la comunicacion SSL
public SslContext getSslContext(){
try {
ByteArrayInputStream is = new ByteArrayInputStream(certificate.getBytes());
final KeyStore keyStore = readKeyStore(is);
X509Certificate[] trusted = Collections.list(keyStore.aliases()).stream().map(alias -> {
try {
return (X509Certificate) keyStore.getCertificate(alias);
} catch (KeyStoreException e) {
System.out.println(e.getMessage());
throw new RuntimeException(e);
}
}).toArray(X509Certificate[]::new);
sslContext = SslContextBuilder.forClient().trustManager(trusted).build();
}catch (GeneralSecurityException | SSLException e ){
System.out.println(e.getMessage());
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
}
return sslContext;
}
private static KeyStore readKeyStore(InputStream is) throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
CertificateFactory cf = CertificateFactory.getInstance(certificateType);
Certificate cert = null;
while (is.available() > 0) {
cert = cf.generateCertificate(is);
}
ks.setCertificateEntry(alias, cert);
return ks;
}
}
After this, I can make a request and get the response what I need.
I am trying to make an SSL conection to a server. I have created a Truststore and imported the server's certificate as well as mine as trusted entries into the Keystore. The server guys also have imported my certificate into their keystore. But when i try to connect, i get this error:
Received fatal alert: bad_certificate
On the server, they are getting this error:
javax.net.ssl.SSLHandshakeException: null cert chain
What could i be possibly be doing wrong?, How do i fix this error? I have been battling this issue for a very long time now.
My Client Code
import java.io.*;
import java.net.*;
import java.security.*;
import java.util.Enumeration;
import javax.net.ssl.*;
public class SSLConnect {
public String MakeSSlCall(String meternum) {
String message = "";
FileWriter file = null;
try {
file = new FileWriter("C:\\SSLCERT\\ClientJavalog.txt");
} catch (Exception ee) {
message = ee.getMessage();
}
//writer = new BufferedWriter(file );
try {
file.write("KeyStore Generated\r\n");
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream("C:\\SSLCERT\\newclientkeystore"), "client".toCharArray());
file.write("KeyStore Generated\r\n");
Enumeration enumeration = keystore.aliases();
while (enumeration.hasMoreElements()) {
String alias = (String) enumeration.nextElement();
file.write("alias name: " + alias + "\r\n");
keystore.getCertificate(alias);
file.write(keystore.getCertificate(alias).toString() + "\r\n");
}
TrustManagerFactory tmf =TrustManagerFactory.getInstance("SunX509");
tmf.init(keystore);
file.write("KeyStore Stored\r\n");
SSLContext context = SSLContext.getInstance("SSL");
TrustManager[] trustManagers = tmf.getTrustManagers();
context.init(null, trustManagers, null);
SSLSocketFactory f = context.getSocketFactory();
file.write("About to Connect to Ontech\r\n");
SSLSocket c = (SSLSocket) f.createSocket("192.168.1.16", 4447);
file.write("Connection Established to 196.14.30.33 Port: 8462\r\n");
file.write("About to Start Handshake\r\n");
c.startHandshake();
file.write("Handshake Established\r\n");
file.flush();
file.close();
return "Connection Established";
} catch (Exception e) {
try {
file.write("An Error Occured\r\n");
file.write(e.getMessage() + "\r\n");
file.flush();
file.close();
} catch (Exception eee) {
message = eee.getMessage();
}
return "Connection Failed";
}
}
}
Keytool commands for creating my truststore
keytool -import -alias client -file client.cer -keystore MyKeystore -storepass mystore
keytool -import -alias server -file server.cer -keystore MyKeystore -storepass mystore
And i have also added the two certificates to my cacerts keystore
It's been a while, but I had to face similar issue. Here is my working code:
Properties systemProps = System.getProperties();
systemProps.put("javax.net.debug","ssl");
systemProps.put("javax.net.ssl.trustStore","<path to trustore>");
systemProps.put("javax.net.ssl.trustStorePassword","password");
System.setProperties(systemProps);
SSLContext sslcontext;
KeyStore keyStore;
final char[] JKS_PASSWORD = "password".toCharArray();
final char[] KEY_PASSWORD = "password".toCharArray();
try {
final InputStream is = new FileInputStream("<path_to_keystore.pkcs12>");
keyStore = KeyStore.getInstance("pkcs12");
keyStore.load(is, JKS_PASSWORD);
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, KEY_PASSWORD);
sslcontext=SSLContext.getInstance("TLS");
sslcontext.init(kmf.getKeyManagers(), null, new java.security.SecureRandom());
} catch (Exception ex) {
throw new IllegalStateException("Failure initializing default SSL context", ex);
}
SSLSocketFactory sslsocketfactory = sslcontext.getSocketFactory();
DataOutputStream os = null;
try {
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket();
sslsocket.connect(new InetSocketAddress(host, port), connectTimeout);
sslsocket.startHandshake();
os = new DataOutputStream(sslsocket.getOutputStream());
// log.info("Sending echo packet");
String toSend = "{\"echo\":\"echo\"}";
os.writeBytes(toSend);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
i am a relative novice at Android and have had issues getting a simple SSL connection working to a java server.
I know the java server works as I tested it using the same keystore as the server and a java client.
The Android client does send something as the java server accepts a connection and displays a null value for a readline variable, and no error message.
I have my keystore, and truststore in bks format, and added to the res/raw folder.
Android Client:
SSLContext sslContext = SSLContext.getDefault();
KeyStore trustSt = KeyStore.getInstance("BKS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
InputStream trustStoreStream = this.getResources().openRawResource(R.raw.truststore);
trustSt.load(trustStoreStream, "password".toCharArray());
trustManagerFactory.init(trustSt);
KeyStore keyStore = KeyStore.getInstance("BKS");
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
InputStream keyStoreStream = this.getResources().openRawResource(R.raw.keystore);
keyStore.load(keyStoreStream, "password".toCharArray());
keyManagerFactory.init(keyStore, "password".toCharArray());
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
}
catch (NoSuchAlgorithmException nsae){Log.d("SSL", nsae.getMessage());}
catch (KeyStoreException kse){Log.d("SSL", kse.getMessage());}
catch (IOException ioe){Log.d("SSL", ioe.getMessage());}
catch (CertificateException ce){Log.d("SSL", ce.getMessage());}
catch (KeyManagementException kme){Log.d("SSL", kme.getMessage());}
catch(AccessControlException ace){Log.d("SSL", ace.getMessage());}
catch(UnrecoverableKeyException uke){Log.d("SSL", uke.getMessage());}
try{
//error catch
String error = "test";
sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
s = (SSLSocket) sslsocketfactory.createSocket("192.168.2.101", port);
outStream = s.getOutputStream();
outStreamWriter = new OutputStreamWriter(outStream);
bufferedWriter = new BufferedWriter(outStreamWriter);
bufferedWriter.write(error + "\n");
bufferedWriter.flush();
} //end try
catch (UnknownHostException e) {e.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
finally{
if (s != null){
try {s.close();}
catch (IOException e) {e.printStackTrace();}
}
}//end finally
}
I have specified a truststore but do not not how to initialise the truststore on the socket.
Any help would be appreciated.
I think changing this line
sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
to use the SSLSocketFactory(KeyStore truststore) constructor may solve your problem.
sslsocketfactory = new SSLSocketFactory(trustSt);
I would like to know what's the equivalent in java of the following :
-Djavax.net.ssl.trustStore=keystore.jks -Djavax.net.ssl.keyStore=keystore.jks
-Djavax.net.debug=ssl -Djavax.net.ssl.keyStorePassword=test JavaFile
I would like to load the keystore otherwise than sending it as arguments from the command line. I've been working with :
private TcpLink createSSL() {
KeyStore keyStore = null;
TrustManagerFactory tmf = null;
SSLContext ctx = null;
SSLSocket socket = null;
TcpLink smscLink = null;
try {
keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
LOGGER.info("Got keystore");
keyStore.load(new FileInputStream("/root/keystore.jks"), "test".toCharArray());
LOGGER.info("Loaded keystore");
tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
LOGGER.info("Inited keystore");
ctx = SSLContext.getInstance("TLSv1");
ctx.init(null, tmf.getTrustManagers(), null);
SSLSocketFactory factory = ctx.getSocketFactory();
socket = (SSLSocket)factory.createSocket("100.100.201.189", 8807);
LOGGER.info("Got socket");
smscLink = new TcpLink(socket);
return smscLink;
} catch (KeyStoreException e) {
LOGGER.error("Key store exception : " + e);
} catch (NoSuchAlgorithmException e) {
LOGGER.error("NoSuchAlgorithmException : " + e);
} catch (CertificateException e) {
LOGGER.error("CertificateException : " + e);
} catch (FileNotFoundException e) {
LOGGER.error("FileNotFoundException : " + e);
} catch (IOException e) {
LOGGER.error("FileNotFoundException : " + e);
} catch (KeyManagementException e) {
LOGGER.error("KeyManagementException : " + e);
} catch (Exception e) {
LOGGER.error("Exception : " + e);
}
return null;
}
but I get :
javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1293)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:65)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
Any ideas are welcome !
Thx
You can set the System properties this way:
System.setProperty("javax.net.ssl.keyStore", '/path/to/keystore.jks');
System.setProperty("javax.net.ssl.keyStorePassword", 'your-password-here');
They will be used system-wide (in this instance of JVM), so probably you want to do it at initialisation time.
It works using this piece of code :
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(this.getCertificateContent(), "test".toCharArray());
kmf.init(keyStore, "test".toCharArray());
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("TLSv1");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SSLSocketFactory factory = ctx.getSocketFactory();
socket = (SSLSocket)factory.createSocket("100.125.100.1", 8775);
If you want, here's an API to create SSLSocket and SSLServerSocket easyly:
https://github.com/gpotter2/SSLKeystoreFactories
It does not require any other jars.... just get the files and use them like:
SSLSocket s = SSLSocketKeystoreFactory.getSocketWithCert(ip, port, Main.class.getResourceAsStream("/mykey.jks"), "password")
Or:
SSLServerSocket s = SSLServerSocketKeystoreFactory.getSocketWithCert(port, Main.class.getResourceAsStream("/mykey.jks"), "password")
That's much easier to use :)