Imagine for a moment that we're using classic asymmetric encription with WCF (private/public key pairs). Obviously it's secure until private keys aren't stolen. We don't need any trust chains between keys, right? Client only needs to know its server's public key and vice versa.
A problem arises only if client doesn't know server's public key in advance and gets it on the first access. Here we have a risk that actual server is a "man-in-the-middle" instead of the real server. Here we need certificates. Client accesses a server, gets its certificate (which contains public key) and validates it.
For validation client needs to make sure that server's certificate was issued for this particular server. And here we need trust chains. Right?
If a client accessing a server via WCF with MessageSecurity.Mode=Certificate knowns in advance the server's certificate (its public key), can we say that the communication is secure even if the certificate is self-signed?
Usualy it's believed that using self-signed certifacate is not secure and should be always avoided in production.
But why? If client knows expected public key then gets a certificate, treats it as trusted (by matching its public key with the expected one) then it doesn't cancel the fact that the server must encypt payload with its private key. And the cypher can be decrypted successfuly with pulbic key if and only if the private key and the public key were created together.
Can you see any flaws in my reasoning?
If it's correct then can I be sure that using a custom X509CertifacateValidator and setting client proxy's ClientCredentials.ServiceCertificate.DefaultCertificate to some fixed (on the client) X509Certificate secure?
Custom X509CertifacateValidator is something like this:
public class CustomCertificateValidator : X509CertificateValidator
{
private readonly X509Certificate2 m_expectedCertificate;
public CustomCertificateValidatorBase(X509Certificate2 expectedCertificate)
{
m_expectedCertificate = expectedCertificate;
}
public override void Validate(X509Certificate2 certificate)
{
ArgumentValidator.EnsureArgumentNotNull(certificate, "certificate");
if (certificate.Thumbprint != m_expectedCertificate.Thumbprint)
throw new SecurityTokenValidationException("Certificated was not issued by trusted issuer");
}
}