I have a simple web service call, generated by a .NET (C#) 2.0 Windows app, via the web service proxy generated by Visual Studio, for a web service also written in C# (2.0). This has worked for several years, and continues to do so at the dozen or so places where it is running.
A new installation at a new site is running into a problem. When attempting to invoke the web service, it fails with the message saying:
Could not establish a trust relationship for the SSL/TLS secure
channel
The URL of the web service uses SSL (https://) -- but this has been working for a long time (and continues to do so) from many other locations.
Where do I look? Could this be a security issue between Windows and .NET that is unique to this install? If so, where do I set up trust relationships? I'm lost!
The following snippets will fix the case where there is something wrong with the SSL certificate on the server you are calling. For example, it may be self-signed or the host name between the certificate and the server may not match.
This is dangerous if you are calling a server outside of your direct control, since you can no longer be as sure that you are talking to the server you think you're connected to. However, if you are dealing with internal servers and getting a "correct" certificate is not practical, use the following to tell the web service to ignore the certificate problems and bravely soldier on.
The first two use lambda expressions, the third uses regular code. The first accepts any certificate. The last two at least check that the host name in the certificate is the one you expect.
... hope you find it helpful
//Trust all certificates
System.Net.ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);
// trust sender
System.Net.ServicePointManager.ServerCertificateValidationCallback
= ((sender, cert, chain, errors) => cert.Subject.Contains("YourServerName"));
// validate cert by calling a function
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);
// callback used to validate the certificate in an SSL conversation
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
bool result = cert.Subject.Contains("YourServerName");
return result;
}
The very simple "catch all" solution is this:
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
The solution from sebastian-castaldi is a bit more detailed.
Thoughts (based on pain in the past):
do you have DNS and line-of-sight to the server?
are you using the correct name from the certificate?
is the certificate still valid?
is a badly configured load balancer messing things up?
does the new server machine have the clock set correctly (i.e. so that the UTC time is correct [ignore local time, it is largely irrelevent]) - this certainly matters for WCF, so may impact regular SOAP?
is there a certificate trust chain issue? if you browse from the server to the soap service, can you get SSL?
related to the above - has the certificate been installed to the correct location? (you may need a copy in Trusted Root Certification Authorities)
is the server's machine-level proxy set correctly? (which different to the user's proxy); see proxycfg for XP / 2003 (not sure about Vista etc)
I personally like the following solution the most:
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
... then before you do request getting the error, do the following
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };
Found this after consulting Luke's Solution
If you do not wan't to blindly trust everybody and make a trust exception only for certain hosts the following solution is more appropriate.
public static class Ssl
{
private static readonly string[] TrustedHosts = new[] {
"host1.domain.com",
"host2.domain.com"
};
public static void EnableTrustedHosts()
{
ServicePointManager.ServerCertificateValidationCallback =
(sender, certificate, chain, errors) =>
{
if (errors == SslPolicyErrors.None)
{
return true;
}
var request = sender as HttpWebRequest;
if (request != null)
{
return TrustedHosts.Contains(request.RequestUri.Host);
}
return false;
};
}
}
Then just call Ssl.EnableTrustedHosts when your app starts.
If you are using Windows 2003, you can try this:
Open Microsoft Management Console
(Start --> Run --> mmc.exe);
Choose File --> Add/Remove Snap-in;
In the Standalone tab, choose Add;
Choose the Certificates snap-in, and
click Add;
In the wizard, choose the Computer
Account, and then choose Local
Computer. Press Finish to end the
wizard;
Close the Add/Remove Snap-in dialog;
Navigate to Certificates (Local
Computer) and choose a store to
import:
If you have the Root CA certificate
for the company that issued the
certificate, choose Trusted Root
Certification Authorities;
If you have the certificate for the
server itself, choose Other People
Right-click the store and choose All
Tasks --> Import
Follow the wizard and provide the
certificate file you have;
After that, simply restart IIS and try
calling the web service again.
Reference: http://www.outsystems.com/NetworkForums/ViewTopic.aspx?Topic=Web-Services:-Could-not-establish-trust-relationship-for-the-SSL/TLS-...
Luke wrote a pretty good article about this ..
pretty straight forward .. give this a try
Luke's Solution
Reason (quote from his article (minus cursing))
"..
The problem with the code above is that it doesn’t work if your certificate is not valid. Why would I be posting to a web page with and invalid SSL certificate? Because I’m cheap and I didn’t feel like paying Verisign or one of the other **-*s for a cert to my test box so I self signed it. When I sent the request I got a lovely exception thrown at me:
System.Net.WebException
The underlying connection was closed. Could not establish trust relationship with remote server.
I don’t know about you, but to me that exception looked like something that would be caused by a silly mistake in my code that was causing the POST to fail. So I kept searching, and tweaking and doing all kinds of weird things. Only after I googled the ***n thing I found out that the default behavior after encountering an invalid SSL cert is to throw this very exception.
.."
Microsoft's SSL Diagnostics Tool may be able to help identify the issue.
UPDATE the link has been fixed now.
add this:
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;}
right before the line that you're calling the service
I just encountered this issue. My resolution was to update the system time by manually syncing to the time servers. To do this you can:
Right-click the clock in the task bar
Select Adjust Date/Time
Select the Internet Time tab
Click Change Settings
Select Update Now
In my case this was syncing incorrectly so I had to click it several times before it updated correctly. If it continues to update incorrectly you can even try using a different time server from the server drop-down.
Try this:
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
Notice that you have to work at least with 4.5 .NET framework
I had a similar problem in .NET app in Internet Explorer.
I solved the problem adding the certificate (VeriSign Class 3 certificate in my case) to trusted editors certificates.
Go to Internet Options-> Content -> Publishers and import it
You can get the certificate if you export it from:
Internet Options-> Content -> Certificates -> Intermediate Certification Authorities -> VeriSign Class 3 Public Primary Certification Authority - G5
thanks
I had this error running against a webserver with url like:
a.b.domain.com
but there was no certificate for it, so I got a DNS called
a_b.domain.com
Just putting hint to this solution here since this came up top in google.
For those who are having this issue through a VS client side once successfully added a service reference and trying to execute the first call got this exception:
“The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel”
If you are using (like my case) an endpoint URL with the IP address and got this exception, then you should probably need to re-add the service reference doing this steps:
Open the endpoint URL on Internet Explorer.
Click on the certificate error (red icon in address bar)
Click on View certificates.
Grab the issued to: "name" and replace the IP address or whatever name we were using and getting the error for this "name".
Try again :).
Thanks
In my case I was trying to test SSL in my Visual Studio environment using IIS 7.
This is what I ended up doing to get it to work:
Under my site in the 'Bindings...' section on the right in IIS, I had to add the 'https' binding to port 443 and select "IIS Express Developement Certificate".
Under my site in the 'Advanced Settings...' section on the right I had to change the 'Enabled Protocols' from "http" to "https".
Under the 'SSL Settings' icon I selected 'Accept' for client certificates.
Then I had to recycle the app pool.
I also had to import the local host certificate into my personal store using mmc.exe.
My web.config file was already configured correctly, so after I got all the above sorted out, I was able to continue my testing.
My solution (VB.Net, the "staging" (UAT) version of this application needs to work with the "staging" certificate but not affect requests once they are on the live site):
...
Dim url As String = ConfigurationManager.AppSettings("APIURL") & "token"
If url.ToLower().Contains("staging") Then
System.Net.ServicePointManager.ServerCertificateValidationCallback = AddressOf AcceptAllCertifications
End If
...
Private Function AcceptAllCertifications(ByVal sender As Object, ByVal certification As System.Security.Cryptography.X509Certificates.X509Certificate, ByVal chain As System.Security.Cryptography.X509Certificates.X509Chain, ByVal sslPolicyErrors As System.Net.Security.SslPolicyErrors) As Boolean
Return True
End Function
A variation I've been using for a while it if helps anyone.
The caller has to explicitly request that untrusted certifications are required and places the callback back into it's default state upon completion.
/// <summary>
/// Helper method for returning the content of an external webpage
/// </summary>
/// <param name="url">URL to get</param>
/// <param name="allowUntrustedCertificates">Flags whether to trust untrusted or self-signed certificates</param>
/// <returns>HTML of the webpage</returns>
public static string HttpGet(string url, bool allowUntrustedCertificates = false) {
var oldCallback = ServicePointManager.ServerCertificateValidationCallback;
string webPage = "";
try {
WebRequest req = WebRequest.Create(url);
if (allowUntrustedCertificates) {
// so we can query self-signed certificates
ServicePointManager.ServerCertificateValidationCallback =
((sender, certification, chain, sslPolicyErrors) => true);
}
WebResponse resp = req.GetResponse();
using (StreamReader sr = new StreamReader(resp.GetResponseStream())) {
webPage = sr.ReadToEnd().Trim();
sr.Close();
}
return webPage;
}
catch {
// if the remote site fails to response (or we have no connection)
return null;
}
finally {
ServicePointManager.ServerCertificateValidationCallback = oldCallback;
}
}
If not work bad sertificate, when ServerCertificateValidationCallback return true;
My ServerCertificateValidationCallback code:
ServicePointManager.ServerCertificateValidationCallback += delegate
{
LogWriter.LogInfo("Проверка сертификата отключена, на уровне ServerCertificateValidationCallback");
return true;
};
My code which the prevented execute ServerCertificateValidationCallback:
if (!(ServicePointManager.CertificatePolicy is CertificateValidation))
{
CertificateValidation certValidate = new CertificateValidation();
certValidate.ValidatingError += new CertificateValidation.ValidateCertificateEventHandler(this.OnValidateCertificateError);
ServicePointManager.CertificatePolicy = certValidate;
}
OnValidateCertificateError function:
private void OnValidateCertificateError(object sender, CertificateValidationEventArgs e)
{
string msg = string.Format(Strings.OnValidateCertificateError, e.Request.RequestUri, e.Certificate.GetName(), e.Problem, new Win32Exception(e.Problem).Message);
LogWriter.LogError(msg);
//Message.ShowError(msg);
}
I disabled CertificateValidation code and ServerCertificateValidationCallback running very well
Related
I am attempting to create a gRPC server and client using ssl (with .NET 5 and VS2019).
I want to use a generated X509Certificate2 as a root certificate to generate other client certificates. For that, I wrote a helper class CertificateUtil, following these threads:
How can I create a self-signed certificate using C#?
Generate and Sign Certificate Request using pure .net Framework.
Next, the root certificate should be registered as a custom trust store in the startup settings of the gRPC server, and the client should connect using the generated client certificate.
I have the following question:
Is it possible to register a custom trust store in gRPC?
If not, what is a good alternative?
If yes, what part of the process I explain below is incorrect?
Currently, I am getting the following errors:
client: "Error starting gRPC call. HttpRequestException: The SSL connection could not be established, see inner exception. IOException: Received an unexpected EOF or 0 bytes from the transport stream."
server: "The local security authority (LSA) is unreachable"
Steps to reproduce:
Pull the following MWE: https://github.com/Renopph/GrpcServerClient
Uncomment lines 10 and 11 in GprcCert/Program.cs and run. This should create two certificate files, GrpcServer.pfx and GrpcClient.pfx. Set both files' properties to Copy always. Do NOT register these certificates in your system's trust store.
Place GrpcClient.pfx in the root of the GrpcClient project.
Comment out lines 10 and 11, and uncomment line 12 in GprcCert/Program.cs.
Right click the Solution, open Properties. Select "Multiple startup projects" and set both GrpcCertand GrpcClient to "Start". Then run the solution (should run GrpcCert first, then GrpcClient).
The client and server both show the aforementioned errors.
I also tried leaving out the KestrelServerOptions in the Startup.cs of the server. This allowed any client to connect, even without the certificate.
I will write up this answer, but as I already said I think it only answers half your questions. Regarding your question Is it possible to register a custom trust store in gRPC? I think the answer is yes, as long as you fulfill the TLS requirements of gRPC and the underlying certificate structure works, it should be possible. According to the MS Documentation for certificate authentication, the certificate authentication happens at the TLS level, long before it ever gets to ASP.NET Core, therefore the Kestrel (which hosts the gRPC services) does not care if the (root) certificate comes from a custom trust store or the local machine store (or somewhere else).
It took me a while to get both my self-signed certs in the local machine store and my company's certs in the Trusted Root Certification Authorities Certificate Store to work with gRPC, therefore it's maybe easier to get your certificates first to a point where they just work with the root cert getting fetched from the local machine store, and then move it to a custom store.
This is the service I used to inject the certs on the client- and serverside (in .NET 6), I think you could extend it easily to fetch a cert from any other location (like a custom certificate store):
using System.Security.Cryptography.X509Certificates;
namespace Shared.Certificates
{
public class CertificateService : ICertificateService
{
public X509Certificate2 GetCertificateFromLocalMachineStore(string friendlyName)
{
var store = GetLocalMachineCertificates();
X509Certificate2 certificate = null;
foreach (var cert in store.Cast<X509Certificate2>().Where(cert => cert.FriendlyName.Equals(friendlyName)))
{
certificate = cert;
}
return certificate;
}
private static X509Certificate2Collection GetLocalMachineCertificates()
{
var localMachineStore = new X509Store(StoreLocation.LocalMachine);
localMachineStore.Open(OpenFlags.ReadOnly);
var certificates = localMachineStore.Certificates;
localMachineStore.Close();
return certificates;
}
}
}
And the interface for the service, which you could extend for a method like public X509Certificate2 GetCertificateFromCustomTrustStore(string friendlyName), where you could fetch your cert from wherever you want to store them:
using System.Security.Cryptography.X509Certificates;
namespace Shared.Certificates
{
public interface ICertificateService
{
X509Certificate2 GetCertificateFromLocalMachineStore(string friendlyName);
}
}
Server-side certificate injection with the service from above:
CertificateService service = new CertificateService();
X509Certificate2 cert = service.GetCertificateFromLocalMachineStore("grpc_cert");
builder.WebHost.ConfigureKestrel(opt =>
{
opt.ConfigureHttpsDefaults(h =>
{
h.ClientCertificateMode = Microsoft.AspNetCore.Server.Kestrel.Https.ClientCertificateMode.AllowCertificate;
h.CheckCertificateRevocation = false;
h.ServerCertificate = cert;
});
}
And client-side certificate injection with the service from above:
CertificateService service = new CertificateService();
X509Certificate2 cert = service.GetCertificateFromLocalMachineStore("grpc_cert");
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(cert);
Channel = GrpcChannel.ForAddress($"https://{address}:{port}", new GrpcChannelOptions
{
HttpHandler = handler
});
If you want to, I can also provide you with the script that I used to generate my self-signed certificates, but I don't think they are of much use to you, since you have different certificates. Sadly I cannot help you more, I think your main problem is somewhere in your certificate structure, and I don't know too much about certs ...
each time when I run unit tests by NUnit(2.6.4) that use titanium-web-proxy(3.0.398-beta) appears security warning about installing the certificate, but if I start titanium-web-proxy like the standalone app it asks only at first time and then starts without the security warning. The code of launching proxy at both projects the same:
private readonly ProxyServer _proxyServer = new ProxyServer();
public void ProxyStart()
{
var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000);
_proxyServer.AddEndPoint(explicitEndPoint);
_proxyServer.Start();
_proxyServer.SetAsSystemProxy(explicitEndPoint , ProxyProtocolType.AllHttp);
}
Previously I had this issue in our Production environment. I searched deeply and got this solution. This may be worth-able to solution to try
Kindly check the certificate file"rootCert.pfx" in the base folder.(This is the reason)
This certificate file has to be in the base location of where application running. Other wise Titanium Create a new certificate for each and every time.
If the certificate has same serial number then "You will not get any Security Message Warning"
the runtime will then look into the Trusted Root Certification Authority store and see if the certificate for the issuer of the publisher's certificate is installed in that store. It will then look at who the publisher on the certificate is, and see if their certificate is in the Trusted Publishers store. If those two things are true, then by default the user will not be prompted,
Note :
Titanium Proxy first check if the file exist otherwise it will
generate a new one. If I was correct the file name was
"rootCert.pfx".
Before you start the application go to the base folder and check the
certificate file was there.
I don't have any idea how NUnit works
Thanks for the help, you are prompted me to solve this issue.
Problem was that Titanium-web-proxy (3.0.503) generate new cert each time,
So I am just set root cert by manual and it helps.
Tests launching without the security warning.
ProxyServer.CertificateManager.RootCertificate = new X509Certificate2(path + "\\Resources\\rootCert.pfx");
I got one Digital certificate from NeutralUS CA. I have installed in my local system. I found the installed certificate under Personal Certificates in MMC and my application validated with this certificate. I just moved to my application to our production server and installed same certificate. here also i can see my certificate under personal certificates in MMC on windows server 2008 R2. But when I am trying to load certificate with serial number, it is showing the store certificates count is zero. Could you please tell me what would be the reason? Why it is not recognize from the Personal folder. i have only one certificate in in personal folder.
var clientCertStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
clientCertStore.Open(OpenFlags.OpenExistingOnly & OpenFlags.ReadOnly);
base.Data.ErrorLog.Append("Certificates Count : " + clientCertStore.Certificates.Count);
I just log the data into one text file... it is giving clientCertStore.Certificates.Count as 0.
I got one Digital certificate from NeutralUS CA. I have installed in my local system.
What is installed? Is the end entity cert installed and trusted? Or is it the NeutralUS CA?
I could not find the NeutralUS CA for download on the net. That's unusual.
Could you please tell me what would be the reason? Why it is not recognize from the Personal folder.
I suspect its a problem with accounts (but its just a guess). What account was the certificate installed under, and what account is the program running under?
I really despise how difficult Java and .Net make it to use a damn certificate. Here's the code I use to avoid wasting time with those damn stores. It allows you to load directly from the filesystem or an app bundle. It also does not use the hundreds of CAs and subordinates that Windows carries around.
static bool VerifyServerCertificate(object sender, X509Certificate certificate,
X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
try
{
String CA_FILE = "ca-cert.der";
X509Certificate2 ca = new X509Certificate2();
ca.Import(CA_FILE);
X509Chain chain2 = new X509Chain();
chain2.ChainPolicy.ExtraStore.Add(ca);
// Check all properties
chain2.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
// This setup does not have revocation information
chain2.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
// Are there any failures from building the chain?
chain2.Build(new X509Certificate2(certificate));
if (chain2.ChainStatus.Length == 0)
return true;
// Verify the status is NoError
bool result = chain2.ChainStatus[0].Status == X509ChainStatusFlags.NoError;
Debug.Assert(result == true);
return result;
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return false;
}
And I still have not figured out how to set the original X509Chain chain that comes in as a parameter to the X509Chain chain2 that I want to use before the callback VerifyServerCertificate is invoked.
I have a black box service I have to call into with simple rest commands that returns xml.
They issued us a certificate that had to be run in IE and installs in to IE's Certificate section. As per their instructions I exported it with the entire chain as a pfx with password.
On the machine that the cert was issued directly to, everything works fine in code
var certHandler = new WebRequestHandler();
certHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
certHandler.UseDefaultCredentials = false;
var certificate = new X509Certificate2(Properties.Resources.SigningCert, "password", X509KeyStorageFlags.DefaultKeySet | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet); //Must be renewed and replaced every year.
certHandler.ClientCertificates.Add(certificate);
//Execute the command
var client = new HttpClient(certHandler);
string result;
try
{
result = await client.GetStringAsync(url);
System.Diagnostics.Debug.WriteLine(result);
}
catch (Exception ex)
{
throw ex;
}
(I've stored the cert in the resources, but it loads fine and loading it from a file works fine too in developer machine.) I also imported it into IE on the server just in case. Obviously this is likely under the wrong cert store, but I couldn't figure out how to load this in globally. I can tell you that the same REST GETs work in IE on the server just like they do on the developer machine. It's only in code that it fails.)
In production, this same code throws a 403 forbidden.
Production (really a beta server) is actually behind the same nat as the as the development machine so they're seeing the same IP come through etc.
Any ideas why it would fail on the server and not on the developer box?
Thanks!
You should use X509KeyStorageFlags according to account under which your app is running. If it is
1) An app that runs under regular Windows User Account you should use
X509Certificate2(Properties.Resources.SigningCert, "password", X509KeyStorageFlags.UserKeySet);
2) Windows Service under LocalSystem, IIS under NetworkService or other services under built in Windows Account, you should use
X509Certificate2(Properties.Resources.SigningCert, "password", X509KeyStorageFlags.MachineKeySet);
Basically, you shouldn't use X509KeyStorageFlags.PersistKeySet in your case - you import certificate from pfx format every time.
Certificate's private key is storing in the container according to flags. So you may have no access to it if you use wrong flags.
DefaultKeySet is not just alias for UserKeySet (msdn) - so choose appropriate flags in every case.
These articles also may be helpfull:
Key Storage and Retrieval
Eight tips for working with X.509 certificates in .NET
How Certificates Work
What I've found is that for whatever reason it won't allow you to grant permissions properly to the key. To work around it, I went to:
X:\Users\All Users\Microsoft\Crypto\RSA\MachineKeys
In explorer and found the key in question (I used deduction by Date but the thumbprint is there so you should be able to match it up.) and then right clicked, took over the file permissions and then set the permissions manually.
Then my code just started working.
Interestingly however, on another machine that I needed to deploy this to, the file doesn't exist in the machinekeys directory so I don't know what I'm going to do there but...
If I use HttpsURLConnection in a Java program and try to open an URL starting with https:// I'll get an error message:
unable to find valid certification path to requested target
and the solution I found is to add the server certificate to the client certificate storage. But if I write a C# program that uses HttpWebRequest then I don't have to add anything anywhere.
So for me it looks like a C# client "just works" and a Java client only works after being tweaked with a hammer.
Why is an extra step required for a Java client? Can I somehow skip saving the certificate to the client storage of JVM?
HttpWebRequest will use Window's own certificate store to validate certificates, i.e. the same as IE. If your IE can validate the certificate correctly, either by having the certificate or a CA path back to a trusted root, then HttpWebRequest should accept the certificate OK.
In the Java case I suspect adding the server certificate itself is wrong, unless it's self-signed in which case you'll have no choice. You should add the CA path back to a trusted root instead - you can probably pull these certificates out of Windows's CA store or download them from the root CA's website if you need them.
I believe it is because C# uses the same HTTP client as MSIE, so it has a lot of pre-installed SSL certificates including one that your use. JVM has less certificates pre-installed.
By default, Java uses its own set of trust anchors (in the default truststore, see the JSSE Reference Guide).
If you want to use the Windows certificate store, you can use the Windows-ROOT keystore as a trust store.
A good source of information on this topic is the Leveraging Security in the Native Platform Using Java SE 6 Technology and Java Secure Socket Extension (JSSE) Reference Guide on the Oracle site.
If you want Java to use the Windows certificate store to validate certificates then you can specify the the following system properties on launch:
-Djavax.net.ssl.keyStoreType=Windows-MY -Djavax.net.ssl.trustStoreType=Windows-ROOT
If you want only one connection to use the Windows certificate store to validate certificates you can modify the following code to fit your needs:
KeyStore ks = KeyStore.getInstance("Windows-MY");
ks.load(null, null);
KeyStore ts = KeyStore.getInstance("Windows-ROOT");
ts.load(null, null);
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ts);
KeyManagerFactory kmf = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, new char[0]);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
URL url = new URL("https://some.web.site.org");
javax.net.ssl.HttpsURLConnection urlConnection =
(javax.net.ssl.HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(ctx.getSocketFactory());
urlConnection.connect();
try (InputStream in = urlConnection.getInputStream();) {
byte[] chunk = new byte[1024];
for (int len; (len = in.read(chunk)) > -1;) {
System.out.write(chunk, 0, len);
}
} finally {
urlConnection.disconnect();
}