Get encrypted data from HTTPS request to use certificate manually C# - c#

I am trying for my project this:
I want to download the (root) certificate from given url (or from diff location in later stages)
i want then get data from given url and use certificate i download in step one to "decrypt them"
check response on given url if step 1 and 2 get me same results as just response from the server
Basically I am trying to create something that check that given certificates works on given url same as the one automatically given.
Preferably do all 3 steps in one request (so if given url has counter for access, whole procedure is just one access on website)
I can do quite nice step 1)
var client = new TcpClient(address.ToString(), 443);
var certValidation = new RemoteCertificateValidationCallback(delegate (object snd, X509Certificate certificate, X509Chain chainLocal, SslPolicyErrors sslPolicyErrors)
{
return true; //Accept every certificate, even if it's invalid
});
// Create an SSL stream and takeover client's stream
using (var sslStream = new SslStream(client.GetStream(), true, certValidation))
{
sslStream.AuthenticateAsClient(InputWWW.Text);
var serverCertificate = sslStream.RemoteCertificate;
cert = new X509Certificate2(serverCertificate);
}
But I am not able to find any tips hot to get that raw data locally.
So far I found only something like this, where I use certificate in request handler
WebRequestHandler handler = new WebRequestHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ServerCertificateValidationCallback = (a, b, c, d) => { return true; };
handler.ClientCertificates.Add(certificate);
which is usage of certificate.
I want something like this:
var binary/StringBlob = webRequest.getRawData(url,port);
var serverResponseManualy = applyCertificate/publicKey(binary/StringBlob, X509Certificate2 certificate );
checkBodyEquals(serverResponseManually, webRequest.GetResponse());
Do you know how to do it, or what should I search for?
Is it possible to do all this in one request to server or not?
Thanks

So i was able to get more info about https, after that i discover that the way i ask this question is not correct. Because certificate (asymmetric cryptography) is used only to create symmetric key, which is used for encryption/description. So encrypted message by private key cannot be obtained

Related

Equalivent for openssl s_client -connect <hostname>:<port> in C#

When I execute a openssl command to connect a particular server [myadda.tie.fire.glass.... dummy server name] , it gives me some output.
openssl s_client -connect myadda.tie.fire.glass:443
It gives me some output which contains information like
server certificate
issuer information
And another command which required the certificate from above command to provide me details info about the certificate.
openssl x509 -in <Certificate_FileName.crt> -text -nout
It gives me output as information about the certificate
issued for server
Validity
I want similar kind of output using some C# classes. I am not sure how to solve this query. Can anyone help me out?
Well below code help me to retrieve the required information.
X509Certificate2 cert = null;
var client = new TcpClient(host, 443);
var certValidation = new RemoteCertificateValidationCallback(delegate (object snd, X509Certificate certificate, X509Chain chainLocal, SslPolicyErrors sslPolicyErrors)
{
//Accept every certificate, even if it's invalid
return true;
});
// Create an SSL stream and takeover client's stream
using (var sslStream = new SslStream(client.GetStream(), true, certValidation))
{
sslStream.AuthenticateAsClient(host);
var serverCertificate = sslStream.RemoteCertificate;
cert = new X509Certificate2(serverCertificate);
//Convert Raw Data to Base64String
var certBytes = cert.Export(X509ContentType.Cert);
var certAsString = Convert.ToBase64String(certBytes, Base64FormattingOptions.None);
}
Here vertAsString gives me the certificate whereas cert gives me the other required information.

Loading X509Certificate2 certificate chain from store

I have a file (.p12) that contains 3 certificates (chained together) password-protected, that i have installed on my store.
I'm trying to load them to my code.
The way I load them from the file is like this:
var clientCert = new X509Certificate2(#"myfile.p12", "mypassword");
How can i achieve the same result while loading them from the store?
I've tried:
var computerCaStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
computerCaStore.Open(OpenFlags.ReadOnly);
var certificates = computerCaStore.Certificates.OfType<X509Certificate2>().ToLi‌​st();
var certFromStore = certificates.Single(c => c.Thumbprint == thumbprintMerchant);
var newCert = new X509Certificate2(certFromStore.RawData, "mypassword");
certFromStore should be equivalent to clientCert, the last line is what's breaking you.
The RawData property on X509Certificate2 returns the DER-encoded value for the certificate, not the original file bytes. A certificate does not have a private key, so the last line strips it away. Your question had previously mentioned a TLS exception, and that is because your cert no longer has a private key.
If certFromStore.HasPrivateKey is false, then whatever you did to put the certificate into the store didn't work the way you think it did. It's pretty unusual for a certificate with a private key to be in the Root store.

A WebException with status TrustFailure was thrown. AmazonS3 .net 3.5 Version 3 invoking from sharepoint 2010

Currently I am working in POC with CRUD operations using AmazonS3 Sdk for .net 3.5 version 3. I am trying to retrieve the Region Endpoint(Location) of the specific bucket name using secret key and Access Key and bucket name( has Location: EU (Frankfurt) (eu-central-1)). in order to establish connection
with AmazonS3 and perform CRUD operations
So I get the A WebException with status TrustFailure was thrown when I tried to get the Region Endpoint from share point(web page I create my own page using the master page of SharePoint) in order to create AmazonS3Client instance with Region Retrieve.
with the following code:
private string defaultAmazonHttpsHost = "https://s3.amazonaws.com";
private string defaultAmazonHttpHost = "http://s3.amazonaws.com";
private Amazon.RegionEndpoint GetRegionEndpoint(string bucket, BasicAWSCredentials amazonCredentials, bool useSSL)
{
Amazon.RegionEndpoint regiongEndpoint = null;
AmazonS3Config configurationClient = new AmazonS3Config();
configurationClient.UseHttp = !useSSL;
configurationClient.ServiceURL = useSSL ? defaultAmazonHttpsHost : defaultAmazonHttpHost;
try
{
using (AmazonS3Client clientConnection = new AmazonS3Client(amazonCredentials, configurationClient))
{
GetBucketLocationRequest locationRequest = new GetBucketLocationRequest();
locationRequest.BucketName = bucket;
string locationName = clientConnection.GetBucketLocation(locationRequest).Location.Value;
if (locationName.Equals("EU", StringComparison.InvariantCultureIgnoreCase))
{
regiongEndpoint = Amazon.RegionEndpoint.EUWest1;
}
else if (string.IsNullOrEmpty(locationName))
{
regiongEndpoint = Amazon.RegionEndpoint.USEast1;
}
else
{
regiongEndpoint = Amazon.RegionEndpoint.GetBySystemName(locationName);
}
}
}
catch (AmazonS3Exception amazonS3Exception)
{
throw amazonS3Exception;
}
catch (Exception unExpectedException)
{
throw unExpectedException;
}
return regiongEndpoint;
}
BasicAWSCredentials credentials = new BasicAWSCredentials("my access Key", "my secret key");
AmazonS3Config configurationAmazon = new AmazonS3Config();
configurationAmazon.RegionEndpoint = GetRegionEndpoint("bucketName", credentials, false);
AmazonS3Client _s3 = new AmazonS3Client(credentials, configurationAmazon );
My task Perform CRUD operations + test connection with AmazonS3 Sdk .net 3.5 version 3 , with the source information :
-secret key
- access key
- bucket Name
the strange is if this part code run(execute) since another Project (without share point interaction for example: Console Project) I do not get this exception) Do you know what is the problem?
I used the following before execute any request to amazonS3 and now it works as expected I think the problem was with the certificates that sharepoint is using .
ServicePointManager.ServerCertificateValidationCallback +=
delegate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
return true;
};
the post provide a explanation about it
The key point here is "TrustFailure". There's something wrong with the certificate. In my case, this error was caused because my company uses Websense, a web filter/security suite that intercepts and reissues https certificates for web traffic so it can spy on you. Even if you don't use anything like that, the bottom line is that your computer doesn't trust the issuer of the certificate being used by the remote computer. The server on which I was receiving this error did not have the correct certificate in its Trusted Root Certification Authorities. After importing the correct trusted root cert (Add trusted root certificate authority to local computer), I no longer received the error.
If you don't think this is the case, you can get more details on what the exception is by either writing the details to console or putting a breakpoint on the Console.WriteLine here and actually inspect the certificate and ssl errors:
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
.....
.....
//before you make the request
System.Net.ServicePointManager.ServerCertificateValidationCallback +=
delegate (
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
Console.WriteLine("Subject: " + certificate.Subject + ", Issuer: " + certificate.Issuer + ". SSL Errors: " + sslPolicyErrors.ToString());
return false;
};
The key point here is that you need to find the certificate issue and resolve it instead of leaving yourself vulnerable by ignoring all ssl errors.
TrustFailure can also be caused by the date being incorrect on the machine.

Can we send unsigned client certificates with HttpClient?

I have seen code samples of how to use WebRequestHandler with HttpClient to embed a certificate in my http request (see snippet below). However, I just tested this with a self-signed cert and it is not working. According to this post this method will not work without a trusted certificate.
I can see the certificate on the server if I send it through the browser or Postman, but not programmatically.
Can someone confirm or deny if HttpClient or WebRequestHandlerperform any kind of certificate validation before sending it as part of the request?
A quick de-compile did not show anything obvious, but there are many things in play along the request pipeline.
Sample code:
var cert = new X509Certificate2(rawCert);
//This call fails, cannot check revocation authority.
//Specific error: The revocation function was unable to check
//revocation for the certificate.
//X509CertificateValidator.ChainTrust.Validate(cert);
var certHandler = new WebRequestHandler()
{
ClientCertificateOptions = ClientCertificateOption.Manual,
UseDefaultCredentials = false
};
certHandler.ClientCertificates.Add(cert);
var Certificateclient = new HttpClient(certHandler)
{
BaseAddress = new Uri("https://web.local")
};
var response = await Certificateclient.GetAsync("somepath");
To use a self signed cert, you can add using System.Net.Security;
add a handler callback method
public static bool ValidateServerCertificate(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
and set before invoke the API:
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
See:
https://es.stackoverflow.com/a/153207/86150
https://social.msdn.microsoft.com/Forums/es-ES/130308da-4092-4f21-8355-ee3c77a22f97/llamar-web-service-con-certificado?forum=netfxwebes

Is it possible to determine if a HTTPS proxy is being used just by looking at the certificate?

Since HTTPS proxies will replace the SSL certificate with their own, what are my options to determine if a given HTTPS connection has a proxy in the middle?
I will use this information to determine my application policy, since there are cases where I want a 100% end-to-end encrypted tunnel with no decryption by any 3rd party.
Even better if you can tell me how to determine this via C# in a .NET application or Silverlight.
For starters, here is a sample method to validate a certificate using .NET, but I'm still not sure how to use this to determine what part of the cert to validate. In addition, I think the ServicePointManger is more of a "global" connection class. Using this may be too broad when I'm testing a single HTTP connection, and I'm not sure if ServicePointManager is available within Silverlight.
http://msdn.microsoft.com/en-us/library/bb408523.aspx
You have a couple of options. The first option is to use the ServicePointManager class. You are correct in that it manages all service points, but you can use the "sender" parameter in the callback method to differentiate between the different service points:
void SomeMethod()
{
ServicePointManager.ServerCertificateValidationCallback +=
ValidateServerCertificate;
var url = "https://mail.google.com/mail/?shva=1#inbox";
var request = (HttpWebRequest)WebRequest.Create(url);
request.GetResponse();
}
private static bool ValidateServerCertificate(object sender,
X509Certificate certificate, X509Chain chain,
SslPolicyErrors sslpolicyerrors)
{
if(sender is HttpWebRequest)
{
var request = (HttpWebRequest) sender;
if(request.RequestUri.ToString() == "https://mail.google.com/mail/?shva=1#inbox")
{
return (certificate.GetPublicKeyString() == "The public key string you expect");
}
}
return true;
}
This option will work for manually-created HttpWebRequest and WCF-created requests, as the "sender" will be HttpWebRequest for both. I'm not sure if the "sender" will be anything other than an HttpWebRequest.
The second option is to get the certificate from the service point directly:
void SomeMethod()
{
ServicePointManager.ServerCertificateValidationCallback +=
ValidateServerCertificate;
var url = "https://mail.google.com/mail/?shva=1#inbox";
var request = (HttpWebRequest)WebRequest.Create(url);
request.GetResponse();
var serverCert = request.ServicePoint.Certificate;
// Validate the certificate.
}
I couldn't figure out if it's possible to get the ServicePoint used by a WCF proxy. If it's not possible, this option won't work for WCF. Other than that, the biggest difference is that the first option prevents the connection if the certificate validation fails, while the second method won't validate until after the connection has been made.
If you just need to determine if a request is going to pass through a proxy:
var httpRequest = (HttpWebRequest)WebRequest.Create("someurl");
var isUsingProxy = DoesRequstUseProxy(request);
bool DoesRequestUseProxy(HttpWebRequest request)
{
if(request.Proxy == null)
{
return false;
}
return request.Proxy.GetProxy(request.RequestUri) != request.RequestUri;
}

Categories

Resources