Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check the signature for a signed XML document with SHA256?

Seems that SignedXml.CheckSignature is working fine only for signed documents using SHA1.

I tried this code by adding the algorithm SHA256, and the CheckSignature worked fine but the WIF classes started throwing the following exception:

System.Security.Cryptography.CryptographicException: Invalid algorithm specified. In this method call System.IdentityModel.Services.FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest

Seems that the ProcessSignInRequest uses the algorithm SHA1 which has been overridden internally here:

CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), 
                          "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");

What did I miss? How can I specify the algorithm in CheckSignature?

like image 844
Homam Avatar asked Dec 04 '14 14:12

Homam


People also ask

What is signature value in XML?

The <SignatureValue> element is a subelement of the <Signature> element. Use the SignatureValue property to retrieve the value of the XML digital signature. This property is automatically populated when you make a successful call to the ComputeSignature method.

What are XML signatures list and describe the 3 types of XML signatures?

Introduction to XML Signatures You can use an XML Signature to sign any arbitrary data, whether it is XML or binary. The data is identified via URIs in one or more Reference elements. XML Signatures are described in one or more of three forms: detached, enveloping, or enveloped.

How does XML signature work?

An XML digital signature (XML DSIG) is an electronic, encrypted, stamp of authentication on digital information such as messages. The digital signature confirms that the information originated from the signer and was not altered in transmission.


1 Answers

I had the same issue today. It turned out that the WIF signing certificate was generated using a CSP without SHA256 support (more details).

I browsed the System.IdentityModel source code and discovered that it contains special handling for this case. When you have the corresponding algorithm registered globally, WIF uses it instead of its internal implementation, and the RSAPKCS1SHA256SignatureDescription class does not include this special handling.

So I made my own SignatureDescription implementation which recreates the RSACryptoServiceProvider with default parameters, which include SHA256 support.

/// <summary>
/// Represents the sha256RSA signature algorithm.
/// </summary>
public sealed class RsaPkcs1Sha256SignatureDescription : SignatureDescription
{
    /// <summary>
    /// This type of CSP has SHA256 support
    /// </summary>
    private const int PROV_RSA_AES = 24;

    public RsaPkcs1Sha256SignatureDescription()
    {
        KeyAlgorithm = typeof(RSACryptoServiceProvider).FullName;
        DigestAlgorithm = typeof(SHA256Cng).FullName;
        FormatterAlgorithm = typeof(RSAPKCS1SignatureFormatter).FullName;
        DeformatterAlgorithm = typeof(RSAPKCS1SignatureDeformatter).FullName;
    }

    /// <summary>
    /// Adds support for sha256RSA XML signatures.
    /// </summary>
    public static void RegisterForSignedXml()
    {
        CryptoConfig.AddAlgorithm(
            typeof (RsaPkcs1Sha256SignatureDescription),
            "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
    }

    public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
    {
        if (key == null) throw new ArgumentNullException("key");

        key = GetSha2CompatibleKey(key);

        var signatureDeformatter = new RSAPKCS1SignatureDeformatter(key);
        signatureDeformatter.SetHashAlgorithm("SHA256");
        return signatureDeformatter;
    }

    public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
    {
        if (key == null) throw new ArgumentNullException("key");

        key = GetSha2CompatibleKey(key);

        var signatureFormatter = new RSAPKCS1SignatureFormatter(key);
        signatureFormatter.SetHashAlgorithm("SHA256");
        return signatureFormatter;
    }

    // Some certificates are generated without SHA2 support, this method recreates the CSP for them.
    // See https://stackoverflow.com/a/11223454/280778
    // WIF handles this case internally if no sha256RSA support is installed globally.
    private static AsymmetricAlgorithm GetSha2CompatibleKey(AsymmetricAlgorithm key)
    {
        var csp = key as RSACryptoServiceProvider;
        if (csp == null || csp.CspKeyContainerInfo.ProviderType == PROV_RSA_AES)
            return key;

        var newKey = new RSACryptoServiceProvider(new CspParameters(PROV_RSA_AES));
        newKey.ImportParameters(csp.ExportParameters(true));
        return newKey;
    }
}
like image 102
Dark Daskin Avatar answered Oct 14 '22 12:10

Dark Daskin