I am trying to verify a detached pkcs7 CMS signature with System.Security.Cryptography or the bouncycastle library and still cannot get it to work after hours and hours of testing.
My problem is that I only receive a hash of the original data to sign along with the detached cms signature of that hash from a external source and I need to verify the signature.
I got the following code to work and verify the signature, when instead of hashedData I input the original data. However I do not have access to that and only receive the hash of that data.
I suppose it is not working because the CheckSignature method hashes the hashedData internally again before validating the signature and I need a way to suppress that behavior.
Is there any way to validate the signature without having the original data?
byte[] originalData = Encoding.UTF8.GetBytes("Test");
byte[] hashedData = new SHA512Managed().ComputeHash(data); // hashedData is what I receive along with the signature
var content = new System.Security.Cryptography.Pkcs.ContentInfo(originalData); // working, but I dont have original data
var content = new System.Security.Cryptography.Pkcs.ContentInfo(hashedData); // not working
var cms = new System.Security.Cryptography.Pkcs.SignedCms(content, true);
cms.Decode(signature);
cms.CheckSignature(true);
I also tried to specify that the data is already hashed in the ContentInfo constructor, but that didn't work either.
If this is not possible in .NET, I am also welcoming a solution with BouncyCastle. See below for my current code in bouncycastle, which also only works with the original data, but not its hash:
var certificate = DotNetUtilities.FromX509Certificate(workerCert);
var processable = new CmsProcessableByteArray(hashedData);
var cms = new CmsSignedData(processable, signature);
var signers = cms.GetSignerInfos();
var signersCollection = signers.GetSigners();
foreach (var signer in signersCollection.Cast<SignerInformation>())
{
if (signer.Verify(certificate.GetPublicKey()))
{
Console.WriteLine("Working");
}
}
With BouncyCastle this is possible using:
In the absence of a documentation for C#/BouncyCastle, here is the link to the documentation of the Java/BouncyCastle counterpart.
Below is a sample implementation based on the code you posted: