Actualicé una de nuestras aplicaciones web de .NET Framework 4.6 a 4.8. En algún lugar profundo del código, se firma una cadena XML y este XML firmado se envía de vuelta al cliente, que verificará la firma. La firma XML utiliza la clase SignedXml
.
Debido a su naturaleza heredada, SHA1 todavía se usa (¡tenga paciencia conmigo!). Para no interrumpir este comportamiento al actualizar .NET Framework, tuve que configurar los siguientes modificadores de AppContext antes de firmar el XML:
AppContext.SetSwitch("Switch.System.Security.Cryptography.Xml.UseInsecureHashAlgorithms", true); AppContext.SetSwitch("Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms", true);
Eso resolvió todos los problemas en mi máquina local y pude firmar con éxito los XML.
Ahora, al avanzar e implementar la nueva versión del código en nuestro entorno de prueba, surgió un nuevo problema: la firma XML falla con una excepción Invalid algorithm specified
. Aquí está el seguimiento de la pila:
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash, Int32 cbHash, ObjectHandleOnStack retSignature) at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash) at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, Int32 calgHash) at System.Security.Cryptography.Xml.SignedXml.ComputeSignature()
Ahora me topé con esta pregunta y especialmente con esa respuesta en particular .
Así que revisé los CSP usando certutil
y obtengo los siguientes resultados:
Microsoft Enhanced RSA and AES Cryptographic Provider
→ funcionaMicrosoft Enhanced Cryptographic Provider v1.0
→ no funcionaPregunta : ¿hay alguna posibilidad de mitigar este comportamiento, por ejemplo, mediante el uso de otra pieza de código para firmar el XML? ¿O tengo que volver a crear el certificado?
¡Gracias por adelantado!
Finalmente encontré una solución que funcionó para mí. Hay dos puntos principales:
SwissSign nos proporcionó los certificados para nuestro entorno de ensayo ( pem
y archivo de key
) y creamos el archivo p12
por nuestra cuenta.
Al especificar el CSP
del parámetro OpenSSL al crear el archivo p12
, se puede configurar el CSP correcto. Un comando podría parecerse a:
openssl pkcs12 -export -out Output.p12 -inkey My.key -in My.chain.pem -name My -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider"
En caso de que solo tenga el archivo p12
, debe convertirlo de PKCS10 a formato PEM antes llamando:
openssl pkcs12 -in my.p12 -out my.pem
Como se mencionó anteriormente, se deben configurar los siguientes modificadores de AppContext:
AppContext.SetSwitch("Switch.System.Security.Cryptography.Xml.UseInsecureHashAlgorithms", true); AppContext.SetSwitch("Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms", true);
En mi caso, estaba configurando los interruptores en algún lugar profundo de la clase donde realmente firmé el XML. Entonces, este código se ejecutó en tiempo de ejecución cuando se manejó la primera solicitud web.
Al investigar las partes internas de System.Security.Cryptography.Xml.SignedXml
, descubrí que algunos de los conmutadores de AppContext en realidad se almacenan en caché. Mis actualizaciones simplemente llegaron demasiado tarde.
Ahora configuro los interruptores en el inicio de la aplicación y todo funciona bien 🥳