Search code examples
c#certificatedigital-signaturex509certificate2x509chain

Why does the X509Chain.build() method return true if the signature is invalid on the dll?


I want to verify the signature on a dll using the X509Chain class. I tried this so far:

X509Certificate2 intermediateCertificate = new X509Certificate2();
X509Certificate2 rootCertificate = new X509Certificate2();
intermediateCertificate.Import(intermediateCert);
rootCertificate.Import(rootCert);

X509Chain certificateChain = new X509Chain();
certificateChain.ChainPolicy.ExtraStore.Add(intermediateCertificate);
certificateChain.ChainPolicy.ExtraStore.Add(rootCertificate);
certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
certificateChain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
certificateChain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;

X509Certificate2 dllCert= new X509Certificate2("path/To/The/Dll");
bool isCertChainValid = certificateChain.Build(dllCert);

I am working on a solution that works on machines that are not connected to the internet, so I add the certificates to the extra store and I set the revocation mode to noCheck. My most important question is why does the build() method return true when the signature on the dll is invalid (I invalidated it using a hex editor and overwrote some bytes in the file)


Solution

  • Your code isn't trying to check the signature of the DLL, it's just asking if the certificate that claims to have signed the DLL is trusted.

    X509Certificate2 dllCert= new X509Certificate2("path/To/The/Dll"); only finds the Authenticode signature data element and extracts the certificate of the first signer (usually there's just one, but if there are more than one it's the first)... then completely forgets about the DLL.

    The .NET Base Class Libraries (BCL) layer doesn't expose a way to verify Authenticode signatures or application execution policies.

    Extra note:

    X509Certificate2 intermediateCertificate = new X509Certificate2();
    X509Certificate2 rootCertificate = new X509Certificate2();
    intermediateCertificate.Import(intermediateCert);
    rootCertificate.Import(rootCert);
    

    The Import methods no longer function in .NET Core / .NET 5+. You should just combine those lines into a constructor call:

    X509Certificate2 intermediateCertificate = new X509Certificate2(intermediateCert);
    X509Certificate2 rootCertificate = new X509Certificate2(rootCert);