I receive an XML document as a string parameter in my method. The XML document is:
<Document>
<ZipContainer> Zip_File_In_Base64 </ZipContainer>
<X509Certificate> Certificate_In_Base64 </X509Certificate>
</Document>
From this string I extract the ZIP file in base64 format and X509Certificate2 certificate in base64 format. The ZIP file contains:
file describing the contents of the ZIP file as XML (file
packageDescription.xml
);files with the contents of transmitted documents (for example,
*.doc
files);files with content of detached digital signature (
*.p7s
files - detached digital signature);
From the archive should be extracted signature that signed documents (detached digital signature may be more than one). Detached digital signature are stored in files with .p7s
extension. Each signature must be done to check its agreement with digital signature, with which the user is logged in to the portal.
The must consist of two steps:
See method
certificateValidator()
(see this method below): This is a of detached signature, contained in the.p7s
files with their corresponding files that are signed, these *. P7s-files.
For example: a pair of related files:ZayavUL_3594c921f545406d9b8734bbe28bf894.doc_1.p7s
and
ZayavUL_3594c921f545406d9b8734bbe28bf894.doc
.See method
certificateValidator()
: This verifies certificate from a file.p7s
with a certificate that is extracted from the XML document input string.
Questions
The method
signatureValidator
(see this method below) is not currently used detached signature of the files.p7s
. I did try, but without success. How do I properly verify the detached signature of.p7s
file for its corresponding file?In the method
certificateValidator
(see this method below) how do I verify the conformity of the certificate extracted from the.p7s
file, with a certificate extracted from input string in Base64 format?The line of code
foreach (X509Certificate2 x509 in signCms.Certificates) { }
---> Certificates Collection always is empty. Why?
Input parameters
Dictionary <string, byte[]> dictP7SFiles
(key - the name of the file *.p7s, value - array of bytes, representing *.p7s file)Dictionary <string, byte[]> dictNotP7SFiles
(key - the name of the file that is signed using detached signature from *.p7s file, value - array of bytes, representing file)X509Certificate2 userCertX509
- certificate object, extracted from the input xml-document (where it has the format Base64)
Code
Here below are testing implementation of verification steps (see above this 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;
}