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密钥签名时,它工作得很好。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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密钥:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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),我不知道为什么会出现此错误。
谢谢您!
托马斯
我终于找到了解决问题的办法。如果它能帮助某人:
以前我尝试通过以下方式从证书中获取私钥:
1 |
这是我班手势证书的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | 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,我做了以下操作:
1 2 3 4 |
现在签名生效了!