Search code examples
c#x509certificate2rsacryptoserviceprovider

Constructing RSACryptoServiceProvider from X509Certificate2 without LDAP request being made


When the line to extract the public key is executed, an LDAP request is sent:

        this.certificate = new X509Certificate2(buffer);
        System.Security.Cryptography.X509Certificates.PublicKey key = this.certificate.PublicKey;

50 0.853745000 xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx LDAP 404 searchRequest(1) "" baseObject

...which I believe is authenticating the currently logged on user. I really need to avoid this call, as on a customer system this causes a long delay because of network configuration.

I'm assuming it's attempting to do some authentication around some kind of key store, but as in this case the certificate is all contained in the buffer provided, all I want is for the key to be used without this request being sent.

All I actually want is to create an RSACryptoServiceProvider from the private key in the certificate. I tried a few methods I've found on here involving GetPrivateKey, but struggled to get anything to work.

Thanks in advance!

EDIT Test program:

    static void Main( string[] args )
    {
        var certificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(@"E:\Temp\Cert.cer");
        System.Security.Cryptography.X509Certificates.PublicKey key = certificate.PublicKey;
    }

The certificate I tested with can be found here: Cert.cer

Yes, it's not the strongest signature or key, before I get comments!

Thanks again.

EDIT: I actually worked around this by using a suggestion to use BouncyCastle. I use this to parse the certificate:

X509CertificateParser parser = new X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate cert = parser.ReadCertificate(buffer);

I then extract the modulus and exponent and push them into a Microsoft RSAParameters:

RsaKeyParameters key = (RsaKeyParameters)cert.GetPublicKey();

// Construct a microsoft RSA crypto service provider using the public key in the certificate
RSAParameters param = new RSAParameters();
param.Exponent = key.Exponent.ToByteArrayUnsigned();
param.Modulus = key.Modulus.ToByteArrayUnsigned();

I can then construct the Microsoft RSACryptoServiceProvider from this:

using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider())
{
    provider.ImportParameters(param);
    byte[] rsaBlock = provider.Encrypt(preMasterSecret, false);
    this.Client.Writer.Write(rsaBlock);
}

Solution

  • I never got any other response, so here's the Bouncycastle implementation I used.

    X509CertificateParser parser = new X509CertificateParser();
    Org.BouncyCastle.X509.X509Certificate cert = parser.ReadCertificate(buffer);
    

    I then extract the modulus and exponent and push them into a Microsoft RSAParameters:

    RsaKeyParameters key = (RsaKeyParameters)cert.GetPublicKey();
    
    // Construct a microsoft RSA crypto service provider using the public key in the certificate
    RSAParameters param = new RSAParameters();
    param.Exponent = key.Exponent.ToByteArrayUnsigned();
    param.Modulus = key.Modulus.ToByteArrayUnsigned();
    

    I can then construct the Microsoft RSACryptoServiceProvider from this:

    using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider())
    {
        provider.ImportParameters(param);
        byte[] rsaBlock = provider.Encrypt(preMasterSecret, false);
        this.Client.Writer.Write(rsaBlock);
    }