I'm having real issues attempting to contact a secure rest URL. Basically I have little knowledge of certificates, and am wondering whether what I am doing with the certificate file(s) is correct.
I have 2 URL's effectively one for read and one for write.
I have 2 .pem files, one for each, that were provided with the URLs. The act of importing these into Certificate manager didn't change the outcome below).
I have also a .p12 file, which if I'm honest don't know where it fits in to all this... (I cannot import this into my Win7 cert magager as I do not have a password)
When running req.GetResponse() an exception occurs:
"The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."
Inner Ex: "The remote certificate is invalid according to the validation procedure."
I'm currently unsure as to whether things need a little tinkering or I'm simply way off.
code is basically...
if (!File.Exists(certificateLocation))
{
throw new Exception(string.Format("The specified certificate file does not exist: {0}", certificateLocation));
}
//Cert Challenge URL
Uri requestURI = new Uri(url);
//Create the Request Object
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requestURI);
//Set the Request Object parameters
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
req.AllowAutoRedirect = false;
//Create certificate from our file
X509Certificate cert = X509Certificate.CreateFromCertFile(certificateLocation);
req.ClientCertificates.Add(cert);
WebResponse response = req.GetResponse(); // *** Errors here
...
Edit: Currently I'm only attempting the "read" url - seemed logical.
After contacting the issuer for the password accompanying the .p12 certificate, and importing that into the "Trusted Root Certification Authorities section" of certification manager, the error has now changed to the following...
System.Net.WebException
"The underlying connection was closed: An unexpected error occurred on a receive."
Inner Ex:
"Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host."
-- re-posting comment as answer --
The password is required for this to work.
It is created at the same time as the .p12 file.
Related
I have used Titanium web proxy for a windows forms application and there, I intercept https traffic and update it. I have first used titanium root certificate and it worked fine.
when I was trying to use custom ssl certificate as below
proxyServer.CertificateManager.RootCertificate = new X509Certificate2("default.pfx",
"password",
X509KeyStorageFlags.MachineKeySet);
proxyServer.CertificateManager.TrustRootCertificate(true);
but I couldn't able to decrypt the https traffic and it says
"The underlying connection was closed: An unexpected error occurred on a send." innerException says "
Authentication failed because the remote party has closed the transport stream."
how to decrypt the https traffic using custom ssl certificate in titanium-web proxy.
Issue was fixed when I add custom certification name and issuer name to proxyserver constructor and didn't needed any of above code. just fixed the issue by below code and certificate needs to installed in the machine
ProxyServer proxyServer = new ProxyServer("certificate.pfx", "Issuer Name",true,true,true);
proxyServer.CertificateManager.PfxPassword = "Password";
I'm trying to communicate with an external website using mutual certificate authentication, but am receiving a "Could not establish secure channel for SSL/TLS with authority" exception. I've narrowed it down to the following snippet (sensitive things removed):
void Example()
{
string KeyIdentifier = "<MyKeyId>";
X509Store store = new X509Store("My", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindByThumbprint, KeyIdentifier, true);
X509Certificate2 certificate = certificates[0];
HttpWebRequest r = (HttpWebRequest)HttpWebRequest.Create("https://www.example.org");
r.ClientCertificates.Add( certificate);
r.Accept = "text/xml";
r.Method = WebRequestMethods.Http.Post;
string result = null;
using (HttpWebResponse resp = (HttpWebResponse)r.GetResponse())
{
StreamReader reader = new StreamReader(resp.GetResponseStream());
result = reader.ReadToEnd();
}
}
I've set up the certificates and such properly and this code finds them successfully, with certificate.HasPrivateKey=true, but fails. SoapUI happily connects with TLS. Chrome reports no certificate errors when I access the website. However, the above code always throws the exception. I've tried all 3 TLS versions with no success. Using ServicePointManager to skip server Cert validation makes no difference.
Strangely, if I specify SSL3
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
then the process completes successfully, but naturally I don't want to be using SSL3. The app is .Net 4.6 running on Server 2012.
After several months and more digging on and off I ended up trying to make the connection using SSLStream, getting a different exception, and finding this answer: A call to SSPI failed, see inner exception - The Local Security Authority cannot be contacted
which advises you to add the following registry key:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman] "ClientMinKeyBitLength"=dword:00000200
This switches the minimum key length for Diffie-Hellman to 512-bit. This minimum value was raised in a Windows Update to 1024-bit to attempt to mitigate logjam attacks, so take care in setting this value as it is system wide and may open up attack vectors against your system.
I'm struggling to connect to a REST web service that's working only over HTTPS / SSL from my .NET application.
I received the certificate and private key to use as two separate files - a certificate.pem file which contains the certificate, and the webservice.key file which contains the private key. Those are both text files with BASE64 encoded binary data contained in them.
The provider also sent me a PDF showing how to call that web service using CURL and those two files, and that works just fine:
curl.exe -k -v "https://(URL)" --cert certificate.pem --key webservice.key
I need to use the -k option since there seems to be a self-signed certificate somewhere in the hierarchy of certs. Without this option, the call fails.
In order to call this web service from a .NET application (a console app for now), I used OpenSSL (on Windows) to combine these two files into a *.pfx file using this command:
openssl pkcs12 -export -out webservice.pfx -in certificate.pem -inkey webservice.key
This seems to have worked, too - no errors were reported, the file was created and is about 3K in size and it's a totally binary file.
Now, I tried to call that web service from my .NET code something like this:
try
{
// use the SSL protocol (instead of TLS)
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
// ignore any certificate complaints
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; };
// create HTTP web request with proper content type
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.ContentType = "application/xml;charset=UTF8";
// grab the PFX as a X.509 certificate from disk
string certFileName = Path.Combine(certPath, "webservice.pfx");
// load the X.509 certificate and add to the web request
X509Certificate cert = new X509Certificate(certFileName, "(top-secret password)");
request.ClientCertificates.Add(cert);
request.PreAuthenticate = true;
// call the web service and get response
WebResponse response = request.GetResponse();
Stream responseStream = response.GetResponseStream();
}
catch (Exception exc)
{
// log and print out error
}
However, I can try whatever I like (fiddling around with various settings, on the ServicePointManager and the HttpWebRequest, but I just keep getting these errors:
WebException: The underlying connection was closed: An unexpected error occurred on a send.
IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
SocketException: An existing connection was forcibly closed by the remote host
and no response - even though communicating with the service with CURL has worked just fine.....
What am I missing?? I'm a bit puzzled and mystified by all those certificates, private keys, service point manager options and so on - just waaaaay too many knob and switches to turn, set or turn off - what are the RIGHT settings here??
Update:
If I use
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
then the error just simply is:
WebException: The request was aborted: Could not create SSL/TLS secure channel.
S O L U T I O N :
In the end, with looking at the output from curl and a lot of help from #Alexandru and #JurajMajer, I was able to get this to work with this code:
try
{
// use the TLS protocol
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
// create HTTP web request with proper content type
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.ContentType = "application/xml;charset=UTF8";
// grab the PFX as a X.509 certificate from disk
string certFileName = Path.Combine(certPath, "webservice.pfx");
// load the X.509 certificate and add to the web request
X509Certificate2 cert = new X509Certificate2(certFileName, "(top-secret password)");
request.ClientCertificates.Add(cert);
request.PreAuthenticate = true;
// call the web service and get response
WebResponse response = request.GetResponse();
Stream responseStream = response.GetResponseStream();
string xmlContents = new StreamReader(responseStream).ReadToEnd();
}
catch (Exception exc)
{
// log and print out error
}
You've used the X509Certificate(String, String) constructor with a PKCS#12 certificate, but that constructor only works for PKCS#7 certificates, as MSDN says it...
Initializes a new instance of the X509Certificate class using the name
of a PKCS7 signed file and a password to access the certificate.
PKCS#7 does not include the private (key) part of a certificate/private-key pair, which you will need. This means you will need to use your PKCS#12 certificate given the nature of your certificate.
You may want to try the X509Certificate2(String, String) constructor with your existing PKCS#12 certificate, as this constructor is used with PKCS#12 (PFX) files that contain the certificate's private key, as MSDN says...
This constructor creates a new X509Certificate2 object using a
certificate file name and a password needed to access the certificate.
It is used with PKCS12 (PFX) files that contain the certificate's
private key. Calling this constructor with the correct password
decrypts the private key and saves it to a key container.
Try to enable Network Tracing in App.config on the client - instructions here. That should create network.log with more debug info. In my test environment I have one pfx which works and one which doesn't.
network.log for working pfx:
SecureChannel#9343812 - We have user-provided certificates. The server has specified 34 issuer(s). Looking for certificates that match any of the issuers.
SecureChannel#9343812 - Left with 1 client certificates to choose from.
SecureChannel#9343812 - Trying to find a matching certificate in the certificate store.
SecureChannel#9343812 - Locating the private key for the certificate:
SecureChannel#9343812 - Certificate is of type X509Certificate2 and contains the private key.
network log for non-working pfx:
SecureChannel#26756241 - We have user-provided certificates. The server has specified 34 issuer(s). Looking for certificates that match any of the issuers.
SecureChannel#26756241 - Left with 0 client certificates to choose from.
So for me the problem is my non-working certificate was issued by CA not in list.
Interesting points (possible problems):
1.) Server sends the list of known issuers for client certificate.
2.) Client code is looking for certificate and private key in certificate store event though both are in pfx.
I am trying to post an XML file to an URL that was given to me:
https://54.xx.xx.xxx/mycompany/path
using (WebClient client = new WebClient())
{
client.UploadFile(url, filePath);
}
However, I get this error:
"The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."
When I open up the URL, it returns a page saying "Running" however, I see the lock with an X on it, with error: "The Identity of this website has not been verified".
Could this be the problem? I need some light please.
it seems that your site uses SSL certificate authenticity and for some reason, its application verifies authenticity and this does not allow the operation run due to "lack of security"
possibly its certificate expired?
I'm trying to call a JBoss service from a C# program and I'm getting an annoyingly vague error.
JbossService proxy = new JbossService();
proxy.Credentials = new NetworkCredential("ME", "thepwd");
proxy.Url = //https url snipped
proxy.CookieContainer = new CookieContainer();
proxy.PreAuthenticate = true;
Console.WriteLine("Calling service...");
queryResponse qr = proxy.query();
Console.WriteLine("Done.");
The exception and inner exception thrown are as follows:
exception : The underlying connection was closed: An unexpected error occurred on a send.
inner exception : Authentication failed because the remote party has closed the transport stream.
I'm not quite sure what this means, other than perhaps that JBoss likes me even less than I like it. I'm calling from the local machine so I don't think it's a networking issue. Has anyone seen this before?
This usually happens when your client cannot verify trust over https with the server (usually because the server certificate is self signed or if it is signed by a root authority not installed on your client machine.
Easy fix (although there are security consequences)....somewhere in your initialization code add the following:
System.Net.ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { return true;};
Basically this replaces the application wide handling of server certificate validation and causes your application to accept any certificate. If you want to get finer grained, you can examine the certificate and put some logic in the method.
This works for anything based on System.Net, so it should work for Web Services and any thing based on WebRequest.
I haven't used JBOSS. This is how I troubleshoot similar problems, when using Microsoft technologies -- the same issues may be affecting your program:
Firewall settings or network issue (try connecting manually, to rule this out)
Self-service certificate issues:
Check the following certificate values:
Ensure the server's certificate issuer has a valid, matching issuing trusted root Certificate Authority (CA), on the same machine
The server certificate subject name matches the machine name exactly
The machine name the client is accessing matches that defined in the server certificate
An administrator account set (server) certificate thumbprint
Try recreating the SSL Certificate on both servers)
Try creating your own CA cert, add to trusted publishers, and then create an SSL sert based on that