Dart secure connection with private key: SSLV3_ALERT_HANDSHAKE_FAILURE - java

I have a site certificate ('tls_connection_cert') for TSL connection and a private certificate ('private_cert.p12') for authentication. Whenever I want to make connection in dart I get an error SSLV3_ALERT_HANDSHAKE_FAILURE(tls_record.cc:586) with no extra information.
Dart code:
SecurityContext context = new SecurityContext(withTrustedRoots: true)
..setTrustedCertificates('tls_connection_cert')
..usePrivateKey('private_cert.p12', password: 'password');
await SecureSocket.connect(
"service_host", 9002, context: context, onBadCertificate: _onSelfSignedCertificate).then((socket) {
print('Connected to: '
'${socket.remoteAddress.address}:${socket.remotePort}');
socket.destroy();
});
I already uses his service with a JAVA code which work perfectly, with no errors. The service in question is already used by the java code for 3 years now.
Java code:
KeyManager[] privateCert; // private_cert.p12
TrustManager[] publicCert; // tls_connection_cert
SSLContext ssl = SSLContext.getInstance("TLS");
ssl.init(privateCert.getKeyManagers(), publicCert.getTrustManagers(), null);
SSLSocket socket = (SSLSocket)ssl.getSocketFactory().createSocket("service_host", 9002);
socket.startHandshake();
socket.close();
Online service only allow TLSv1.2. Project is a Flutter project build in Android Studio on Windows 10 machine.
How can I found what’s wrong with dart code?

Related

Loading pk12 file within the application in Wildfly 16

I have a code which calls a rest api protected with certificate, and that code was working for some time without issues, until I migrate application from Wildfly 10 to Wildfly 16.
The code itself is straight forward, it creates http request and set custom socket factory: `
private SSLSocketFactory getSSLSocketFactory() {
char[] certPassword = {}; // password hidden from you
try {
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
final SSLContext sslContext = SSLContext.getInstance("TLS");
final KeyStore keyStore = KeyStore.getInstance("PKCS12");
try (FileInputStream fileInputStream = new FileInputStream(new File("cert.pk12"))) {
keyStore.load(fileInputStream, certPassword);
} catch (final Exception e) {
logger.error("....", e);
}
this.readLoadCertificateFile(keyStore);
kmf.init(keyStore, certPassword);
sslContext.init(kmf.getKeyManagers(), new TrustManager[]{new AnyTrust()}, null);
return sslContext.getSocketFactory();
} catch (Exception e) {
logger.error(".....", e);
}
throw new IllegalStateException("....");
}
HTTPRequest req = ....
req.setSSLSocketFactory(getSSLSocketFactory());
tokenHttpResp = req.send();`
`
All seems good but when I run this code from within WF16 it throws
IOException: Failed to load .p12 keystore:C:\Cert\cert.p12; error
constructing MAC: java.lang.SecurityException: JCE cannot authenticate
the provider BC;
org.bouncycastle.jcajce.provider.keystore.pkcs12.PKCS12KeyStoreSpi.engineLoad::-1
java.security.KeyStore.load in KeyStore.java::1445
I checked for the bouncy castle lib, and I don't have it in the application itself...
If any one knows what the issue could be I would appreciate any input.
Alternatively, I'm looking to move this socket factory creation in to the container itself, seems like Wildfly Elytron subsystem specifically designed for this, is it a good idea?
Answering my own question.
The error message like "JCE cannot authenticate the provider BC" indicating that the jar file, the Security Provider is loaded from, cannot be verified by JVM. Either the jar is not signed or signature cannot be verified. In my case, the newer Wildfly version has a newer version of bouncy castle library, which for some reason, cannot be verified by Java 8. Interesting enough, that it is fine with Java 10. Some people on the Internet says that this issue only occurs in Oracle's JVM and does not exist for Open JDK, I haven't tested it, just think it worth to mention.
To overcome issue you need to tell JVM to trust the security provider, for that, make sure that the Security Provider you want to use/JVM decided to use, mentioned in jre/lib/security/java.security file, it should have line like:
security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider
Then copy Jars with Security Provider into /jre/lib/ext folder

Problem Connecting a Java Client (JMS) to a IBM MQ

I'm trying to consume an IBM MQ (version 8.0.0.8) with SSL using a Java client built basically with:
Oracle JKD 8 and IBM JRE 7 (for testing purposes I have one client for each of them)
com.ibm.mq.allclient-9.1.0.0.jar
javax.jms-api-2.0.1.jarspring-jms-4.3.7.RELEASE.jar
spring-jms-4.3.7.RELEASE.jar
The MQ is a Request/Reply type.
I have the correct certificate and all MQ properties set, but for some reason the connection “drops” and I get no errors on my client side and my requests never get any response and keeps running “forever”, never getting any response. The only clue that I have is an error message in the MQ log that says:
Process(31600.16) User(QMQM) Jobname(JOB_NAME)
Host(HOST_NAME)
VRMF(8.0.0.8) QMgr(MANAGER_NAME)
AMQ9638: SSL communications error for channel 'CHANNEL_NAME'. EXPLANATION:
Cause . . . . . : An unexpected SSL communications error occurred for a channel, as reported in the preceding messages. The
channel is 'CHANNEL_NAME';
The strange thing is that the SSL Handshake happens, my certificate is accepted by the MQ, but for some reason something happens after this. I’m trying using both Oracle JRE 8 and IBM JRE 7. Maybe is something on MQ side (IBM MQ v8.0.0.8) or some configuration that I’m missing on my side.
I have already installed the JCE Unlimited Policies, so the problem is not CipherSpec X CipherSuite.
I'm using -Djavax.net.debug=all and I can see that my certificate is being used correctly and I can't see any problems there...
My contact point on the MQ Team told me that for some reason my application is revoking the certificate (something related with CLR), but I have no idea why this would happen.
My Java code:
public Message callMQ() {
Message message = null;
try {
MQConnectionFactory factory = mqQueueConnectionFactory();
JMSContext context = factory.createContext();
Destination requestQueue = context.createQueue("queue:///REQUEST_QUEUE");
Destination replyQueue = context.createQueue("queue:///REPLY_QUEUE");
JmsTemplate jmsTemplate = new JmsTemplate(factory);
FIXMLRootInbound inbound = new FIXMLRootInbound();
String xml = XmlUtil.xmlObjectToString(inbound);
message = jmsTemplate.sendAndReceive(requestQueue,
session -> {
Message req = session.createTextMessage(xml);
req.setJMSCorrelationID(UUID.randomUUID().toString());
req.setJMSDestination(requestQueue);
req.setJMSReplyTo(replyQueue);
return req;
});
} catch (Throwable e) {
e.printStackTrace();
}
return message;
}
private MQConnectionFactory mqQueueConnectionFactory() throws NoSuchAlgorithmException, KeyStoreException,
IOException, CertificateException, UnrecoverableKeyException, KeyManagementException, JmsException {
SSLSocketFactory sslSocketFactory = sslContext().getSocketFactory();
MQEnvironment.sslSocketFactory = sslSocketFactory;
MQEnvironment.sslCipherSuite = "TLS_RSA_WITH_AES_256_CBC_SHA";
MQEnvironment.sslFipsRequired = false;
MQConnectionFactory mqQueueConnectionFactory = new MQQueueConnectionFactory();
mqQueueConnectionFactory.setHostName(host);
try {
mqQueueConnectionFactory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
mqQueueConnectionFactory.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE,
WMQConstants.WMQ_CM_CLIENT);
mqQueueConnectionFactory.setQueueManager(queueManager);
mqQueueConnectionFactory.setSSLCipherSuite("TLS_RSA_WITH_AES_256_CBC_SHA");
mqQueueConnectionFactory.setCCSID(285);
mqQueueConnectionFactory.setChannel(channel);
mqQueueConnectionFactory.setPort(port);
mqQueueConnectionFactory.setSSLSocketFactory(sslSocketFactory);
mqQueueConnectionFactory.setSSLFipsRequired(false);
} catch (Exception e) {
log.error("Error creating MQQueueConnectionFactory.", e);
}
return mqQueueConnectionFactory;
}
private SSLContext sslContext() throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
try (InputStream cert = new FileInputStream("C:\\myplace\\Dev\\Certificates\\MY_KEYSTORE.jks")) {
final KeyStore caCertsKeyStore = KeyStore.getInstance("JKS");
caCertsKeyStore.load(cert, "changeit".toCharArray());
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker();
rc.setOptions(EnumSet.of(
PKIXRevocationChecker.Option.PREFER_CRLS,
PKIXRevocationChecker.Option.ONLY_END_ENTITY,
PKIXRevocationChecker.Option.SOFT_FAIL,
PKIXRevocationChecker.Option.NO_FALLBACK));
PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(caCertsKeyStore, new X509CertSelector());
pkixParams.addCertPathChecker(rc);
kmf.init(caCertsKeyStore, "changeit".toCharArray());
tmf.init( new CertPathTrustManagerParameters(pkixParams) );
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
return sslContext;
} catch (Exception e) {
throw new RuntimeException("Exception creating SSLContext", e);
}
}
Since you are using the 9.1.0.0 com.ibm.mq.allclient.jar you do not need all of the code you have related to the key store, for example:
SSLSocketFactory sslSocketFactory = sslContext().getSocketFactory();
//Note that MQEnvironment is used with IBM MQ Classes for Java not IBM MQ Classes for JMS
MQEnvironment.sslSocketFactory = sslSocketFactory;
MQEnvironment.sslCipherSuite = "TLS_RSA_WITH_AES_256_CBC_SHA";
MQEnvironment.sslFipsRequired = false;
mqQueueConnectionFactory.setSSLSocketFactory(sslSocketFactory);
private SSLContext sslContext() throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
try (InputStream cert = new FileInputStream("C:\\myplace\\Dev\\Certificates\\MY_KEYSTORE.jks")) {
final KeyStore caCertsKeyStore = KeyStore.getInstance("JKS");
caCertsKeyStore.load(cert, "changeit".toCharArray());
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker();
rc.setOptions(EnumSet.of(
PKIXRevocationChecker.Option.PREFER_CRLS,
PKIXRevocationChecker.Option.ONLY_END_ENTITY,
PKIXRevocationChecker.Option.SOFT_FAIL,
PKIXRevocationChecker.Option.NO_FALLBACK));
PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(caCertsKeyStore, new X509CertSelector());
pkixParams.addCertPathChecker(rc);
kmf.init(caCertsKeyStore, "changeit".toCharArray());
tmf.init( new CertPathTrustManagerParameters(pkixParams) );
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
return sslContext;
} catch (Exception e) {
throw new RuntimeException("Exception creating SSLContext", e);
}
}
You can instead replace that with setting the following two system properties, this will work with both Oracle and IBM Java:
System.setProperty("javax.net.ssl.keyStore", "C:\\myplace\\Dev\\Certificates\\MY_KEYSTORE.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
The above settings have always worked for IBM Java, but with Oracle Java this did not work with older versions of MQ. It was fixed for Oracle java in the following versions of IBM MQ (Base 9.0 and 9.1 have the same fix):
Version Maintenance Level
v7.1 7.1.0.8
v7.5 7.5.0.7
v8.0 8.0.0.5
IBM Java and Oracle Java have different CipherSuite names, these are documented in the IBM MQ v9.1 Knowledge center page "TLS CipherSpecs and CipherSuites in IBM MQ classes for JMS.
You have specified TLS_RSA_WITH_AES_256_CBC_SHA in the posted code, this would be the SSLCIPH value on the MQ Queue manager SVRCONN channel, and would map to the following CipherSuites:
IBM Java: SSL_RSA_WITH_AES_256_CBC_SHA
Oracle Java: TLS_RSA_WITH_AES_256_CBC_SHA
Related to the above, if you are using Oracle Java you need to set the following system property so that the MQ JMS classes will be able to use the right mapping of the Oracle CipherSuite name:
System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false");
The error you provided appears to be from the IBM i MQ Queue manager, but does not provide enough information to diagnose the problem.
The error states the following:
An unexpected SSL communications error occurred for a channel, as reported in the preceding messages.
Can you edit your question and provide the details from the "preceding messages".
You stated
for some reason my application is revoking the certificate (something related with CLR)
It could be that the MQ queue manager is attempting itself to connect to the OCSP server specified in the your client cert's AuthorityInfoAccess (AIA) certificate extension. If MQ can not reach this OCSP server with a default configuration the connection will be denied. If you are unable to update your network to allow connection to the OCSP server then you can disable this check but note that you will not know if a cert is revoked. To disable the checking the following can be added to the queue manager's qm.ini file SSL stanza:
SSL:
OCSPAuthentication=Optional
OCSPCheckExtensions=no
One last comment, the CipherSuite you listed in your example code TLS_RSA_WITH_AES_256_CBC_SHA is a TLS1.0 CipherSuite. Like SSL before it this and TLS1.1 are commonly deprecated across many industries. I looked for reference to post and a google of "tls 1.0 end of life" gives many references.
Quoting one "TLS 1.0 end-of-life on June 30th, 2018" below:
The Deadline The PCI Council is responsible for determining when older protocols are phased out. They initially decided TLS 1.0 would
reach end of life on 30 June 2016, later extending the date to 30 June
2018. The final deadline has past and all web servers, web browsers, web software and email applications have had to discontinue TLS 1.0
support, or fall foul of important security updates.
I would suggest choosing one listed as TLS1.2 in the Knowledge center page I linked to above for example TLS_RSA_WITH_AES_256_CBC_SHA256.

how we make Riak KV Cluster with security implementation using java client

Can anybody tell how we interact with security enables Riak KV Cluster using java client.
I tried with following java code to interact with security enabled riak cluster, but getting SSLEngine Problem, Below is the java code ......
InputStream inputStream = null;
KeyStore ks = null;
try {
inputStream = new FileInputStream("/etc/ssl/certs/rootCA.pem");
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
X509Certificate caCert = (X509Certificate) certFactory.generateCertificate(inputStream);
inputStream.close();
ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, "password".toCharArray());
ks.setCertificateEntry("cacert", caCert);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (RiakConfig.class) {
List<RiakNode> riakNodeList = new ArrayList<RiakNode>();
for (final String riakServer : riakServerArray) {
RiakNode node = new RiakNode.Builder()
.withMinConnections(10)
.withMinConnections(50)
.withRemoteAddress(riakServer.split(":")[0])
.withRemotePort(Integer.parseInt(riakServer.split(":")[1]))
.withAuth("riakuser", "riakuser", ks)
.build();
riakNodeList.add(node);
}
cluster = new RiakCluster.Builder(riakNodeList).build();
cluster.start();
}
suggenst anyone how we do that???
getting SSLEngine Problem
Please, always provide the specific problem you are getting. "getting SSLEngine Problem" is a useless bit of information.
Based on this document it appears you are using the correct steps. Without more information about the security issue you are getting, further help is impossible. Most likely you do not have your certificates set up correctly. The RabbitMQ documentation includes a comprehensive TLS/SSL troubleshooting guide that can help you determine if your certificates were created correctly.
Additionally, I suggest that you review how the Riak Java Client sets up certificates and then uses them.
This part of the Makefile is where certs are imported with keytool:
https://github.com/basho/riak-java-client/blob/develop/Makefile#L43-L62
This is a class that uses the key store to create connections for use in tests:
https://github.com/basho/riak-java-client/blob/develop/src/test/java/com/basho/riak/client/core/operations/itest/RiakJKSConnection.java
Achually this is working fine for single node, in cluster i am facing SSL Engine Problem.

SSL Sockets - Java and Certificates?

I am trying to implement a SSL socket between an Android App and a Python API.
The code below...
SSLSocketFactory ssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
Socket s = ssf.createSocket("10.0.2.2", 5001);
DataOutputStream myDataOut = new DataOutputStream(s.getOutputStream());
myDataOut.writeUTF("Hello Server");
myDataOut.flush();
myDataOut.close();
s.close();
doesn't work as you can see:
590.0750 - Establishing connection to ('127.0.0.1', 50888)
590.0970 - Error while connecting
590.0970 - Error information: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:590)
I believe it doesn't because I am not specifying the certificate.
See a Python working example of client:
import socket, ssl, pprint
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket(s,
ca_certs="server.crt",
cert_reqs=ssl.CERT_REQUIRED)
ssl_sock.connect(('localhost', 5001))
print repr(ssl_sock.getpeername())
print ssl_sock.cipher()
print pprint.pformat(ssl_sock.getpeercert())
ssl_sock.write("Hello from the client...")
How can I specify the certificate in Java like I did in Python?
Taken that I understood you right, this answer to a related question might be interesting for you. It describes the ways of specififying the certifications.

Example of using ssl with org.apache.http.impl.bootstrap.HttpServer from Apache HttpCore 4.4.3

I have successfully created an embedded HttpServer using the example at https://hc.apache.org.httpcomponents-core-ga/httpcore/examples/org/apache/http/examples/HttpFileServer.java, which handles http: traffic just fine. Now I would like to extend this to support TLS.
I copied some likely looking code from here: https://hc.apache.org/httpcomponents-core-ga/tutorial/html/blocking-io.html#d5e455
But some parts of it are showing up as deprecated, which makes me wonder whether this example is out of date and whether the tree I'm at is the one where I should be barking. Even if that weren't the case, I am having trouble finding the relationship between HttpServer and DefaultBHttpClientConnection (mentioned in the example). I suspect that I should be using DefaultBHttpServerConnection but I am so far unable to find that either.
Is there a newer example of this anywhere?
Michael D. Spence
Mockingbird Data Systems, Inc.
I am not sure understand the problem you are having. All you need is to provide a correctly initialized SSLContext instance to ServerBoostrap . HttpCore ships with SSLContextBuilder specifically designed to simplify the process of SSLContext initialization.
The example included in HttpCore distribution pretty much shows every step required to set up SSL/TLS transport layer.
SSLContext sslcontext = null;
if (port == 8443) {
// Initialize SSL context
URL url = HttpFileServer.class.getResource("/my.keystore");
if (url == null) {
System.out.println("Keystore not found");
System.exit(1);
}
sslcontext = SSLContexts.custom()
.loadKeyMaterial(url, "secret".toCharArray(), "secret".toCharArray())
.build();
}
SocketConfig socketConfig = SocketConfig.custom()
.setSoTimeout(15000)
.setTcpNoDelay(true)
.build();
final HttpServer server = ServerBootstrap.bootstrap()
.setListenerPort(port)
.setServerInfo("Test/1.1")
.setSocketConfig(socketConfig)
.setSslContext(sslcontext)
.setExceptionLogger(new StdErrorExceptionLogger())
.registerHandler("*", new HttpFileHandler(docRoot))
.create();
server.start();

Categories

Resources