XML 签名适用于随机 RSA 密钥,但不适用于证书中的密钥

XML Signature works with random RSA Key but not with key from certificate

我正在尝试使用 C# 中的以下算法签署 XML 文档:

http://www.w3.org/2001/04/xmldsig-more#rsa-sha256

当我尝试使用随机 RSA 密钥对其进行签名时,它运行良好。

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.PreserveWhitespace = false;
        xmlDoc.Load("hpbtest.xml");
        RSA Key = new RSACryptoServiceProvider(2048);
        // Create a SignedXml object.
        PrefixedSignedXML signedXml = new PrefixedSignedXML(xmlDoc);
        // Add the key to the SignedXml document.
        signedXml.SigningKey = Key;
        signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
        // Create a reference to be signed.
        Reference reference = new Reference();
        reference.Uri = "#xpointer(//*[@authenticate='true'])";
        reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
        // Add an enveloped transformation to the reference.
        XmlDsigExcC14NTransform env = new XmlDsigExcC14NTransform();
        env.Algorithm = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
        reference.AddTransform(env);
        // Add the reference to the SignedXml object.
        signedXml.AddReference(reference);
        // Compute the signature.
        signedXml.ComputeSignature("ds");
        // Get the XML representation of the signature and save
        // it to an XmlElement object.
        XmlElement xmlDigitalSignature = signedXml.GetXml("ds");
        // Append the element to the XML document.
        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
        xmlDoc.Save("hpbtest.xml");

但是如果我想使用 OpenSSL 生成的证书中的 RSA 密钥:

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.PreserveWhitespace = false;
        xmlDoc.Load("hpbtest.xml");
        RSA Key = new GestionCertificat("CN=Bruno").getClePrivee();//Get the private key
        // Create a SignedXml object.
        PrefixedSignedXML signedXml = new PrefixedSignedXML(xmlDoc);
        // Add the key to the SignedXml document.
        signedXml.SigningKey = Key;
        signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
        // Create a reference to be signed.
        Reference reference = new Reference();
        reference.Uri = "#xpointer(//*[@authenticate='true'])";
        reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
        // Add an enveloped transformation to the reference.
        XmlDsigExcC14NTransform env = new XmlDsigExcC14NTransform();
        env.Algorithm = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
        reference.AddTransform(env);
        // Add the reference to the SignedXml object.
        signedXml.AddReference(reference);
        // Compute the signature.
        signedXml.ComputeSignature("ds");
        // Get the XML representation of the signature and save
        // it to an XmlElement object.
        XmlElement xmlDigitalSignature = signedXml.GetXml("ds");
        // Append the element to the XML document.
        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
        xmlDoc.Save("hpbtest.xml");

我收到此错误:

Invalid specified algorithm

在这两个示例中,我的 RSA 密钥长度相同 (2048),我不知道为什么会出现此错误。

谢谢!

托马斯

我终于找到了解决问题的方法。如果它可以帮助某人:

以前我尝试通过这种方式从证书中获取私钥:

RSA Key = new GestionCertificat("CN=EbicsAuth").getClePrivee();//Get the private key

这是我的 class GestionCertificat 的代码:

String CertificatEncoded;
    String ModulusEncoded;
    String ExponentEncoded;
    RSA Cle;
    RSA ClePrivee;
    X509Certificate2 Certificat;
    public GestionCertificat(String NomCertificat)
    {
        X509Store store = new X509Store(StoreLocation.CurrentUser);
        store.Open(OpenFlags.ReadOnly);
        X509Certificate2Collection certCollection = store.Certificates;
        X509Certificate2 cert = null;
        foreach (X509Certificate2 c in certCollection)
        {
            if (c.Subject == NomCertificat)
            {
                cert = c;
                break;
            }
        }
        store.Close();
        Certificat = cert;
        CertificatEncoded = Convert.ToBase64String(cert.RawData); //Conversion du certificat en base64
        RSACryptoServiceProvider rsaprovider = (RSACryptoServiceProvider)cert.PublicKey.Key;//Récupération de la clé RSA du certificat
        RSAParameters newparams = rsaprovider.ExportParameters(false);//Extractions des paramètres de la clé
        ModulusEncoded = Convert.ToBase64String(newparams.Modulus);//Conversion du Modulus en base64
        ExponentEncoded = Convert.ToBase64String(newparams.Exponent);//Conversion de l'Exponent en base64
        Cle = (RSA)cert.PublicKey.Key;
        ClePrivee = (RSA)cert.PrivateKey;
    }

    public String getCertificatEncoded()
    {
        return this.CertificatEncoded;
    }

    public String getModulusEncoded()
    {
        return this.ModulusEncoded;
    }

    public String getExponentEncoded()
    {
        return this.ExponentEncoded;
    }

    public RSA getClePublique()
    {
        return this.Cle;
    }

    public RSA getClePrivee()
    {
        return this.ClePrivee;
    }

    public X509Certificate2 getCertificat()
    {
        return this.Certificat;
    }

但现在要获得 RSA 密钥来签署我的 XML 我这样做了:

RSACryptoServiceProvider Key = new RSACryptoServiceProvider();
var gestionCertif = new GestionCertificat("CN=EbicsAuth");
X509Certificate2 Cert = gestionCertif.getCertificat();
Key.FromXmlString(Cert.PrivateKey.ToXmlString(true));

现在签名有效了!