我需要读取从java签名的XML中的值

时间:2015-02-13 21:50:48

标签: dom digital-signature

我有一个签名的XML文档,我可以验证签名,我感兴趣的是获取某些工作字段:

<?xml version="1.0" encoding="UTF-8"?>
<inicio>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#1500-Fri Jan 30 19:11:38 BOT 2015">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>YOzKDc7CB3QvedYMF2ZBB6omlsg=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
DLZKHySIMKwFuB1wc8cR7w/UbLhYyZtul/ndFch1GCeiKrmohyNOGO82Hbcm+rFEWxK1yMx2sKtM
KnuPTTCnIiZaYCLax5UJUe27AVqzpHZOc7+UKBmQoOOi3gYfAuyCZX5xBv0lrFNuigoNv6b0Z00B
u5Eu5e2zf01zceUqig40Y3yWUpEVRl+nbEUmVEBT+8fFwcigIQhqMbwFftGO8mcu55VKbGmMZS7c
pwzfq+PsTrnDDHbZ9cme/8p3lWo8TGTEDTcQ2HZoSI5VAPR2/fGDGKtS5PEG0Vbb0WFdVZ+PKuOA
hXqiP947xi6PP6Qv1bCbUqwsNLwTfuTjNR9lGg==
</ds:SignatureValue>
<ds:KeyInfo>
<ds:KeyName>50</ds:KeyName>
</ds:KeyInfo>
<ds:Object Id="1500-Fri Jan 30 19:11:38 BOT 2015">
  <DATOS>
    <num_orden>49</num_orden>
    <cod_alfanumerico>HJYafrtr3456ABDFG</cod_alfanumerico>
    <cod_pais>BO</cod_pais>
  </DATOS></ds:Object>
</ds:Signature>
  <Otros>TAG que no debe estar firmado</Otros>
</inicio>

我试图获取标签内的字段&lt; DATOS&gt;和此标记中包含的节点,但没有成功。 在java中,我可以验证签名,但是我无法访问XML标记以找到我需要使用的DOM和JDOM。

try{
            if (doc == null){
                doc = createFromString(IOUtils.toString(in));
                LOG.info("Documento creado\n{}", documentToString(doc));
            }
            LOG.info("documento a verificar\n{}", documentToString(doc));

            URL url = getClass().getResource("/repositorio.jks");
            KeyStore ks = KeyStore.getInstance("JKS");
            ks.load(url.openStream(), claveRepositorio.toCharArray());

            Certificate cer = ks.getCertificate("pruebas.certificado");

            Map<String, Certificate> pubring = new HashMap<String, Certificate>();

            pubring.put("50", cer);
            pubring.put("09", cer);

            NodeList signatures = doc.getElementsByTagNameNS(Constants.SignatureSpecNS, "Signature");
            if (signatures.getLength() < 1) {
            LOG.error("This message does not contain any signature");
            return;
            }

            signatures.getLength());

            for (int i = 0; i < signatures.getLength(); i++) {
                Element sigElement = (Element) signatures.item(i);
                OutputStream out = new WriterOutputStream();
                XMLUtils.ElementToStream(sigElement, out);
                LOG.info("Part of the signature to verify\n{}", out);

                XMLSignature signature = new XMLSignature(sigElement, "");
                String keyName = signature.getKeyInfo().itemKeyName(0).getKeyName();
                Certificate certificado = pubring.get(keyName);
                if (certificado == null) {
                    String msg = "I do not have the public certificate signer...";
                    LOG.error(msg);
                    fail(msg);
                    return;
                }

                PublicKey pk = certificado.getPublicKey();
                X509Certificate x509 = X509Certificate.getInstance(cer.getEncoded());
                Date notBefore = x509.getNotBefore();
                Date notAfter = x509.getNotAfter();

                LOG.debug("certificate '{}' valid from '{}' to '{}'",
                    new Object[] { keyName, sdf.format(notBefore), sdf.format(notAfter) });

                try {
                    x509.checkValidity();
                } catch (CertificateNotYetValidException e) {
                    String msg = "Participant Certificate '" + keyName + "' not valid";
                    LOG.error(msg, e);
                    fail(msg);
                    return;
                } catch (CertificateExpiredException e) {
                    String msg = "Participant Certificate '" + keyName + "' has expired";
                    LOG.error(msg, e);
                    fail(msg);
                    return;
                }

                valid &= signature.checkSignatureValue(pk);
            }

            if (valid) {
            LOG.info("Digital signature validates!!");
            return;
            } else {
            String msg = "Digital Signature INVALID!!";
            LOG.info(msg);
            fail(msg);
            }

        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            fail("Failed to verify the signature");
        } finally {
            IOUtils.closeQuietly(in);
        }
        LOG.error("The message contains an invalid signature");

非常感谢任何帮助。

非常感谢提前。

2 个答案:

答案 0 :(得分:0)

我只添加了一些代码来修改for循环签名元素的语句,请参阅DATOS被引用的部分。

          for (int i = 0; i < signatures.getLength(); i++) {
            Element sigElement = (Element) signatures.item(i);

            if(sigElement.tagName.equals("Object"))
            {
              Element  datos = sigElement.getElementsByTagName("DATOS")[0];
              Element  num_ordenElm =  datos.getElementsByTagName("num_orden")[0];
              Element  cod_alfanumericoElm =  datos.getElementsByTagName("cod_alfanumerico")[0];
              Element  cod_paisElm =  datos.getElementsByTagName("cod_pais")[0];
              String  num_ordenElm     =  num_ordenElm.textContent;
              String  cod_alfanumerico    cod_alfanumericoElm.textContent;
              String  cod_paisElm      =  cod_paisElm.textContent;
            }


            OutputStream out = new WriterOutputStream();
            XMLUtils.ElementToStream(sigElement, out);
            LOG.info("Part of the signature to verify\n{}", out);

            XMLSignature signature = new XMLSignature(sigElement, "");
            String keyName = signature.getKeyInfo().itemKeyName(0).getKeyName();
            Certificate certificado = pubring.get(keyName);
            if (certificado == null) {
                String msg = "I do not have the public certificate signer...";
                LOG.error(msg);
                fail(msg);
                return;
            }

答案 1 :(得分:0)

将问题分为两部分,第一个有效签名,第二个读取值需要: 下面显示了用于读取xml的代码:

DocumentBuilder db =DocumentBuilderFactory.newInstance().newDocumentBuilder();

InputSource is = new InputSource();

is.setCharacterStream(new StringReader(XMLRecord)); 
Document doc = db.parse(is);
NodeList nodes = doc.getElementsByTagName("ds:Signature");  
String num_orden=null;    
for (int i = 0; i < nodes.getLength(); i++) {
     Element element = (Element) nodes.item(i);
     NodeList nume = element.getElementsByTagName("num_orden");
     Element line = (Element) nume.item(0);
     num_orden =element.getElementsByTagName("num_orden").item(0).getTextContent();
     System.out.println("Nume: " + getCharacterDataFromElement(line));

     NodeList codi = element.getElementsByTagName("cod_alfanumerico");
     line = (Element) codi.item(0);
     System.out.println("cod_alfanumerico: " + getCharacterDataFromElement(line));

     NodeList pais = element.getElementsByTagName("cod_pais");
     line = (Element) pais.item(0);
     System.out.println("Pais: " + getCharacterDataFromElement(line));
     }System.out.println(" El numero de cuenta es "+num_orden);



public static String getCharacterDataFromElement(Element e) {
    Node child = e.getFirstChild();
    if (child instanceof CharacterData) {
      CharacterData cd = (CharacterData) child;
      return cd.getData();
    }
    return "";
  }