我使用signedxml生成了一个xml签名,验证效果很好。 我的签名xml如下所示
<Signature Id="orderSignature" xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>0r1BZecYgC4FzPIxuU9DYIbVqUE=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>B+SreGOR7+QEnvo0zMgJsNgZ4gbA1leOifLGd09HG8lZD0ZxsBkcR0aauTgwRgeOefKSwah+KEqAlZvRNykgPjBmY9BJ2g6OfRdvm/mSj7ecDuq/Ic1vo5bHeFJHzr8qbS7IKS/hl/BOx+06yg5rFbVeQGYypznNLIKrjS5cfDbo11e6tpLWswZMxhly8c+FHuMKzAJKOw4spbebgVT4p/vGYsPekTRtvtLtqp1yVl1za8xWkqXmbPPxwio7rXFpKWAqdLQiHYW0cs8ARXUo2jSjete+m4+wQ3QpN4Wfj8Cs3+bYsh01r1XHUG48w3PGt11+trlIEABCaQrhgj9xzg==</SignatureValue>
<KeyInfo>
<KeyValue>
<RSAKeyValue>
<Modulus>z9KDoRUO4alAwhL2Nq2fIAwsbecLuWYnzwKEX2WsUOWmhXksD+uYqjRqrKpV9j2tWFf6Ba87zEEa5xPOgD9Jj5naq6tDuH9q48u2gosC3vohPTNXL1I1sj9NTYIFNN+xcf/hi7fPQa/yq5lPOwN45kblee8Z6MqVt6Jk5ytQ+jMT6ZMStL6dOASKbwROfb0uhdmOieX60CGNAbdrn/ei2Vr2EOVmHSB1ZqZ0EhaFTKK5PPuiDlptl+bH0KBqkYEcMgzGMgxNJbDM/MlHgXWh9IWTS/A64awy8xUEQwq9QCibYzI5WCDceyTiNSAVhBQDMEX4YyWDj52sceKEK/q9NQ==</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
<X509Data>
<X509IssuerSerial>
<X509IssuerName>CN=Mali Mühür Elektronik Sertifika Hizmet Sağlayıcısı - Sürüm 1, C=TR</X509IssuerName>
<X509SerialNumber>97806797770378</X509SerialNumber>
</X509IssuerSerial>
<X509SubjectName>CN=Bimtel İletişim Ve Bilişim Ticaret Limited Şirketi, SERIALNUMBER=1750422091</X509SubjectName>
<X509Certificate>MIIFrTCCBJWgAwIBAgIGWPRrcA6KMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNVBAYTAlRSMU0wSwYDVQQDDERNYWxpIE3DvGjDvHIgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMTAeFw0xMTEwMTkxMjQ1NDVaFw0xNjEwMTcxMjQ1NDVaMFYxEzARBgNVBAUTCjE3NTA0MjIwOTExPzA9BgNVBAMMNkJpbXRlbCDEsGxldGnFn2ltIFZlIEJpbGnFn2ltIFRpY2FyZXQgTGltaXRlZCDFnmlya2V0aTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM/Sg6EVDuGpQMIS9jatnyAMLG3nC7lmJ88ChF9lrFDlpoV5LA/rmKo0aqyqVfY9rVhX+gWvO8xBGucTzoA/SY+Z2qurQ7h/auPLtoKLAt76IT0zVy9SNbI/TU2CBTTfsXH/4Yu3z0Gv8quZTzsDeOZG5XnvGejKlbeiZOcrUPozE+mTErS+nTgEim8ETn29LoXZjonl+tAhjQG3a5/3otla9hDlZh0gdWamdBIWhUyiuTz7og5abZfmx9CgapGBHDIMxjIMTSWwzPzJR4F1ofSFk0vwOuGsMvMVBEMKvUAom2MyOVgg3Hsk4jUgFYQUAzBF+GMlg4+drHHihCv6vTUCAwEAAaOCAnkwggJ1MB8GA1UdIwQYMBaAFEYgqVMbKAwcrvIoUYOzHr7yUxR8MB0GA1UdDgQWBBRv135w613ZEQPsNPW+8TDIFkKEDzAOBgNVHQ8BAf8EBAMCB4AwggEzBgNVHSAEggEqMIIBJjCCASIGC2CGGAECAQEFBwQBMIIBETAqBggrBgEFBQcCARYeaHR0cDovL2RlcG8ua2FtdXNtLmdvdi50ci9pbGtlMIHiBggrBgEFBQcCAjCB1R6B0gBCAHUAIABzAGUAcgB0AGkAZgBpAGsAYQAgAGkAbABlACAAaQBsAGcAaQBsAGkAIABzAGUAcgB0AGkAZgBpAGsAYQAgAHUAeQBnAHUAbABhAG0AYQAgAGUAcwBhAHMAbABhAHIBMQBuATEAIABvAGsAdQBtAGEAawAgAGkA5wBpAG4AIABiAGUAbABpAHIAdABpAGwAZQBuACAAdwBlAGIAIABzAGkAdABlAHMAaQBuAGkAIAB6AGkAeQBhAHIAZQB0ACAAZQBkAGkAbgBpAHoALjAMBgNVHRMBAf8EAjAAMBYGA1UdJQQPMA0GC2CGGAECAQEFBzIBMEEGA1UdHwQ6MDgwNqA0oDKGMGh0dHA6Ly9kZXBvLmthbXVzbS5nb3YudHIva3VydW1zYWwvbW1lc2hzLXMxLmNybDCBggYIKwYBBQUHAQEEdjB0MDwGCCsGAQUFBzAChjBodHRwOi8vZGVwby5rYW11c20uZ292LnRyL2t1cnVtc2FsL21tZXNocy1zMS5jcnQwNAYIKwYBBQUHMAGGKGh0dHA6Ly9jaXNkdXBtbXMxLmt1cnVtc2FsLmthbXVzbS5nb3YudHIwDQYJKoZIhvcNAQELBQADggEBAFX0arwcDDLRbYHOkxb3Os4t3kMxPG7VzBAcgiPCV/ph1xda1S7IyXTk54L6OsXtsW/JBvf9+mjufAQXPwUl1AoqndBOkzYuOYv5ZXpK0Uzb1yV+XiLZtKp44wv2FeaEN5D/nyMAwi6ckGE959/JnXV5AAURBwgrnuOcksryJwOyRV78JAu28UL0fflDdmLR8qZKUUDdDzAhHTZzXBjF1GtHyEGtg3nJKO13ZZba6HXbv6dP2J7ZgFTTeyobTh5MsnBIedSItxfAxUhls7M8L3h0X42Dkx28nZw7zG1n55TIPrahihjR99qYGVnf5lnfYOt5/dhkeOazxam+QookoBI=</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
但我需要使用“ds:”前缀生成xml签名。
我无法在stackoverflow中找到关于此问题的sollution。
如何获取带前缀的xml签名? 是否可以使用signedxml(System.Security.Cryptography.Xml)库,
或者我可以生成任何库吗?
感谢您的任何建议..
答案 0 :(得分:2)
我真的不明白为什么要在命名空间中添加ds前缀。
有这个:
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="Signature">
<ds:SignedInfo Id="SignedInfo">
<ds:CanonicalizationMethod ...
完全等同于:
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="Signature">
<SignedInfo Id="SignedInfo">
<CanonicalizationMethod ...
在第一种情况下,您必须为http://www.w3.org/2000/09/xmldsig#命名空间中的元素指定ds,在第二种情况下,此命名空间是默认命名空间,因此xml中没有声明前缀的每个元素都来自此命名空间。
此外,您说您需要添加ds前缀才能拥有XAdES-BES,并且您可以对xmldsig和xades签名之间的区别进行评论。您必须知道XAdES只是一个规范,它说明XMLDSIG签名需要哪些属性才能成为XAdES签名。大致XAdES是一个XMLDSIG签名,其中包含:<Object http://www.w3.org/2000/09/xmldsig#>
,它将成为整个限定属性集的包,其中一些是签名的(signedProperties),其中一些是unsigned(unsignedProperties)。对于XAdES-BES案例,您必须在<xades:SigningCertificate xmlns:xades="http://uri.etsi.org/01903/v1.3.2#">
元素中添加<xades:SignedProperties>
。
这里我举一个XAdES-BES签名“没有”ds前缀的例子。
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="Signature">
<SignedInfo Id="SignedInfo">
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference Id="SignedProperties-Reference" Type="http://uri.etsi.org/01903/v1.2.2#SignedProperties" URI="#SignedProperties">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>fiKTaqJzLSmC73cMXZSzjhd877w=</DigestValue>
</Reference>
<Reference Id="SignedDataObject-Reference-1" URI="DetachedObjectReference-1">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>8ruIS/4MRp2wAwVX4/pTCYxTyWc=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue Id="DocumentSignatureValue">
R40YdEEEl0YIZVdl4pm3yyF7qGAG8ZN8PPf0aBRXbvRgdIcvJZtI5AS5NexaO5T4O0gMHWRIKjNb
2QzlfwxlQ3/KqMW4W0QkMLpF4csBpXt9bJ3t+smEeTnxkBcQRXAw5v9kwf20mfz1LtIUhbsU/PMd
YwaGCsItF2rzl3rtcq4=
</SignatureValue>
<KeyInfo Id="KeyInfo">
<X509Data>
<X509Certificate>
MIIIUTCCBzmgAwI...
</X509Certificate>
</X509Data>
<KeyValue>
<RSAKeyValue>
<Modulus>
pb0cJiodddCDVe/t+7...
</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
</KeyInfo>
<Object>
<xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Id="QualifyingProperties" Target="#Signature">
<xades:SignedProperties Id="SignedProperties">
<xades:SignedSignatureProperties>
<xades:SigningCertificate>
<xades:Cert>
<xades:CertDigest>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>UZq4NIL9eVVA7aJixPeiUTM3nOM=</DigestValue>
</xades:CertDigest>
<xades:IssuerSerial>
<X509IssuerName>XXXXXXXXXXXX....</X509IssuerName>
<X509SerialNumber>705964899...</X509SerialNumber>
</xades:IssuerSerial>
</xades:Cert>
</xades:SigningCertificate>
</xades:SignedSignatureProperties>
<xades:SignedDataObjectProperties/>
</xades:SignedProperties>
</xades:QualifyingProperties>
</Object>
希望这有帮助,
答案 1 :(得分:1)
尝试在签名之前将此属性 xmlns:ds =“http://www.w3.org/2000/09/xmldsig#”添加到XML文档的根标记中。我的情况下它有助于封装签名,但我使用的是Crypto API。希望这会对你有所帮助。
答案 2 :(得分:1)
经过大量研究,我找到了答案。 基本上,在获取SignedInfo节点的摘要值之前,必须修改SignedXml类以添加前缀。
将修改ComputeSignature方法以添加前缀参数
public void ComputeSignature(string prefix){...}
当调用此方法时,如果在没有&#34; ds&#34;的情况下获得此值,则通过消化SignedInfo节点的值来计算签名值。前缀然后添加前缀,您将获得无效的签名,因此您必须在获取signedinfo节点的摘要值之前添加前缀。
此摘要值在GetC14NDigest方法中生成,因此将修改此方法以添加前缀参数并在获取摘要值之前添加前缀
private byte[] GetC14NDigest(HashAlgorithm hash, string prefix)
{
XmlDocument document = new XmlDocument();
document.PreserveWhitespace = false;
XmlElement e = this.SignedInfo.GetXml(); //get the signedinfo nodes
document.AppendChild(document.ImportNode(e, true));
Transform canonicalizationMethodObject = this.SignedInfo.CanonicalizationMethodObject;
SetPrefix(prefix, document.DocumentElement); /*Set the prefix before getting the HASH*/
canonicalizationMethodObject.LoadInput(document);
return canonicalizationMethodObject.GetDigestedOutput(hash);
}
好的,现在你有了SIGNInfo节点的Signature Value和&#34; ds&#34;前缀,据说你仍然没有前缀的xml,所以如果你只是调用GetXml方法,你将看不到&#34; ds&#34;前缀,当然因为签名值是根据ds前缀计算的,所以你的签名无效。 为了避免这种情况并获得带有前缀的xml结构,您必须修改GetXml方法,添加前缀参数,并调用SetPrefix方法,它将添加&#34; ds&#34; Signature Xml中所有节点的前缀
public XmlElement GetXml(string prefix)
{
XmlElement e = this.GetXml();
SetPrefix(prefix, e); //return the xml structure with the prefix
return e;
}
我将带着这些修改离开这里
CUSTOM CLASS
internal sealed class CustomSignedXml : SignedXml
{
XmlElement obj = null;
public CustomSignedXml (XmlDocument xml)
: base(xml)
{
}
public CustomSignedXml (XmlElement xmlElement)
: base(xmlElement)
{
}
public XmlElement GetXml(string prefix)
{
XmlElement e = this.GetXml();
SetPrefix(prefix, e);
return e;
}
public void ComputeSignature(string prefix)
{
this.BuildDigestedReferences();
AsymmetricAlgorithm signingKey = this.SigningKey;
if (signingKey == null)
{
throw new CryptographicException("Cryptography_Xml_LoadKeyFailed");
}
if (this.SignedInfo.SignatureMethod == null)
{
if (!(signingKey is DSA))
{
if (!(signingKey is RSA))
{
throw new CryptographicException("Cryptography_Xml_CreatedKeyFailed");
}
if (this.SignedInfo.SignatureMethod == null)
{
this.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
}
}
else
{
this.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
}
}
SignatureDescription description = CryptoConfig.CreateFromName(this.SignedInfo.SignatureMethod) as SignatureDescription;
if (description == null)
{
throw new CryptographicException("Cryptography_Xml_SignatureDescriptionNotCreated");
}
HashAlgorithm hash = description.CreateDigest();
if (hash == null)
{
throw new CryptographicException("Cryptography_Xml_CreateHashAlgorithmFailed");
}
this.GetC14NDigest(hash, prefix);
this.m_signature.SignatureValue = description.CreateFormatter(signingKey).CreateSignature(hash);
}
private byte[] GetC14NDigest(HashAlgorithm hash, string prefix)
{
XmlDocument document = new XmlDocument();
document.PreserveWhitespace = false;
XmlElement e = this.SignedInfo.GetXml();
document.AppendChild(document.ImportNode(e, true));
Transform canonicalizationMethodObject = this.SignedInfo.CanonicalizationMethodObject;
SetPrefix(prefix, document.DocumentElement); //Set the prefix before getting the HASH
canonicalizationMethodObject.LoadInput(document);
return canonicalizationMethodObject.GetDigestedOutput(hash);
}
private void BuildDigestedReferences()
{
Type t = typeof(SignedXml);
MethodInfo m = t.GetMethod("BuildDigestedReferences", BindingFlags.NonPublic | BindingFlags.Instance);
m.Invoke(this, new object[] { });
}
private void SetPrefix(string prefix, XmlNode node)
{
foreach (XmlNode n in node.ChildNodes)
SetPrefix(prefix, n);
node.Prefix = prefix;
}
}
以及使用它的方式
CustomSignedXml signedXml = new CustomSignedXml();
//compute the signature with the "ds" prefix
signedXml.ComputeSignature("ds");
//get the xml of the signature with the "ds" prefix
XmlElement xmlDigitalSignature = signedXml.GetXml("ds");