Securing TCP traffic and certificate pinning? - java

We develop a Java application that serves requests over TCP. We also develop client libraries for the application, where each library supports a different language/platform (Java, .NET, etc.).
Until recently, TCP traffic was confined to a secure network. To support usage on an insecure network we implemented TLS using the recipes in java-plain-and-tls-socket-examples. There are recipes here for both server and client, and a script to generate an X.509 certificate. Below is a summary of the recipe for TLS with server-only authentication:
Create an X.509 root certificate that is self-signed.
Configure the server with a keystore file that contains the certificate's identifying data plus the public and private keys.
Configure the client with a trust store file that contains the same identifying data plus only the public key.
When connecting, the client validates the certificate received from the server by comparing its identifying data with the corresponding data in the client's trust store. (This looks like certificate pinning.)
We assume for now that this approach is valid for securing TCP traffic. Signing by a certificate authority seems unnecessary because we control both server and client.
Initial testing shows that the implementation is working in our Java server and Java client:
Client accepts a server certificate that matches data in the client's trust store.
Client rejects a non-matching server certificate.
TCP packets captured by tcpdump contain encrypted data.
.NET Client
We use SslStream to encrypt TCP traffic. As the documentation suggests, we do not specify a TLS version; instead we throw an exception if the version is below 1.2.
We're not confident about how to use X509Chain.ChainPolicy.CustomTrustStore correctly, because the documentation omits information like use cases for this type, and for option types like X509KeyStorageFlags and X509VerificationFlags.
The code below aims to mimic the recipe outlined above, i.e. configure a trust store data structure for the client to use when validating a server certificate. This approach seems equivalent to importing the certificate into the operating system's trust store.
// Import the trust store.
private X509Certificate2Collection GetCertificates(string storePath, string storePassword)
{
byte[] bytes = File.ReadAllBytes(storePath);
var result = new X509Certificate2Collection();
result.Import(bytes, storePassword, X509KeyStorageFlags.EphemeralKeySet);
return result;
}
// Callback function to validate a certificate received from the server.
// fCertificates stores the result of function GetCertificates.
private bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
// Do not allow this client to communicate with unauthenticated servers.
//
// With a self-signed certficate, sslPolicyErrors should be always equal to
// SslPolicyErrors.RemoteCertificateChainErrors.
var result = (SslPolicyErrors.RemoteCertificateChainErrors == sslPolicyErrors);
if (result)
{
// The values below are default values: set them to be explicit.
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
chain.ChainPolicy.CustomTrustStore.AddRange(fCertificates);
result = chain.Build((X509Certificate2)certificate);
}
return result;
}
// Initialize SslStream.
private SslStream GetStream(TcpClient tcpClient, string targetHost)
{
SslStream sslStream = new SslStream(
tcpClient.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
try
{
sslStream.AuthenticateAsClient(targetHost);
// require TLS 1.2 or higher
if (sslStream.SslProtocol < SslProtocols.Tls12)
{
throw new AuthenticationException($"The SSL protocol ({sslStream.SslProtocol}) must be {SslProtocols.Tls12} or higher.");
}
}
catch (AuthenticationException caught)
{
sslStream.Dispose();
throw caught;
}
return sslStream;
}
Initial testing has yielded results that vary depending on the operating system:
When deployed to Ubuntu on WSL2, this code:
Accepts a valid server certificate.
Rejects an invalid server certificate.
Encrypts TCP packets.
Automatically uses TLS 1.3.
Given a valid server certificate, the callback function argument sslPolicyErrors is equal to SslPolicyErrors.RemoteCertificateChainErrors (expected).
When deployed to MacOS:
This code automatically uses TLS 1.2.
Given a valid server certificate, the callback function argument sslPolicyErrors includes these values:
SslPolicyErrors.RemoteCertificateNameMismatch (unexpected).
SslPolicyErrors.RemoteCertificateChainErrors (expected).
Questions
In what ways could security be compromised with this .NET code?
Upon reviewing discussions about "certificate name mismatch" (see SslPolicyErrors.RemoteCertificateNameMismatch above), it seems that our server certificate should include a subjectAltName field to specify allowed DNS names. Is this necessary, or would it be reasonable, as we are using certificate pinning, to ignore sslPolicyErrors when validating the server certificate?

I can't answer your specific questions but here is some thoughts:
You have not mentioned anything about how the server authenticates clients. So you might consider implementing something like client certificates. If you control both you probably want some way to ensure random attackers cannot connect.
You might consider creating a threat model. In many cases it is the things that you haven't thought about that cause problems.
If you are handling national security data or financial data you might want an external audit. Such might even be required in some cases.
If there is no way an attacker could sell, use, or ransom the data, then you will probably not be directly targeted. So you might worry more about mass attacks against known vulnerabilities, i.e. keep all your software up to date.
Consider other ways to mitigate risks. Are your server/client running in least privilege possible? Are you using a DMZ? Are firewalls correctly configured? Are credentials for support etc well managed?

Related

Validating a leaf certificate from a third party in java 8

I am looking for a way to validate a java.security.cert.X509Certificate object that is sent from a third party. The certificate provider is using dns or ldap to fetch the certificate. I have included a link with additional information on how the certificate is being retrieved.
http://wiki.directproject.org/w/images/2/24/Certificate_Discovery_for_Direct_Project_Implementation_Guide_v4.1.pdf
I also need to know protocols and default ports that would be used in any of the verification steps. The certificate needs to meet the following criteria from page 13 section 4 of this document:
http://wiki.directproject.org/w/images/e/e6/Applicability_Statement_for_Secure_Health_Transport_v1.2.pdf
Has not expired.
Has a valid signature with a valid message digest
Has not been revoked
Binding to the expected entity
Has a trusted certificate path
Item 1 is straight forward to compare the dates from the getNotAfter and getNotBefore methods on the certificate object to the current date or to use the checkValidity method which throws a checked exception.
For item #2, I see a method to get the signature, but I am unsure how to generate the message digest and verify that the signature and message digest are both valid.
For item #3, The certification revocation list seems to be mixed with some other data by calling this method on the certificate getExtensionValue("2.5.29.31"). Retrieving the certification revocation list data seems possible over http, and ocsp seems to be based on http. I haven't been able to find how to do this in java.
For item #4, I am not sure what binding means in the context of certificates, or what is involved in verifying it.
For item #5, It looks like the data for intermediary certificates is mixed with some other data by calling this method on the certificate getExtensionValue("1.3.6.1.5.5.7.1.1"). CertPathValidator looks like it may be able to help verify this information once the certificates data is retrieved over http.
Certificate validation is a complex task. You can perform all the validations you need manually (expiration, revocation, certification chain) using native Java 8 support or Bouncycastle. But the option that I would recommend is to use a specific library that has already taken into account all the possibilities.
Take a look to DSS documentation and Certificate Verification example
// Trusted certificates sources, root and intermediates (#5 )
CertificateSource trustedCertSource = null;
CertificateSource adjunctCertSource = null;
// The certificate to be validated
CertificateToken token = DSSUtils.loadCertificate(new File("src/main/resources/keystore/ec.europa.eu.1.cer"));
// Creates a CertificateVerifier using Online sources. It checks the revocation status with the CRL lists URLs or OCSP server extracted from the certificate #3
CertificateVerifier cv = new CommonCertificateVerifier();
cv.setAdjunctCertSource(adjunctCertSource);
cv.setTrustedCertSource(trustedCertSource);
// Creates an instance of the CertificateValidator with the certificate
CertificateValidator validator = CertificateValidator.fromCertificate(token);
validator.setCertificateVerifier(cv);
// We execute the validation (#1, #2, #3, #5)
CertificateReports certificateReports = validator.validate();
//The final result. You have also a detailedReport and DiagnosticData
SimpleCertificateReport simpleReport = certificateReports.getSimpleReport();
The validation will perform all the steps you indicate, including expiration, signing of the certificate, revocation, and checking the chain of trust (including the download of intermediate certificates).
Step # 4 I don't know exactly what you mean. I suppose to validate that the certificate corresponds to one of the certification entities of the trusted list
To load the trusted certificate sources see this
CertificatePool certPool = new CertificatePool();
CommonCertificateSource ccc = new CommonCertificateSource(certPool);
CertificateToken cert = DSSUtils.loadCertificate(new File("root_ca.cer"));
CertificateToken adddedCert = ccc.addCertificate(cert);
I will split the answer to 3 pieces. The first is the background , the second is the choice of library , implementation code (references that i had used for my implementation with due credit)
In the past i had implemented a very similar use case. I had IOT fabrications done by a vendor and to onboard them i had implement the same X509 verification process that you have mentioned.
Implementation :
For my implementation i had refered the following . You can include BC as your defaultProvider (Security.setProvider) and use the following code . The code directly solves 1,3,5. The code is here : https://nakov.com/blog/2009/12/01/x509-certificate-validation-in-java-build-and-verify-chain-and-verify-clr-with-bouncy-castle/
Now coming to 2 , the answer to that depends on how you will get the certificate from your client and what additional data will be provided by the application.
The high level flow of that is as follows
a) Client produces the certificate
b) Client does a Digest using some algorithm that is acceptable. SHA256 are quite popular, you can increase the strength based on the needs and how much compute you have. Once the client creates the digest , to prove he is the owner of the certificate you can get the digest signed using the private key of the device. This can be then transmitted to the verifier application
c) Once you have the certificate and the signature , you can then use the Certificate and Public key associated with it to verify the signature applying the same digest and then verifying the signature.A good reference is here : http://www.java2s.com/Code/Java/Security/SignatureSignAndVerify.htm
I am not a 100% sure on what 4 means. But if it means proof of identity (who is producing the certificate is bound to be who they are , signing and verifying will provide the same)
Though you can realize the use cases using java security API's , I used bouncycastle core API for realizing the use cases. Bouncycastle API's are far more rich and battle tested especially for weird EC curve algorithms we had to use & you will find that many folks swear by BouncyCastle.
Hope this helps!

How to read SNI extension in Java?

I want to find host name from TLS Client Hello Message. I want to find host name before java does complete handshake for transparent ssl proxy.
Is there any way to find SNI extension value without writing whole ssl handshake logic ?
Is Java supports ssl handshake with initial memory buffer ?
My Idea is:
Read TLS client hello message, parse it and find SNI value
Call sslSocket.startHandshake(initialBuffer) Initial buffer will contain TLS client hello packet data. So Java can do handshake.
Second Idea is to use SSLEngine class. But it seems a lot more implementation than requirement. I assume SSLEngine is used most of async in case which I don't require it.
Third idea is to implement complete TLS protocol.
Which idea is better ?
Both SSLSocket and SSLEngine lack (quite inexplicable) proper SNI support for server connections.
I came across the same problem myself and ended up writing a library: TLS Channel. It does not only that, it is actually a complete abstraction for SSLEngine, exposed as a ByteChannel. Regarding SNI, the library does the parsing of the first bytes before creating the SSLEngine. The user can then supply a function to the server channel, to select SSLContexts depending on the received domain name.
The accepted answer to this question is a bit old and does not really provide an answer to the question.
You should use a custom KeyManager when initializing the SSLContext and the trick is to use a javax.net.ssl.X509ExtendedKeyManager (note the Extended term). This will offer the possibility to expose the SSLEngine during the key alias selection process instead of the plain (useless) socket.
The method chooseEngineServerAlias(...) will be called during the SSL handshake process in order to select the proper alias (cert/key) from the KeyStore. And the SNI information is already populated and available in the SSLEngine. The trick here is to cast the SSLSession as an ExtendedSSLSession (note the Extended term) and then to getRequestedServerNames().
KeyManager[] km = new KeyManager[]
{
new X509ExtendedKeyManager()
{
public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine)
{
if( engine.getHandshakeSession() instanceof ExtendedSSLSession )
{
List<SNIServerName> sni = ((ExtendedSSLSession)engine.getHandshakeSession()).getRequestedServerNames();
// select the proper certificate alias based on SNI here
}
}
}
}
SSLContext context = SSLContext.getInstance("TLS");
context.init(km, null, null);

Difference in dealing with ssl certificate in respect of browser and jvm?

This is how browser deals with ssl certificate when connecting to https site
When i type https://myDemoSite.com in browser , first of all my browser asks for the certificate from myDemoSite.com(due to https), then myDemoSite send that certificate to browser
Once browser receives that certificate, browser will check whether it is signed by verified authority or not like verisign
If yes from second step,then as third step it checks whether certificate issues has same url which user in browser typed
Now i am connecting the https site through java program say HttpsConnectProg1.My question is how the programmei.e HttpsConnectProg1 will deal with this
certificate issued with https site connection(though certificate issued by this https site is cerified i.e signed by verified authority).
I just tried a small
programme connecting to https site which issues the certified certificate. I was expected some error like sslhandshake error or some certificate error
(as i did not add this this certified certificate in $JAVA_HOME\jre\lib\security folder)but to my surprise i did not get any error .
Now important question is does HttpsConnectProg1 checks step 3 done by browser as it is very important step? For your reference here it is
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Properties;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
public class ConnectToDemoSite {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String urlStr = "https://www.myDemoSite.com/demo1/";
URL url;
Properties reply = new Properties();
try {
url = new URL(urlStr);
URLConnection conn = url.openConnection();
if(conn instanceof HttpsURLConnection)
{
HttpsURLConnection conn1 = (HttpsURLConnection)url.openConnection();
conn1.setHostnameVerifier(new HostnameVerifier()
{
public boolean verify(String hostname, SSLSession session)
{
return true;
}
});
reply.load(conn1.getInputStream());
}
else
{
conn = url.openConnection();
reply.load(conn.getInputStream());
}
} catch (MalformedURLException e) {
e.printStackTrace();
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("reply is"+reply);
}
}
When you make a connection to an https:// URI with Java, it uses the Java Secure Socket Extension (JSSE) (unless you really want to use a custom implementation of SSL/TLS, but that's very rare).
There are multiple ways of tweaking the trust management (mainly be using custom TrustManagers), but it will use a certain number of sensible settings otherwise.
In your example, the certificate will be verified using the default SSLContext, itself configured with the default X509TrustManager, with trust anchors read from cacerts (see the table in the Customization section of the JSSE Ref. Guide).
By default, the JRE comes with a number of pre-trusted CA certificates (like most browsers or OSes) in cacerts, which is usually similar to what you would find in browsers. Here is what the JSSE Ref. Guide says about it:
IMPORTANT NOTE: The JDK ships with a limited number of trusted root
certificates in the /lib/security/cacerts file. As
documented in keytool, it is your responsibility to maintain (that is,
add/remove) the certificates contained in this file if you use this
file as a truststore.
Depending on the certificate configuration of the servers you contact,
you may need to add additional root certificate(s). Obtain the needed
specific root certificate(s) from the appropriate vendor.
If the certificate is trusted, it then checks whether the host name is valid for the intended URL. (Note that it's not the full URL that is checked, but the host name only.)
Those rules are defined in RFC 2818 (the HTTPS specification), Section 3.1. (Java 7 doesn't implement RFC 6125 yet, but the rules are very similar, especially for HTTPS.) EDIT: When the connection is established, the URLConnection (and the underlying SSLSession) is set with the host name of the server. In short, following the rules in RFC 2818, it looks into the server certificate for a DNS entry in the Subject Alternative Name (SAN) extension of the certificate to see if it matches the host name set for the connection, or look for that name in the certificate's Subject DN's Common Name (CN), when no SAN DNS entry is present.
The host name verification is normally done by the default host name verifier. In your example, you've replaced the default verifier by one that always returns true. Hence, this verification will not actually happen in your case, and everything will be accepted (you're introducing a security hole by doing this).
In addition, the default host name verification done in Java follows RFC 2818 more strictly than a number of browsers. In particular, it won't accept IP addresses in CNs.
(For the same reason as you should use a host name verifier that always returns true, you shouldn't use trust managers that don't do anything, as you'll see a number of examples around, offering a quick fix for some SSL error messages.)
Java includes root certificates from well-known certificate authorities, so if you have a real certificate, it operates much like a browser.
If you sign your own certificate, a browser will warn you and provide a UI to enable use of the certificate in the future. This is where things diverge for a Java program—the right way to handle this depends entirely on the program you are writing, and there can't be a one-size-fits-all approach.
If your application has a UI, you could do something similar to what a browser does.
On the other hand, a "headless" application is usually pre-configured with the necessary root certificates.
In the end, both browsers and the Java PKIX validation libraries are maintaining the security of TLS by requiring you to provide or approve the root certificates on which authentication ultimately depend. Without trusted root certificates, it is impossible to authenticate a server, and thus impossible to ensure privacy or integrity of communications.

Java: TCP Encryption, SSL and Netty

Ok so I have a peer to peer (client/server on one host) setup (over a local LAN), this is using Netty, a Java networking framework. I use raw TCP/IP (as in, no HTTP) for communication and transfers.
Currently all data is transferred in "plain-text" and i'm starting the process of securing such transmitted data.
I've had a good read of types of encryption/practices etc (but probably only touched the surface and its melting my brain already)
Netty includes a SSL implemntation, heres some links to hopefully better explain myself:
http://docs.jboss.org/netty/3.2/xref/org/jboss/netty/example/securechat/package-summary.html
Inside "SecureChatTrustManagerFactory" there are 2 methods:
public void checkClientTrusted(
X509Certificate[] chain, String authType) throws CertificateException {
// Always trust - it is an example.
// You should do something in the real world.
// You will reach here only if you enabled client certificate auth,
// as described in SecureChatSslContextFactory.
System.err.println(
"UNKNOWN CLIENT CERTIFICATE: " + chain[0].getSubjectDN());
}
public void checkServerTrusted(
X509Certificate[] chain, String authType) throws CertificateException {
// Always trust - it is an example.
// You should do something in the real world.
System.err.println(
"UNKNOWN SERVER CERTIFICATE: " + chain[0].getSubjectDN());
}
"SecureChatKeyStore" contains a hard coded certificate from what I can see.
So my questions are:
Do I need to generate a certificate?
if so, each time the application is run?
if so, per client?
if so, is this certification passed between client and server?
if so, how is it done securely?
I'm not entirely sure where to start.
From what I can see the Netty implementation is saying "Here's the basis of creating secure connections, but we have left out the part that actually makes them secure/authenticated".
Any other pointers/tips I should know about?
Thank you in advance.
As others have pointed out, there is a difference between application security and transport link security. I think you are aiming for the last one as you mainly mention encryption. Encryption offers confidentiallity from eavesdroppers. Furhermore, as SSL also incorporates message authentication code, it will also offer protection of a third party altering packets during transit. It does not provide any protection of messages once received.
As you may have noticed on the internet for HTTPS connections, you will need at least a server certificate. This certificate can remain static, although it should contain an expiry date at which time you should replace the certificate. The server certificate should be trusted by the client (e.g. by embedding it as a resource). You can also use SSL with client authentication, but that means you need to have ample security measures to keep the private key on the client safe.
It's probably best to start off with a "self-signed" server certificate only. Thats the one you need to trust in the checkServerTrusted method. Basically, the chain is simply that one certificate.

Choosing SSL client certificate in Java

Our system communicates with several web services providers. They are all invoked from a single Java client application. All the web services up until now have been over SSL, but none use client certificates. Well, a new partner is changing that.
Making the application use a certificate for the invocation is easy; setting javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword will do it. However, the problem is now how to make it so that it only uses the certificate when invoking that particular web service. I guess more generally speaking, we'd like to be able to choose the client certificate to be used, if any.
One quick solution could be setting the system properties, invoking the methods, and then unsetting them. The only problem with that is that we're dealing with a multi-threaded application, so now we would need to deal with synchronization or locks or what have you.
Each service client is supposed to be completely independent from each other, and they're individually packaged in separate JARs. Thus, one option that has occurred to me (although we haven't properly analyzed it) is to somehow isolate each JAR, maybe load each one under a different VM with different parameters. That's merely an idea that I don't know how to implement (or if it's even possible, for that matter.)
This post suggests that it is possible to select an individual certificate from a key store, but how to attach it to the request seems to be a different issue altogether.
We're using Java 1.5, Axis2, and client classes generated with either wsimport or wsdl2java.
The configuration is done via an SSLContext, which is effectively a factory for the SSLSocketFactory (or SSLEngine). By default, this will be configured from the javax.net.ssl.* properties. In addition, when a server requests a certificate, it sends a TLS/SSL CertificateRequest message that contains a list of CA's distinguished names that it's willing to accept. Although this list is strictly speaking only indicative (i.e. servers could accept certs from issuers not in the list or could refuse valid certs from CAs in the list), it usually works this way.
By default, the certificate chooser in the X509KeyManager configured within the SSLContext (again you normally don't have to worry about it), will pick one of the certificates that has been issued by one in the list (or can be chained to an issuer there).
That list is the issuers parameter in X509KeyManager.chooseClientAlias (the alias is the alias name for the cert you want to picked, as referred to within the keystore). If you have multiple candidates, you can also use the socket parameter, which will get you the peer's IP address if that helps making a choice.
If this helps, you may find using jSSLutils (and its wrapper) for the configuration of your SSLContext (these are mainly helper classes to build SSLContexts). (Note that this example is for choosing the server-side alias, but it can be adapted, the source code is available.)
Once you've done this, you should look for the documentation regarding the axis.socketSecureFactorysystem property in Axis (and SecureSocketFactory). If you look at the Axis source code, it shouldn't be too difficult to build a org.apache.axis.components.net.SunJSSESocketFactory that's initialized from the SSLContext of your choice (see this question).
Just realized you were talking about Axis2, where the SecureSocketFactory seems to have disappeared. You might be able to find a workaround using the default SSLContext, but this will affect your entire application (which isn't great). If you use a X509KeyManagerWrapper of jSSLutils, you might be able to use the default X509KeyManager and treat only certain hosts as an exception. (This is not an ideal situation, I'm not sure how to use a custom SSLContext/SSLSocketFactory in Axis 2.)
Alternatively, according to this Axis 2 document, it looks like Axis 2 uses Apache HTTP Client 3.x:
If you want to perform SSL client
authentication (2-way SSL), you may
use the Protocol.registerProtocol
feature of HttpClient. You can
overwrite the "https" protocol, or use
a different protocol for your SSL
client authentication communications
if you don't want to mess with regular
https. Find more information at
http://jakarta.apache.org/commons/httpclient/sslguide.html
In this case, the SslContextedSecureProtocolSocketFactory should help you configure an SSLContext.
Java SSL clients will only send a certificate if requested by the server. A server can send an optional hint about what certificates it will accept; this will help a client choose a single certificate if it has multiple.
Normally, a new SSLContext is created with a specific client certificate, and Socket instances are created from a factory obtained from that context. Unfortunately, Axis2 doesn't appear to support the use of an SSLContext or a custom SocketFactory. Its client certificate settings are global.
I initialized EasySSLProtocolSocketFactory and Protocol instances for different endpoints and register the protocol with unique key like this:
/**
* This method does the following:
* 1. Creates a new and unique protocol for each SSL URL that is secured by client certificate
* 2. Bind keyStore related information to this protocol
* 3. Registers it with HTTP Protocol object
* 4. Stores the local reference for this custom protocol for use during furture collect calls
*
* #throws Exception
*/
public void registerProtocolCertificate() throws Exception {
EasySSLProtocolSocketFactory easySSLPSFactory = new EasySSLProtocolSocketFactory();
easySSLPSFactory.setKeyMaterial(createKeyMaterial());
myProtocolPrefix = (HTTPS_PROTOCOL + uniqueCounter.incrementAndGet());
Protocol httpsProtocol = new Protocol(myProtocolPrefix,(ProtocolSocketFactory) easySSLPSFactory, port);
Protocol.registerProtocol(myProtocolPrefix, httpsProtocol);
log.trace("Protocol [ "+myProtocolPrefix+" ] registered for the first time");
}
/**
* Load keystore for CLIENT-CERT protected endpoints
*/
private KeyMaterial createKeyMaterial() throws GeneralSecurityException, Exception {
KeyMaterial km = null;
char[] password = keyStorePassphrase.toCharArray();
File f = new File(keyStoreLocation);
if (f.exists()) {
try {
km = new KeyMaterial(keyStoreLocation, password);
log.trace("Keystore location is: " + keyStoreLocation + "");
} catch (GeneralSecurityException gse) {
if (logErrors){
log.error("Exception occured while loading keystore from the following location: "+keyStoreLocation, gse);
throw gse;
}
}
} else {
log.error("Unable to load Keystore from the following location: " + keyStoreLocation );
throw new CollectorInitException("Unable to load Keystore from the following location: " + keyStoreLocation);
}
return km;
}
When I have to invoke the web service, I do this (which basically replace "https" in the URL with https1, or https2 or something else depending on the Protocol you initialized for that particular endpoint):
httpClient.getHostConfiguration().setHost(host, port,Protocol.getProtocol(myProtocolPrefix));
initializeHttpMethod(this.url.toString().replace(HTTPS_PROTOCOL, myProtocolPrefix));
It works like a charm!

Categories

Resources