0 votes

Hi,

We have a certificate distributed by a local government agency that is not publicly trusted -- i.e. we need to install a Root CA and Intermediate CA in order for their certificate to be considered valid.

This is fine, except when it comes to signing and encrypting. If we're to use a cloud service (say Azure Functions) that doesn't allow us to manipulate the local certificate store, we can't sign with an effectively "self-signed" certificate.

I've tried changing the Sign IncludeWith options to just use the EndCert, but as it's not trusted, Mail.dll won't have a bar of it. My understanding is that's a limitation of the X509Certificates signing provided by .NET and Microsoft?

Is there any alternatives to either forcing the sign?
Or, using an alternate signing library such as BouncyCastle?
Or, a way to load the Root CA into the signing Cert chain to make it trusted?

2021-07-03 23:58:31.133 +10:00 [INF] Starting up...
2021-07-03 23:58:31.140 +10:00 [INF] Loading Certificates
2021-07-03 23:58:31.486 +10:00 [INF] Loaded encryption cert: 538B8AEFFD522A3E96A10AFA1D6C68AEDB989019
2021-07-03 23:58:31.625 +10:00 [INF] Loaded signing cert: 7A1A5EBD3D804BC082D8B6D999244FB2945E05C7
2021-07-03 23:58:31.630 +10:00 [INF] - Signing 
2021-07-03 23:58:31.634 +10:00 [INF] - Encrypting
2021-07-03 23:58:31.652 +10:00 [ERR] Unable to process email
 System.Security.Cryptography.CryptographicException: A certificate chain could not be built to a trusted root authority.

   at System.Security.Cryptography.Pkcs.PkcsUtils.CreateBagOfCertificates(CmsSigner signer)
   at System.Security.Cryptography.Pkcs.SignedCms.Sign(CmsSigner signer, Boolean silent)
   at System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(CmsSigner signer, Boolean silent)
   at Limilabs.Mail.MIME.MimeSigned.__0_(Byte[] _0, CmsSigner __)
   at Limilabs.Mail.MIME.MimeSigned.__00(Byte[] _0, SignatureConfiguration __)
   at Limilabs.Mail.MIME.MimeSigned.___(SignatureConfiguration _0)
   at Limilabs.Mail.MailBuilder.____0()
   at Limilabs.Mail.MailBuilder.Create()
   at App.SignAndEncryptOutbox(IEnumerable`1 outbox, EncryptionCertificateData encryptionCertificateData) in App.cs:line 470

Regards,
Jake

by (200 points)
edited by
Are you getting any exception? What is the stack trace?

Please edit the question to include those details.

1 Answer

0 votes

There should be no problem with signing using self-signed certificates. Certificate validity is not checked during signing process. We use self-signed certificates in our unit tests for example.

When signing with a certificate signed by an untrusted root two approaches are possible:

Specify X509IncludeOption.EndCertOnly include option:

SignatureConfiguration config = new SignatureConfiguration(cert);
config.IncludeOption = X509IncludeOption.EndCertOnly;

builder.SignWith(config);

-or-

Add the CA certificate to trusted roots on the machine.

'A certificate chain could not be built to a trusted root authority' exception will be thrown otherwise.

Internally, .NET's PkcsUtils.CreateBagOfCertificates method creates a X509Chain instance and requires no X509ChainStatusFlags.PartialChain error returned from X509Chain.Build method. There is no way to supply additional certificates to the chain (MSDN documentation is incorrect about it using CmsSigner.Certificates).

by (272k points)
edited by
Hmm.. definitely was getting a certificate trust root error until the Root and CA certificate were installed.

Also having trouble decrypting attachments if AutoDecrypt is turned off following .Decrypt... Net48. Perhaps you'd want to see our example to see if there's an underlying issue?

This is latest version of NuGet mail.dll. Will dig up a stack trace.
Does your certificate include whole certificate chain to root?

Can you create a new certificate that includes your certificate (with private key) and all intermediate certificates, including your root cert?

[Edit]
I checked and this does not help. X509IncludeOption.EndCertOnly or a trusted CA is required.
...