I'm signing a PDF document with a mobile signing service. I recieve a certificate from the service after it has signed the hash of the document. I am able to replace zero padded signature container in the document with the certificate without any problems, but I"m having problems with including a certificate chain.
I have the root, intermediate and leaf certificates with the application, but I'm not able to include them in the signature. What I thought I would be able to do was to create a chain in code and then inject the encoded bytes from that chain, but this results in an invalid certificate.
The code I'm using to do that is as follows:
X509CertificateParser cp = new X509CertificateParser();
var certFromServer = getCertFromServer();
var rootCert = cp.ReadCertificate(new X509Certificate2(rootCertPath).RawData);
var interCert = cp.ReadCertificate(new X509Certificate2(interCertPath)RawData);
var leafCert = cp.ReadCertificate(new X509Certificate2(leafCertPath).RawData);
List<X509Certificate> intermediateCerts = new List<X509Certificate> {
interCert,
leafCert
};
X509CertificateParser parser = new X509CertificateParser();
PkixCertPathBuilder builder = new PkixCertPathBuilder();
X509CertStoreSelector holder = new X509CertStoreSelector {
Certificate = parser.ReadCertificate(certFromServer)
};
intermediateCerts.Add(holder.Certificate);
HashSet rootCerts = new HashSet {new TrustAnchor(rootCert, null)};
PkixBuilderParameters builderParams = new PkixBuilderParameters(rootCerts, holder)
{
IsRevocationEnabled = false
};
X509CollectionStoreParameters intermediateStoreParameters =
new X509CollectionStoreParameters(intermediateCerts);
builderParams.AddStore(X509StoreFactory.Create(
"Certificate/Collection", intermediateStoreParameters)
);
PkixCertPathBuilderResult result = builder.Build(builderParams);
byte[] certChainBytes = result.CertPath.GetEncoded("PKCS7");
// ExternalSignatureContainer is a container that simply returns the cert bytes
// from its Sign method without changing them.
IExternalSignatureContainer container = new ExternalSignatureContainer(certChainBytes);
MakeSignature.SignDeferred(reader, _signatureFieldName, baos, container);
The method to create the chain is from the following StackOverflow question: Build certificate chain in BouncyCastle in C#
What is the correct way to build a certificate chain for the signature container in iTextSharp?