Я должен подписать документ XML и добавить подпись XML в тот же элемент, который подписывается.Валидатор C # доволен своим собственным результатом, но онлайн-валидатор Java сообщает об ошибке (https://demo.bloombase.com/demo/spitfire/soa/verify.jsp)
Мне нужно вставить подпись в этот узел: / msg: Envelope / msg: EnvelopeBody / cus: Message / cus: MessageFooterи подписать целое / msg: Envelope / msg: EnvelopeBody / cus: Сообщение (расположено с использованием атрибута ID)
Это мой код (вторая часть проверяет документ XML и возвращает true - действительный)Валидатор Java сообщает «неверно».
Я должен что-то упустить, но что: - /Спасибо за любую подсказку.
#region Common
bool PRESERVE = true;
X509Store storex0 = new X509Store("My", StoreLocation.CurrentUser);
storex0.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection storex1 = (X509Certificate2Collection)storex0.Certificates;
// find valid ones
storex1 = storex1.Find(X509FindType.FindByTimeValid, DateTime.Now, true);
// find my real certificate that I want to use (hardcoded, choose yours...)
X509Certificate2 cert = storex1[2];
#endregion
// using this: Online validation fails - but signature there is REQUIRED(!)
string xPathElementWhereToPlaceSignature = "/msg:Envelope/msg:EnvelopeBody/cus:Message/cus:MessageFooter";
// using this: Online validation succeeded
//string xPathElementWhereToPlaceSignature = "/msg:Envelope/msg:EnvelopeHeader";
string xmlFileUnsigned = "C:\\tmp\\_\\mf-vzor-unsigned.xml";
string xmlFileTestSigned = "C:\\tmp\\_\\mf-vzor-signed.xml";
XmlDocument xmldoc = new XmlDocument();
xmldoc.PreserveWhitespace = PRESERVE;
xmldoc.Load(xmlFileUnsigned);
#region nametable
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(xmldoc.NameTable);
namespaceManager.AddNamespace("cus", "urn:cz:mfcr:iissp:schemas:Cus:v1");
namespaceManager.AddNamespace("msg", "urn:cz:mfcr:iissp:schemas:Messaging:v1");
namespaceManager.AddNamespace("iissp", "urn:cz:mfcr:iissp:schemas:Common:v1");
namespaceManager.AddNamespace("acc", "urn:cz:isvs:micr:schemas:AccountTypes:v1");
namespaceManager.AddNamespace("cmn", "urn:cz:isvs:micr:schemas:CommonTypes:v1");
namespaceManager.AddNamespace("bus", "urn:cz:isvs:micr:schemas:BusinessTypes:v2");
namespaceManager.AddNamespace("stm", "urn:cz:isvs:micr:schemas:StatementTypes:v1");
namespaceManager.AddNamespace("sig", "http://www.w3.org/2000/09/xmldsig#");
#endregion
SignedXmlCustomIds sxml = new SignedXmlCustomIds(xmldoc);
XmlNode nodeToSign = xmldoc.DocumentElement.SelectSingleNode("/msg:Envelope/msg:EnvelopeBody/cus:Message", namespaceManager);
sxml.SigningKey = cert.PrivateKey;
sxml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NWithCommentsTransformUrl;
//Reference r = new Reference("");
//r.Uri = String.Empty;
Reference r = new Reference("#podpisovanie");
Transform trns = new XmlDsigExcC14NWithCommentsTransform();
r.AddTransform(trns);
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
r.AddTransform(env);
sxml.AddReference(r);
string keyInfoVloz = "short";
if (keyInfoVloz == "short")
{
KeyInfo keyInfo = new KeyInfo();
//keyInfo.AddClause(new RSAKeyValue((RSA)cert.PrivateKey));
KeyInfoX509Data data = new KeyInfoX509Data(cert);
keyInfo.AddClause(data);
sxml.KeyInfo = keyInfo;
}
if (keyInfoVloz == "long")
{
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new RSAKeyValue((RSA)cert.PrivateKey));
KeyInfoX509Data keyData = new KeyInfoX509Data(cert);
X509IssuerSerial xserial;
xserial.SerialNumber = cert.SerialNumber;
xserial.IssuerName = cert.IssuerName.Name;
keyData.AddIssuerSerial(xserial.IssuerName, xserial.SerialNumber);
keyData.AddSubjectName(cert.SubjectName.Name);
keyInfo.AddClause(keyData);
sxml.KeyInfo = keyInfo;
}
sxml.ComputeSignature();
XmlElement sig = sxml.GetXml();
XmlNode nodeProVlozeniPodpisu = xmldoc.DocumentElement.SelectSingleNode(xPathElementWhereToPlaceSignature, namespaceManager);
// xmldoc.DocumentElement.AppendChild(xmldoc.ImportNode(sig, true));
nodeProVlozeniPodpisu.AppendChild(xmldoc.ImportNode(sig, true));
xmldoc.Save(xmlFileTestSigned);
xmldoc = new XmlDocument();
xmldoc = null;
// ############################################################### verify
//string xmlFile = "C:\\tmp\\_\\12121220-518e-41f8-96a3-228055fcf42f.xml";
List<string> fileNamesToCheck = new List<string>();
fileNamesToCheck.Add(xmlFileTestSigned);
// more files to add here (if u wish)
foreach (string fName in fileNamesToCheck)
{
XmlDocument xdoc = new XmlDocument();
xdoc.PreserveWhitespace = PRESERVE;
xdoc.Load(fName);
SignedXml signedXml = new SignedXml(xdoc);
XmlNodeList nodeList = xdoc.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
bool result = signedXml.CheckSignature(cert, true);
Console.WriteLine("Test of file: " + fName + " Result: " + result.ToString());
}
Неподписанный xml:
<?xml version="1.0" encoding="UTF-8"?>
<msg:Envelope xmlns:msg="urn:cz:mfcr:iissp:schemas:Messaging:v1" xmlns:iissp="urn:cz:mfcr:iissp:schemas:Common:v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cus="urn:cz:mfcr:iissp:schemas:Cus:v1" xmlns:sig="http://www.w3.org/2000/09/xmldsig#">
<msg:EnvelopeHeader>
<iissp:TransactionId>052bf00020478f03a12a2009f21a52</iissp:TransactionId>
<msg:DateTimeCreated>2009-12-03T21:52:07.0Z</msg:DateTimeCreated>
<msg:Sender>
<iissp:IC>99999999</iissp:IC>
<iissp:SubjectName>Účetní jednotka</iissp:SubjectName>
<iissp:ResponsiblePerson>
<iissp:PersonName>Zodpovědná Osoba</iissp:PersonName>
<iissp:Email>zodpovedna.osoba@ucetnijednotka.cz</iissp:Email>
<iissp:PersonId>2000000002</iissp:PersonId>
</iissp:ResponsiblePerson>
</msg:Sender>
<msg:Recipient>
<iissp:IC>00006947</iissp:IC>
<iissp:SubjectName>Ministerstvo financí ČR</iissp:SubjectName>
<iissp:Module>CSUIS</iissp:Module>
</msg:Recipient>
</msg:EnvelopeHeader>
<msg:EnvelopeBody>
<cus:Message ID="podpisovanie">
<cus:MessageHeader>
<cus:MessageId>MessageId0</cus:MessageId>
<cus:DateTimeCreated>2009-12-03T21:52:07.0Z</cus:DateTimeCreated>
<cus:RecordType>061</cus:RecordType>
</cus:MessageHeader>
<cus:MessageBody>
<VykazZAM104 xmlns="urn:cz:isvs:micr:schemas:ZAM_1_04:v1" xmlns:cmn="urn:cz:isvs:micr:schemas:CommonTypes:v1" xmlns:bus="urn:cz:isvs:micr:schemas:BusinessTypes:v2" xmlns:acc="urn:cz:isvs:micr:schemas:AccountTypes:v1" xmlns:cct="urn:cz:isvs:micr:schemas:CoreComponentTypes:v1" xmlns:stm="urn:cz:isvs:micr:schemas:StatementTypes:v1">
<VykazHlavicka>
<bus:SubjektICO>99999999</bus:SubjektICO>
<stm:Kapitola>999</stm:Kapitola>
<stm:DatumSestaveni>2011-01-24</stm:DatumSestaveni>
<stm:DatumVykaz>2010-12-31</stm:DatumVykaz>
<stm:FinancniCastkaRad>1000</stm:FinancniCastkaRad>
</VykazHlavicka>
<OrganStatniSpravyUstredni>
<PocetZamestnancuRozpocetSchvaleny>7149</PocetZamestnancuRozpocetSchvaleny>
<PocetZamestnancuRozpocetPoZmenach>5245</PocetZamestnancuRozpocetPoZmenach>
<PocetZamestnancuRozpocetPoZmenachPrumerRocni>5963</PocetZamestnancuRozpocetPoZmenachPrumerRocni>
<PocetZamestnancuSkutecnostPrumer>5963</PocetZamestnancuSkutecnostPrumer>
</OrganStatniSpravyUstredni>
<OrganStatniSpravyUstredniPrislusniciVojaci>
<PocetZamestnancuRozpocetSchvaleny>3700</PocetZamestnancuRozpocetSchvaleny>
<PocetZamestnancuRozpocetPoZmenach>1190</PocetZamestnancuRozpocetPoZmenach>
<PocetZamestnancuRozpocetPoZmenachPrumerRocni>4218</PocetZamestnancuRozpocetPoZmenachPrumerRocni>
<PocetZamestnancuSkutecnostPrumer>1937</PocetZamestnancuSkutecnostPrumer>
</OrganStatniSpravyUstredniPrislusniciVojaci>
<OrganStatniSpravyUstredniOdmenovaniOdvozene>
<PocetZamestnancuRozpocetSchvaleny>1848</PocetZamestnancuRozpocetSchvaleny>
<PocetZamestnancuRozpocetPoZmenach>1082</PocetZamestnancuRozpocetPoZmenach>
<PocetZamestnancuRozpocetPoZmenachPrumerRocni>1417</PocetZamestnancuRozpocetPoZmenachPrumerRocni>
<PocetZamestnancuSkutecnostPrumer>1179</PocetZamestnancuSkutecnostPrumer>
</OrganStatniSpravyUstredniOdmenovaniOdvozene>
<OSSJednotliveStatniSprava>
<PocetZamestnancuRozpocetSchvaleny>1878</PocetZamestnancuRozpocetSchvaleny>
<PocetZamestnancuRozpocetPoZmenach>1551</PocetZamestnancuRozpocetPoZmenach>
<PocetZamestnancuRozpocetPoZmenachPrumerRocni>1676</PocetZamestnancuRozpocetPoZmenachPrumerRocni>
<PocetZamestnancuSkutecnostPrumer>1777</PocetZamestnancuSkutecnostPrumer>
</OSSJednotliveStatniSprava>
<OSSJednotliveStatniSpravaPrislusniciVojaci>
<PocetZamestnancuRozpocetSchvaleny>4882</PocetZamestnancuRozpocetSchvaleny>
<PocetZamestnancuRozpocetPoZmenach>1659</PocetZamestnancuRozpocetPoZmenach>
<PocetZamestnancuRozpocetPoZmenachPrumerRocni>7386</PocetZamestnancuRozpocetPoZmenachPrumerRocni>
<PocetZamestnancuSkutecnostPrumer>1219</PocetZamestnancuSkutecnostPrumer>
</OSSJednotliveStatniSpravaPrislusniciVojaci>
<OSSJednotliveStatniSpravaOdmenovaniOdvozene>
<PocetZamestnancuRozpocetSchvaleny>6691</PocetZamestnancuRozpocetSchvaleny>
<PocetZamestnancuRozpocetPoZmenach>8443</PocetZamestnancuRozpocetPoZmenach>
<PocetZamestnancuRozpocetPoZmenachPrumerRocni>7314</PocetZamestnancuRozpocetPoZmenachPrumerRocni>
<PocetZamestnancuSkutecnostPrumer>1654</PocetZamestnancuSkutecnostPrumer>
</OSSJednotliveStatniSpravaOdmenovaniOdvozene>
<SOBCPO>
<PocetZamestnancuRozpocetSchvaleny>1176</PocetZamestnancuRozpocetSchvaleny>
<PocetZamestnancuRozpocetPoZmenach>6389</PocetZamestnancuRozpocetPoZmenach>
<PocetZamestnancuRozpocetPoZmenachPrumerRocni>1739</PocetZamestnancuRozpocetPoZmenachPrumerRocni>
<PocetZamestnancuSkutecnostPrumer>7471</PocetZamestnancuSkutecnostPrumer>
</SOBCPO>
<SOBCPOPrislusniciVojaci>
<PocetZamestnancuRozpocetSchvaleny>6021</PocetZamestnancuRozpocetSchvaleny>
<PocetZamestnancuRozpocetPoZmenach>1579</PocetZamestnancuRozpocetPoZmenach>
<PocetZamestnancuRozpocetPoZmenachPrumerRocni>1096</PocetZamestnancuRozpocetPoZmenachPrumerRocni>
<PocetZamestnancuSkutecnostPrumer>1615</PocetZamestnancuSkutecnostPrumer>
</SOBCPOPrislusniciVojaci>
<SOBCPOOdmenovaniOdvozene>
<PocetZamestnancuRozpocetSchvaleny>2280</PocetZamestnancuRozpocetSchvaleny>
<PocetZamestnancuRozpocetPoZmenach>9713</PocetZamestnancuRozpocetPoZmenach>
<PocetZamestnancuRozpocetPoZmenachPrumerRocni>1771</PocetZamestnancuRozpocetPoZmenachPrumerRocni>
<PocetZamestnancuSkutecnostPrumer>4074</PocetZamestnancuSkutecnostPrumer>
</SOBCPOOdmenovaniOdvozene>
<OSSOstatni>
<PocetZamestnancuRozpocetSchvaleny>1028</PocetZamestnancuRozpocetSchvaleny>
<PocetZamestnancuRozpocetPoZmenach>1503</PocetZamestnancuRozpocetPoZmenach>
<PocetZamestnancuRozpocetPoZmenachPrumerRocni>2024</PocetZamestnancuRozpocetPoZmenachPrumerRocni>
<PocetZamestnancuSkutecnostPrumer>1252</PocetZamestnancuSkutecnostPrumer>
</OSSOstatni>
<OSSOstatniPrislusniciVojaci>
<PocetZamestnancuRozpocetSchvaleny>1841</PocetZamestnancuRozpocetSchvaleny>
<PocetZamestnancuRozpocetPoZmenach>9996</PocetZamestnancuRozpocetPoZmenach>
<PocetZamestnancuRozpocetPoZmenachPrumerRocni>1735</PocetZamestnancuRozpocetPoZmenachPrumerRocni>
<PocetZamestnancuSkutecnostPrumer>2694</PocetZamestnancuSkutecnostPrumer>
</OSSOstatniPrislusniciVojaci>
<OSSOstatniOdmenovaniOdvozene>
<PocetZamestnancuRozpocetSchvaleny>1427</PocetZamestnancuRozpocetSchvaleny>
<PocetZamestnancuRozpocetPoZmenach>2069</PocetZamestnancuRozpocetPoZmenach>
<PocetZamestnancuRozpocetPoZmenachPrumerRocni>1248</PocetZamestnancuRozpocetPoZmenachPrumerRocni>
<PocetZamestnancuSkutecnostPrumer>2070</PocetZamestnancuSkutecnostPrumer>
</OSSOstatniOdmenovaniOdvozene>
<OrganizacePrispevkoveStatni>
<PocetZamestnancuRozpocetSchvaleny>2075</PocetZamestnancuRozpocetSchvaleny>
<PocetZamestnancuRozpocetPoZmenach>6324</PocetZamestnancuRozpocetPoZmenach>
<PocetZamestnancuRozpocetPoZmenachPrumerRocni>1346</PocetZamestnancuRozpocetPoZmenachPrumerRocni>
<PocetZamestnancuSkutecnostPrumer>1618</PocetZamestnancuSkutecnostPrumer>
</OrganizacePrispevkoveStatni>
</VykazZAM104>
</cus:MessageBody>
<cus:MessageFooter></cus:MessageFooter>
</cus:Message>
</msg:EnvelopeBody>
</msg:Envelope>
Дополнительно, SignedXmlCustomIds используется для определения местоположения элемента ID:
public class SignedXmlCustomIds : SignedXml
{
private static readonly string[] idAllowedAttrs = new string[]
{
"ID",
"Id",
"id"
};
public SignedXmlCustomIds(XmlDocument doc)
: base(doc)
{
}
public override XmlElement GetIdElement(XmlDocument doc, string id)
{
XmlElement idElem = base.GetIdElement(doc, id);
if (idElem == null)
{
foreach (string atribut in idAllowedAttrs)
{
idElem = doc.SelectSingleNode("//*[@" + atribut + "=\"" + id + "\"]") as XmlElement;
if (idElem != null)
break;
}
}
return idElem;
}
}