XML 签名适用于随机 RSA 密钥,但不适用于证书中的密钥
XML Signature works with random RSA Key but not with key from certificate
我正在尝试使用 C# 中的以下算法签署 XML 文档:
当我尝试使用随机 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));
现在签名有效了!
我正在尝试使用 C# 中的以下算法签署 XML 文档:
当我尝试使用随机 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));
现在签名有效了!