Verify the highlighted signature (* .p7s files) and X509Certificate2

I get an XML document as a string parameter in my method. XML document:

<Document>     <ZipContainer> Zip_File_In_Base64 </ZipContainer>     <X509Certificate> Certificate_In_Base64 </X509Certificate> </Document> 

From this line, I extract the base64 format ZIP file and the base64 format X509Certificate2 certificate. The zip file contains:

  • a file that describes the contents of the ZIP file as XML ( packageDescription.xml file);

  • files with the contents of the transmitted documents (for example, *.doc );

  • files with the contents of a separate digital signature ( *.p7s files - a separate digital signature);

A signature, signed documentation must be extracted from the archive (there can be more than one separate digital signature). A separate digital signature is stored in files with the extension .p7s . Each signature must be made in order to verify its agreement with the digital signature with which the user has logged into the portal.

It should consist of two steps:

  • See the certificateValidator() method (see this method below). This is a separate signature contained in .p7s files with their corresponding files that were signed, these *. P7S files.
    For example: a couple of related files: ZayavUL_3594c921f545406d9b8734bbe28bf894.doc_1.p7s and
    ZayavUL_3594c921f545406d9b8734bbe28bf894.doc .

  • See certificateValidator() method: validates a certificate from a .p7s file with a certificate that is extracted from the input line of an XML document.

Questions

  • The signatureValidator method (see this method below) does not currently use delayed signing of .p7s files. I tried, but to no avail. How to check the selected signature of the .p7s file for the corresponding file?

  • In the certificateValidator method (see this method below), how can I verify the certificate extracted from the .p7s file using the certificate extracted from the input string in Base64 format?

  • Line of code foreach (X509Certificate2 x509 in signCms.Certificates) { } ---> The certificate collection is always empty. Why?

Input parameters

  • Dictionary <string, byte[]> dictP7SFiles (key is the name of the file * .p7s, value is an array of bytes representing the file * .p7s)

  • Dictionary <string, byte[]> dictNotP7SFiles (key is the name of a file signed using the selected signature from the * .p7s file, value is an array of bytes representing the file)

  • X509Certificate2 userCertX509 - certificate object extracted from the input xml document (where it has the Base64 format)

code

The following is a verification of the implementation of the verification steps (see above 2 steps):

 private bool certificateValidator(Dictionary<string, byte[]> dictP7SFiles, Dictionary<string, byte[]> dictNotP7SFiles, X509Certificate2 userCertX509) { bool isValid = false; try { foreach (KeyValuePair<string, byte[]> pair in dictP7SFiles) { ContentInfo contentInfo = new ContentInfo(pair.Value); SignedCms signCms = new SignedCms(contentInfo, true); if (signCms.Certificates.Count != 0) { //Certificates Collection always is empty. Why? foreach (X509Certificate2 x509 in signCms.Certificates) { if ((x509.SerialNumber != userCertX509.SerialNumber) || (x509.Thumbprint != userCertX509.Thumbprint)) { isValid = false; return isValid; } } isValid = true; return isValid; } } } catch (Exception ex) { //here process exception code } return isValid; } private bool signatureValidator(Dictionary<string, byte[]> dictP7SFiles, Dictionary<string, byte[]> dictNotP7SFiles, X509Certificate2 userCertX509) { bool isValid = false; try { byte[] data = dictP7SFiles["ZayavUL_3594c921f545406d9b8734bbe28bf894.doc"]; byte[] publicKey; byte[] signature; object hasher = SHA1.Create(); // Our chosen hashing algorithm. // Generate a new key pair, then sign the data with it: using (var publicPrivate = new RSACryptoServiceProvider()) { signature = publicPrivate.SignData(data, hasher); publicKey = publicPrivate.ExportCspBlob(false); // get public key } // Create a fresh RSA using just the public key, then test the signature. using (var publicOnly = new RSACryptoServiceProvider()) { publicOnly.ImportCspBlob(publicKey); isValid = publicOnly.VerifyData(data, hasher, signature); // Return True //isValid = ByteArrayCompare(dictP7SStreams["ZayavUL_3594c921f545406d9b8734bbe28bf894.doc_1.p7s"], signature); byte[] p7sDetachedSignature = File.ReadAllBytes(@"D:\ZayavUL_3594c921f545406d9b8734bbe28bf894.doc_1.p7s"); isValid = ByteArrayCompare(p7sDetachedSignature, signature); } } catch (Exception) { //here process exception code } return isValid; } 
+4
source share
1 answer

The main thing that you do wrong is to restore the CMS and signature. You must parse the CMS message and then specify the external content during validation.

  • How to check the filtered signature of the .p7s file for the corresponding file?

Take a look at the following Java code on SO to learn how to verify signatures; C # should use the same architecture, so it should work similarly.

  1. In the certificateValidator method (see this method below), how do I check if the certificate extracted from the .p7s file matches the certificate extracted from the input string in Base64 format?

Decrypt the base certificate 64 and perform a chain check and certificate check. How much validation you want to perform (e.g. checking the effective date) is up to you.

  1. Foreach line of code (X509Certificate2 x509 in signCms.Certificates) {} ---> The certificate collection is always empty. Why?

You simply did not invest it in the construction of the new CMS structure.


You, of course, should not regenerate the signature. Usually, you will not have a private key during validation, and the algorithm may not match the one used in the CMS document. Moreover, even if that were the case, signature generation is not always deterministic (you can get different signature values).

0
source

All Articles