/**
   * Recupera los signedInfo de una firma XML, excluyendo los de las firmas indicadas a
   * través de su Id.
   *
   * @param xmlSign XML del que se
   * @param pk Clave publicada usada en las firmas de las que se desea obtener los signedInfo.
   * @param excludedIds Identificadores de las firmas excluidas.
   * @return Listado de signedInfos.
   * @throws SAXException Si hay problemas durante el análisis XML.
   * @throws IOException Si hay problemas en el tratamiento de datos.
   * @throws ParserConfigurationException Si hay problemas con el analizador por defecto para XML.
   * @throws MarshalException Si hay problemas con el empaquetado XML.
   * @throws XMLSignatureException Si hay problemas en la propia firma XMLDSig.
   * @throws XmlPreSignException Cuando no se ha encontrado ningún signedInfo que devolver.
   */
  private static List<byte[]> getSignedInfos(
      final byte[] xmlSign, final PublicKey pk, final List<String> excludedIds)
      throws SAXException, IOException, ParserConfigurationException, MarshalException,
          XMLSignatureException, XmlPreSignException {
    final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);

    final NodeList signatureNodeList =
        dbf.newDocumentBuilder()
            .parse(new ByteArrayInputStream(xmlSign))
            .getElementsByTagNameNS(XMLSignature.XMLNS, AOXAdESSigner.SIGNATURE_TAG);
    if (signatureNodeList.getLength() == 0) {
      throw new IllegalArgumentException("Se ha proporcionado un XML sin firmas"); // $NON-NLS-1$
    }

    // Recogemos el signedInfo de cada firma cuyo identificador no este en la lista de excluidos
    // (excludedIds)
    final List<byte[]> signedInfos = new ArrayList<byte[]>();
    for (int i = 0; i < signatureNodeList.getLength(); i++) {

      final Node currentNode = signatureNodeList.item(i);

      // Saltamos las firmas sin identificador
      if (currentNode.getAttributes() == null
          || currentNode.getAttributes().getNamedItem(XML_NODE_ID) == null) {
        Logger.getLogger("es.gob.afirma")
            .warning(
                "El documento contiene firmas sin identificador reconocido"); //$NON-NLS-1$//$NON-NLS-2$
        continue;
      }

      // Saltamos las firmas excluidas (las que estaban antes)
      final String id = currentNode.getAttributes().getNamedItem(XML_NODE_ID).getNodeValue();
      if (excludedIds != null && excludedIds.contains(id)) {
        continue;
      }

      // Agregamos el signed indo de la firma al listado
      final XMLValidateContext valContext =
          new DOMValidateContext(new SimpleKeySelector(pk), currentNode);
      valContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE); // $NON-NLS-1$
      final XMLSignature signature = Utils.getDOMFactory().unmarshalXMLSignature(valContext);
      signature.validate(valContext);
      signedInfos.add(
          AOUtil.getDataFromInputStream(signature.getSignedInfo().getCanonicalizedData()));
    }

    if (signedInfos.isEmpty()) {
      throw new XmlPreSignException(
          "Se ha creado un nodo firma, pero no se ha encontrado en el postproceso"); //$NON-NLS-1$
    }

    return signedInfos;
  }
Esempio n. 2
0
  /**
   * Validate a signed document with the given public key
   *
   * @param signedDoc
   * @param publicKey
   * @return
   * @throws MarshalException
   * @throws XMLSignatureException
   */
  @SuppressWarnings("unchecked")
  public static boolean validate(Document signedDoc, Key publicKey)
      throws MarshalException, XMLSignatureException {
    if (signedDoc == null) throw logger.nullArgumentError("Signed Document");

    propagateIDAttributeSetup(signedDoc.getDocumentElement(), signedDoc.getDocumentElement());

    NodeList nl = signedDoc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");

    if (nl == null || nl.getLength() == 0) {
      throw logger.nullValueError("Cannot find Signature element");
    }

    if (publicKey == null) throw logger.nullValueError("Public Key");

    for (int i = 0; i < nl.getLength(); i++) {
      DOMValidateContext valContext = new DOMValidateContext(publicKey, nl.item(i));
      XMLSignature signature = fac.unmarshalXMLSignature(valContext);

      boolean coreValidity = signature.validate(valContext);

      if (!coreValidity) {
        if (logger.isTraceEnabled()) {
          boolean sv = signature.getSignatureValue().validate(valContext);
          logger.trace("Signature validation status: " + sv);

          List<Reference> references = signature.getSignedInfo().getReferences();
          for (Reference ref : references) {
            logger.trace(
                "[Ref id="
                    + ref.getId()
                    + ":uri="
                    + ref.getURI()
                    + "]validity status:"
                    + ref.validate(valContext));
          }
        }

        return false;
      }
    }

    return true;
  }