2
votes

I'm getting a PKCS#7/CMS container from a service I'm using that includes a user certificate and a signature.

I am able to see the single certificate using SignedCms

var cert = GetCertFromServer();

SignedCms signedCms = new SignedCms();
signedCms.Decode(cert);

// The user certificate
X509Certificate2 userCert = signedCms.Certificates[0];  

But I need to add the intermediate and root certificate to that chain. SignedCms.Certificates seems to be immutable, so I can't add the certificates directly to the collection and I am not able to replace the certificates collection the following way

// root, inter and leaf certs are X509Certificate2 objects read from files
X509Certificate2[] certArr = new[] {rootCert, interCert, leafCert, userCert};

X509Certificate2Collection chain = new X509Certificate2Collection(certArr);

signedCms.Certificates = chain; // Error: No setter

Since SignedCms.Certificates has no setter. I haven't been able to find a way to create a new container from this one. I have also not had any luck finding info on how to do this in bouncy castle or any other library.

I need to have a container containing the certificate chain and a signature and write the bytes from that container to a PDF file I'm signing. Is there a way to add certificates to the chain in the container?

2
It was a decision by the service provider to give us the certificates and ask us to include them afterwards, to reduce the overhead (this is a mobile phone signing service we're creating). But I I'll have to speak to them and ask them to include the whole chain in the signing process at their side. Thank you for the answer.Axel Örn Sigurðsson
Looks like I've misled you - in some cases (in theory) it's possible to add certificates. But .NET provides limited APIs so it might be not possible at all with .NET classes. Our developers suggest that with our SecureBlackbox adding certificates is possible (though not in all cases).Eugene Mayevski 'Callback

2 Answers

1
votes

I know it's been several years since this question was asked, but I recently ran into the same question.

For anyone with the same issue, the X509Certificate2Collection class has an Export method.

X509Certificate2[] certArr = certificates.ToArray();
X509Certificate2Collection chain = new X509Certificate2Collection(certArr);
byte[] result = chain.Export(X509ContentType.Pkcs7);
0
votes

.NET Core 3.0 has added SignedCms.AddCertificate. You can't control the ordering (SignedCms.Encode() writes the data using the DER encoding rules, which dictates that this particular collection be sorted smallest first), but that's okay... X509Chain straightens it out.

SignedCms signedCms = new SignedCms();
signedCms.Decode(data);

signedCms.AddCertificate(leafCert);
signedCms.AddCertificate(interCert);
signedCms.AddCertificate(rootCert);

byte[] reencoded = signedCms.Encode();