将应用程序从 3.5 升级到 4.6.2 后 以下代码块不再有效。我得到“格式错误的参考元素”错误,即使它作为 3.5 应用程序工作得很好。代码因上述错误而失败,应该是一个很好的参考。我已经尝试了我能想到的一切都无法让 ASP.Net 版本正常工作。我已经构建了一个测试平台版本作为控制台应用程序,它可以正常工作,直到它到达最后一个失败并显示“无法解析 Uri Signature1.jpg”的引用。我读过 XMLSigner 不接受除 id、ID 和 Id 以外的任何元素作为要查找以匹配引用的元素,但我不相信这种情况,因为它适用于控制台应用程序。
问题的核心是:
- 为什么我得到一个“格式错误的参考元素”
signedXMl.AddReference(new Reference("#Head01"));
- 如何修复对客户签名“src="Signature1.jpg"" 的引用
有问题的功能:
private XmlDocument SignDoc(XmlDocument doc, RSA key, X509Certificate x509cert, ArrayList alSignatures)
{
string signatureID = "TamperSealer01";
Uri uri = new Uri(ConfigurationManager.AppSettings["SomeSetting"]);
XmlResolver resolver = new XmlSignatureResolver(uri);
SignedXml signedXml = new SignedXml(doc);
signedXml.Signature.Id = signatureID;
signedXml.Resolver = resolver;
// Add the key to the SignedXml responseDocument.
signedXml.SigningKey = key;
// Create a new KeyInfo object.
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new RSAKeyValue(key));
KeyInfoX509Data x509Data = new KeyInfoX509Data(x509cert);
string subjectName = x509cert.Subject;
subjectName = subjectName.Replace("S=", "ST=");
string tmpSubName = subjectName;
tmpSubName = tmpSubName.Replace("O=A", "O=B");
tmpSubName = tmpSubName.Replace("CN=A", "CN=B");
x509Data.AddSubjectName(tmpSubName);
x509Data.AddIssuerSerial(x509cert.Issuer, x509cert.GetSerialNumberString()); //GetIssuerName
keyInfo.AddClause(x509Data);
signedXml.KeyInfo = keyInfo;
//TIMESTAMP
XmlElement signaturePropertiesRoot = doc.CreateElement("SignatureProperties", "http://www.w3.org/2000/09/xmldsig#");
DataObject signatureProperties = new DataObject();
signatureProperties.Id = "TimeStamp";
signatureProperties.Data = signaturePropertiesRoot.SelectNodes(".");
signedXml.AddObject(signatureProperties);
// and add a reference to the data object
Reference propertiesRef = new Reference();
propertiesRef.Uri = "#TimeStamp";
propertiesRef.Type = "http://www.w3.org/2000/09/xmldsig#SignatureProperties";
signedXml.AddReference(propertiesRef);
XmlElement property = doc.CreateElement("SignatureProperty", "http://www.w3.org/2000/09/xmldsig#");
property.SetAttribute("Id", "TamperSealer01TimeStamp");
property.SetAttribute("Target", "#" + signedXml.Signature.Id);
signaturePropertiesRoot.AppendChild(property);
XmlElement timestamp = doc.CreateElement("DateTimeStamp", "http://www.w3.org/2000/09/xmldsig#");
timestamp.SetAttribute("DateTime", String.Format("{0:s}Z", DateTime.Now.ToUniversalTime()));
property.AppendChild(timestamp);
signedXml.ComputeSignature();
// References contains three strings "Head01", "Data01", and "View01"
foreach (string docRef in references)
{
// Create a reference to be signed.
Reference tempRef = new Reference();
tempRef.Uri = "#" + docRef;
Logger.Current.LogInformation("DocRef: #" + docRef + ".");
// Add the reference to the SignedXml object
signedXml.AddReference(tempRef);
signedXml.ComputeSignature(); //Immediately Fails here
}
// alSignatures only contains "Signature1.jpg" in this case. Don't yell at me for this crappy code, I didn't write it and plan on fixing it when everything else works.
int ctr = 0;
foreach (string str in alSignatures)
{
Reference testRef = new Reference();
Uri relativeUri = new Uri(alSignatures[ctr].ToString(), UriKind.RelativeOrAbsolute);
Logger.Current.LogInformation("Signature Reference: " + alSignatures[ctr].ToString());
testRef.Uri = alSignatures[ctr].ToString();
signedXml.AddReference(testRef);
ctr += 1;
}
// Compute the signature.
signedXml.ComputeSignature();
// Get the XML representation of the signature and save it to an XmlElement object.
XmlElement xmlDigitalSignature = signedXml.GetXml();
XmlElement signaturesElement = doc.CreateElement("SIGNATURES", "http://www.mismo.org");
signaturesElement.AppendChild(signedXml.GetXml());
doc.DocumentElement.AppendChild(signaturesElement);
key.Clear();
key.Dispose();
return doc;
}
它应该签名的 XML 至少是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<DOCUMENT MISMOVersionIdentifier="1.02">
<HEADER _ID="Head01">
<SIGNATURE_MODEL>
<SIGNER AreaIDREF="Borrower1SignatureArea" SectionIDREF="BorrowerSignatures" SignatureIDREF="Borrower1SignatureLine" SignatureType="Image" TargetsIDREFS="View01" _RoleType="Borrower" _SignatureOrderNumber="1" />
<SIGNER SignatureIDREF="TamperSealer01" SignatureType="DigitalSignature" TargetsIDREFS="Head01 Data01 View01" _RoleType="TamperSealer" _SignatureOrderNumber="1" />
</SIGNATURE_MODEL>
</HEADER>
<DATA _ID="Data01">
<MAIN>
</MAIN>
</DATA>
<VIEW _ID="View01" _MIMETypeDescription="text/html" _TaggedIndicator="True">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<span class="dataEntered" id="BORROWER_Signer-Info">
<SIGNATURE_SECTION _ID="BorrowerSignatures">
<SIGNATURE_AREA _ID="Borrower1SignatureArea">
<p class="right">
<SIGNATURE_ABOVE_LINE />
<SIGNATURE_IMAGE _EncodingTypeDescription="None" _ID="Borrower1SignatureLine" _MIMEType="image/jpeg">
<img align="right" alt="Signature file is missing - Invalid Document" src="Signature1.jpg" />
</SIGNATURE_IMAGE>
</p>
<p>04/12/2011 12:00 PM</p>
</SIGNATURE_AREA>
</SIGNATURE_SECTION>
</span>
</body>
</html>
</VIEW>
</DOCUMENT>