openiddict-core: Signing certificate invalid on production in docker container

Confirm you’ve already contributed to this project or that you sponsor it

  • I confirm I’m a sponsor or a contributor

Version

3.x

Question

I’ve deployed my application using docker to a server, I’ve generated certificates using OpenSSL and passed them as a volume to my docker container.

When the application starts up I get an exception in the log saying:

root-nextlevel-auth-1  | warn: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver[12]
root-nextlevel-auth-1  |       Key {5698643d-b0a7-4c77-b4f7-03c93ed2d78f} is ineligible to be the default key because its CreateEncryptor method failed.
root-nextlevel-auth-1  |       System.Security.Cryptography.CryptographicException: Symmetric algorithm is not specified.
root-nextlevel-auth-1  |          at System.Security.Cryptography.Xml.EncryptedXml.GetDecryptionKey(EncryptedData , String )
root-nextlevel-auth-1  |          at System.Security.Cryptography.Xml.EncryptedXml.DecryptDocument()
root-nextlevel-auth-1  |          at Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor.Decrypt(XElement encryptedElement)
root-nextlevel-auth-1  |          at Microsoft.AspNetCore.DataProtection.XmlEncryption.XmlEncryptionExtensions.DecryptElement(XElement element, IActivator activator)
root-nextlevel-auth-1  |          at Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(XElement keyElement)
root-nextlevel-auth-1  |          at Microsoft.AspNetCore.DataProtection.KeyManagement.DeferredKey.<>c__DisplayClass1_0.<GetLazyDescriptorDelegate>b__0()
root-nextlevel-auth-1  |          at System.Lazy`1.ViaFactory(LazyThreadSafetyMode )
root-nextlevel-auth-1  |          at System.Lazy`1.ExecutionAndPublication(LazyHelper , Boolean )
root-nextlevel-auth-1  |          at System.Lazy`1.CreateValue()
root-nextlevel-auth-1  |          at System.Lazy`1.get_Value()
root-nextlevel-auth-1  |          at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyBase.get_Descriptor()
root-nextlevel-auth-1  |          at Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory.CreateEncryptorInstance(IKey key)
root-nextlevel-auth-1  |          at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyBase.CreateEncryptor()
root-nextlevel-auth-1  |          at Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver.CanCreateAuthenticatedEncryptor(IKey key)

This is an exception from the data protection stack, but if I disable this certificate on data protection I get about the same error from OpenIddict because they utilize the same certificate.

This is the code how I set up data protection and OpenIddict:

using var store = new X509Store(StoreName.My, StoreLocation.CurrentUser, OpenFlags.ReadWrite);

var dataProtectionCertificate = new X509Certificate2(
  configuration.GetValue<string>("Core:DataProtectionCertificatePath"),
  configuration.GetValue<string>("Core:DataProtectionCertificatePassword"));

var signingCertificate = new X509Certificate2(
  configuration.GetValue<string>("OpenId:SigningKeyCerfificatePath"),
  configuration.GetValue<string>("OpenId:SigningKeyCertificatePassword"));

store.Add(dataProtectionCertificate);
store.Add(signingCertificate);

services.AddDataProtection()
  .SetApplicationName(hidden)
  .PersistKeysToDbContext<ApplicationDbContext>()
  .ProtectKeysWithCertificate(dataProtectionCertificate);
            
----------------
// OpenIddict server options builder
options.UseDataProtection();
options.AddEncryptionCredentials(encryptionKey);
options.AddSigningCertificate(signingCertificate);

The 2 certificates are (for now) the exact same certificate generated using OpenSSL like so:

openssl genrsa -aes256 -out app_key.pem 2048
openssl req -key app_key.pem -new -x509 -days 36500 -out app_cert.crt
openssl pkcs12 -export -in app_cert.crt -inkey app_key.pem -out app_cert.pfx

Like I said the application is hosted on docker using the aspnet docker image, so this is running on Debian 11. The host system is Ubuntu 20.04.

What do I need to do to get valid certificates (because with the exact same certificates downloaded to my PC this exact same scenario works completely fine)

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 18 (9 by maintainers)

Most upvoted comments

You’re correct, which is why CryptoConfig.CreateFromName is painted with [RequiresUnreferencedCode("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")].

It might work to just have strong references somewhere else in your code; but in the BCL we never call into CryptoConfig, just use our own switchafalls (e.g. https://github.com/dotnet/runtime/blob/2f3fcca06499725469b6ae021be960e08d808c75/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACCommon.cs#L57-L69).

I think it hasn’t come up automatically yet because we haven’t finished trimmer analysis on System.Security.Cryptography.Xml. That’s not to say that wherever the data protector lives wouldn’t benefit from a nudge to let them know they might want to draft a “how to make data protector happy in this scenario” doc.