Using a self-signed certificate with .NET's HttpWebRequest/Response
@Domster: that works, but you might want to enforce a bit of security by checking if the certificate hash matches what you expect. So an expanded version looks a bit like this (based on some live code we're using):
static readonly byte[] apiCertHash = { 0xZZ, 0xYY, ....};
/// <summary>
/// Somewhere in your application's startup/init sequence...
/// </summary>
void InitPhase()
{
// Override automatic validation of SSL server certificates.
ServicePointManager.ServerCertificateValidationCallback =
ValidateServerCertficate;
}
/// <summary>
/// Validates the SSL server certificate.
/// </summary>
/// <param name="sender">An object that contains state information for this
/// validation.</param>
/// <param name="cert">The certificate used to authenticate the remote party.</param>
/// <param name="chain">The chain of certificate authorities associated with the
/// remote certificate.</param>
/// <param name="sslPolicyErrors">One or more errors associated with the remote
/// certificate.</param>
/// <returns>Returns a boolean value that determines whether the specified
/// certificate is accepted for authentication; true to accept or false to
/// reject.</returns>
private static bool ValidateServerCertficate(
object sender,
X509Certificate cert,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
{
// Good certificate.
return true;
}
log.DebugFormat("SSL certificate error: {0}", sslPolicyErrors);
bool certMatch = false; // Assume failure
byte[] certHash = cert.GetCertHash();
if (certHash.Length == apiCertHash.Length)
{
certMatch = true; // Now assume success.
for (int idx = 0; idx < certHash.Length; idx++)
{
if (certHash[idx] != apiCertHash[idx])
{
certMatch = false; // No match
break;
}
}
}
// Return true => allow unauthenticated server,
// false => disallow unauthenticated server.
return certMatch;
}
HttpWebRequest: Could not establish Trust Relationship for SSL - Self Signed Certificate already added to Trusted Root CA
I resolved this issue by changing the URL of the site I was trying to access the web service on.
By choosing a URL with the computer name (rather than local host), it accepted the certificate.
How do I use SSL certificates with HttpWebRequest in C#?
(Edit from our comments below)
I suppose what you need to do is create a custom class and store the data you need in it inside the delegate code, rather than pass around the actual certificate reference.
Trusting Self-Signed Certificate using HttpClient
SelfSigned CA has to be in LocalMachine\Root store on server and on any client connecting to the server.
SSL certificate should have exact DNS name that clients will use to connect to it. It can have several DNS names specified in the certificate in Subject alternative name (SAN) extension. In your case you are using IP address so either
- you place the IP address in SAN or
- you put the IP address in hosts file with DNS name you specified when issuing SSL certificate and use this DNS name in HttpClient
You might consider using XCA to issue your certificates. It has nice GUI and is built on top of OpenSSL. It has predefined templates for CA and SSL server. More info in documentation here.
Related Topics
Get the Ip Address of the Remote Host
Large Object Heap Fragmentation
Why Firefox Requires Geckodriver
Token Based Authentication in ASP.NET Core
Nullable Type as a Generic Parameter Possible
Catching "Maximum Request Length Exceeded"
Ide's for C# Development on Linux
How to Unserialize PHP Serialized Array/Variable/Class and Return Suitable Object in C#
How Do Prefix (++X) and Postfix (X++) Operations Work
Marshal C++ Struct Array into C#
Running Scripts in HTMLagilitypack
How Does the Ternary Operator Work
Asp.Net: Invalid Postback or Callback Argument
Parsing HTML Page with HTMLagilitypack