I have a business requirement to check the digital signature on an Open Packaging Conventions Package (it's a Word document) prior to continuing to process the document. The package is signed by me prior to delivering it to the client, so my code needs to verify at runtime that the file came from me and also has not been altered. I have working code that does this properly:
public static bool VerifySignature(Package package)
{
bool verified = true;
PackageDigitalSignatureManager dsm = new PackageDigitalSignatureManager(package);
VerifyResult verifyResult = dsm.VerifySignatures(false);
verified &= verifyResult == VerifyResult.Success;
var signature = dsm.Signatures.Where(s => s.Signer.Subject.Equals("MyCompanyName")).FirstOrDefault();
verified &= !ReferenceEquals(signature, null) && signature.Signer.Issuer.Equals("NameOfCA");
return verified;
}
My question relates to what actually happens when PackageDigitalSignatureManager.VerifySignatures()
is called. I am concerned that during the certificate validation a CRL check, or some other call outside the network, will be made. I have some clients who run my application on machines with absolutely no internet access. If the code relies on internet access, it's basically a showstopper for me.
I want to know two things:
- Will my code lead to a CRL check or something else which could result in a call outside the network?
- If so, is there a way to prevent it, or perhaps a different way to validate the signature reliably using a different mechanism?
No: MS, in their infinite wisdom appears to have split the verification process into two parts, PackageDigitalSignatureManager.VerifySignatures and PackageDigitalSignatureManager.VerifyCertificate
From the MS docs, it looks like the VerifySignature method only checks the format of the signature and the hash, ensuring that the doc has not been changed since signed. The MS docs state in the Remarks section "This method verifies only the digital signatures; it does not verify the related X.509 certificates. The VerifyCertificate method can be used to verify the X.509 certificates."
Next, you (should) use the VerifyCertificate method to check the signing cert's revocation status at signing time. It includes the possible error code value "OfflineRevocation"
Summary: At this time, your code is not fully verifying the signature since you are not checking the signing cert's revocation status. Therefore your code is only doing local signature checks. Those checks are not, formally speaking, complete verification.
Don't verify the signing cert (what you're doing now).
Attempt to verify the signing cert, but give the user a nice message if the only issue is that the revocation status can't be checked because the system is not connected to the internet. Here is the message that Adobe reader gives in this exact same situation:
Train your users that they should expect the "Offline revocation" status only when the system is offline. Or better, your code could check its internet status and if it is offline then improve the verification message.