Как подписать XML-документ (xmldsig), добавить подпись в подписанный элемент (!) И остаться в силе (C # нормально, Java нет) - PullRequest
2 голосов
/ 01 июня 2011

Я должен подписать документ 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;
    }
} 
...