0
votes

This is not a 100% c# or ASP.NET question, it's rather a mixture of security and programming. So I apologize ahead. I need to integrate file signing module to my ASP.NET web application. I also need to write a utility application that will verify the signature. I know how to both sign a file and verify it. Here's how I do signing:

       private byte[] SignFile(byte[] fileData){
        X509Certificate2 cert=GetCertificate();
        RSACryptoServiceProvider csp = cert.PrivateKey;

        SHA1Managed sha1 = new SHA1Managed();
        byte[] hash = sha1.ComputeHash(fileData);
        return csp.SignData(hash, CryptoConfig.MapNameToOID("SHA1"));
      }

So far so good. On the other hand, when verifying I will need the public key. So here's my question. Do I need to send the certificate with the signed file so that the other side can take the public key to verify the signature. If so, this brings another question to mind: Can't someone else take the private key from attached certificate to edit the file and sign it again? What is the proper way of doing this?

1

1 Answers

0
votes

To verify a signature that you create using a pub/private key pair, the other party needs your public key only. You should always protect your private key and never let it get out, or a malicious party can pretend to be you.

With X509Certificate2 you can use the GetPublicKeyString method to get the hex string and pass it to them in a text format. You may also simply use the Export and Import methods to exchange only the public key.

PGP works on exactly the same principle, but assumes that the public key is exchanged through a separate trusted channel (such as a physical meeting and exchange of USB stick) so that the recipient knows that the public key is real and not a fake. If you are using certificates from a CA then the CA signing chain will imply the public key trust for you to as good a degree as is practically possible.

Code sample for Export and Import:

var cspSig = (RSACryptoServiceProvider)cert.PrivateKey;
var sig = cspSig.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
var pubKeyBytes = cert.Export(X509ContentType.Cert);
// either send the client the bytes, or the cert file ...
File.WriteAllBytes("MyCert.cer", pubKeyBytes);

and on the client ...

var pubCert = new X509Certificate2();
pubCert.Import(pubKeyBytes);
var cspVer = (RSACryptoServiceProvider)pubCert.PublicKey.Key;
var isValid = cspVer.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), sig);
var hasPrivateKey = pubCert.HasPrivateKey; // will equal false if using .Export(X509ContentType.Cert)