1 /** 2 * LICENCIA LGPL: 3 * 4 * Esta librería es Software Libre; Usted puede redistribuirla y/o modificarla 5 * bajo los términos de la GNU Lesser General Public License (LGPL) tal y como 6 * ha sido publicada por la Free Software Foundation; o bien la versión 2.1 de 7 * la Licencia, o (a su elección) cualquier versión posterior. 8 * 9 * Esta librería se distribuye con la esperanza de que sea útil, pero SIN 10 * NINGUNA GARANTÍA; tampoco las implícitas garantías de MERCANTILIDAD o 11 * ADECUACIÓN A UN PROPÓSITO PARTICULAR. Consulte la GNU Lesser General Public 12 * License (LGPL) para más detalles 13 * 14 * Usted debe recibir una copia de la GNU Lesser General Public License (LGPL) 15 * junto con esta librería; si no es así, escriba a la Free Software Foundation 16 * Inc. 51 Franklin Street, 5º Piso, Boston, MA 02110-1301, USA o consulte 17 * <http://www.gnu.org/licenses/>. 18 * 19 * Copyright 2011 Agencia de Tecnología y Certificación Electrónica 20 */ 21 package es.accv.arangi.base.signature; 22 23 import java.io.File; 24 import java.io.FileNotFoundException; 25 import java.io.InputStream; 26 import java.net.URL; 27 import java.security.cert.X509Certificate; 28 import java.util.Arrays; 29 30 import org.apache.log4j.Logger; 31 import org.w3c.dom.Document; 32 import org.w3c.dom.NodeList; 33 34 import es.accv.arangi.base.certificate.Certificate; 35 import es.accv.arangi.base.device.DeviceManager; 36 import es.accv.arangi.base.document.FileDocument; 37 import es.accv.arangi.base.document.IDocument; 38 import es.accv.arangi.base.document.URLDocument; 39 import es.accv.arangi.base.exception.certificate.NormalizeCertificateException; 40 import es.accv.arangi.base.exception.device.LoadingObjectException; 41 import es.accv.arangi.base.exception.device.SearchingException; 42 import es.accv.arangi.base.exception.document.HashingException; 43 import es.accv.arangi.base.exception.document.InitDocumentException; 44 import es.accv.arangi.base.exception.signature.CounterSignatureException; 45 import es.accv.arangi.base.exception.signature.NoCoincidentDocumentException; 46 import es.accv.arangi.base.exception.signature.NoDocumentToSignException; 47 import es.accv.arangi.base.exception.signature.SignatureException; 48 import es.accv.arangi.base.exception.signature.SignatureNotFoundException; 49 import es.accv.arangi.base.exception.signature.XMLDocumentException; 50 import es.accv.arangi.base.mityc.ContraFirmaXML; 51 import es.accv.arangi.base.signature.util.XAdESAttachedNodeToSignObject; 52 import es.accv.arangi.base.signature.util.XAdESDataObjectFormat; 53 import es.accv.arangi.base.signature.util.XAdESAttachedSignatureOptions; 54 import es.accv.arangi.base.signature.util.XAdESDetachedSignatureOptions; 55 import es.accv.arangi.base.util.validation.ValidationResult; 56 import es.mityc.firmaJava.libreria.utilidades.UtilidadFicheros; 57 import es.mityc.firmaJava.libreria.xades.DataToSign; 58 import es.mityc.firmaJava.libreria.xades.EnumFormatoFirma; 59 import es.mityc.firmaJava.libreria.xades.ResultadoEnum; 60 import es.mityc.firmaJava.libreria.xades.ResultadoValidacion; 61 62 /** 63 * Clase que maneja firmas en formato XAdES-BES de acuerdo al estándar 64 * <a href="http://uri.etsi.org/01903/v1.3.2/ts_101903v010302p.pdf" target="etsi"> 65 * ETSI TS 101 903</a><br><br> 66 * 67 * Ejemplo de uso: <br><br> 68 * 69 * <code> 70 * KeyStoreManager manager = new KeyStoreManager (..., ...);<br> 71 * String alias = ...;<br> 72 * InputStreamDocument documentTexto = new InputStreamDocument (new FileInputStream (...));<br> 73 * InputStreamDocument documentXML = new InputStreamDocument (new FileInputStream (...));<br> 74 * File file = new File (...);<br> 75 * URL url = new URL (...);<br><br> 76 * 77 * //-- Genera una firma attached. El documento se guardará en la firma en base64<br> 78 * XAdESBESSignature signature1 = XAdESBESSignature.signAttached(manager, alias, documentTexto);<br><br> 79 * 80 * //-- Genera una firma detached que referencia al fichero en disco<br> 81 * XAdESBESSignature signature2 = XAdESBESSignature.signDetached(manager, alias, file);<br><br> 82 * 83 * //-- Genera una firma detached que referencia a "2011/04/29/certificados/CER-2584665.pdf"<br> 84 * XAdESBESSignature signature3 = XAdESBESSignature.signDetached(manager, alias, file, "2011/04/29/certificados/CER-2584665.pdf");<br><br> 85 * 86 * //-- Genera una firma detached que referencia al fichero ubicado en la URL<br> 87 * XAdESBESSignature signature4 = XAdESBESSignature.signDetached(manager, alias, url);<br><br> 88 * 89 * //-- Genera una firma attached dentro del propio documento<br> 90 * XAdESBESSignature signature5 = XAdESBESSignature.signAttached(manager, alias, documentoXML, "titulo", "documento");<br><br> 91 * </code> 92 * 93 * @author <a href="mailto:jgutierrez@accv.es">José M Gutiérrez</a> 94 */ 95 public class XAdESBESSignature extends XAdESSignature { 96 97 /* 98 * Logger de la clase 99 */ 100 static Logger logger = Logger.getLogger(XAdESBESSignature.class); 101 102 /** 103 * Tipo de la firma 104 */ 105 public static final String SIGNATURE_TYPE = "XAdES-BES"; 106 107 /* 108 * Nodos de firma 109 */ 110 protected NodeList signatureNodes; 111 112 113 //-- Constructores 114 115 /** 116 * Construye el objeto en base a un XML que tiene el formato 117 * XAdES-BES 118 * 119 * @param xmlDocument Documento XML 120 */ 121 public XAdESBESSignature(Document xmlDocument) { 122 //TODO Validar que el XML es un XAdES 123 initialize(xmlDocument); 124 } 125 126 /** 127 * Construye el objeto en base a un fichero XAdES-BES 128 * 129 * @param xmlFile Fichero XAdES-BES 130 * @throws FileNotFoundException El fichero no existe 131 * @throws XMLDocumentException El fichero no parece un XML válido 132 */ 133 public XAdESBESSignature(File xmlFile) throws FileNotFoundException, XMLDocumentException { 134 initialize(xmlFile); 135 } 136 137 /** 138 * Construye el objeto en base a un array de bytes. 139 * 140 * @param signature Firma XAdES-BES 141 * @throws XMLDocumentException El fichero no parece un XML válido 142 */ 143 public XAdESBESSignature(byte[] signature) throws XMLDocumentException { 144 initialize(signature); 145 } 146 147 /** 148 * Construye el objeto en base a un stream de lectura. 149 * 150 * @param isSignature Stream de lectura a una firma XAdES-BES 151 * @throws XMLDocumentException El fichero no parece un XML válido 152 */ 153 public XAdESBESSignature(InputStream isSignature) throws XMLDocumentException { 154 initialize(isSignature); 155 } 156 157 /** 158 * Construye el objeto en base a otro XAdES-BES 159 * 160 * @param besSignature Firma XAdES-BES 161 */ 162 protected XAdESBESSignature(XAdESBESSignature besSignature) { 163 xadesDocument = besSignature.xadesDocument; 164 } 165 166 //-- Métodos públicos 167 168 /** 169 * Realiza una firma XAdES-BES detached (el fichero no se incluirá en la firma). No completa los campos 170 * no obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier', 171 * 'signatureProductionPlace' y 'signerRole'.<br><br> 172 * 173 * La referencia a la que apuntará la firma será el path del fichero. 174 * 175 * @param manager Dispositivo criptográfico que realizará la firma 176 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 177 * @param document Fichero a firmar 178 * @return Firma XADES-BES 179 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 180 * para realizar la firma 181 * @throws SignatureException No se puede realizar la firma 182 * @throws NoDocumentToSignException El fichero a firmar no existe o es nulo 183 * @deprecated Usar {@link #signDetached(DeviceManager,String,IDocument,String,XAdESDetachedSignatureOptions) signDetached} 184 */ 185 public static XAdESBESSignature signDetached (DeviceManager manager, String alias, File document) throws LoadingObjectException, SignatureException, NoDocumentToSignException { 186 return signDetached(manager, alias, document, null, null, null); 187 188 } 189 190 /** 191 * Realiza una firma XAdES-BES detached (el fichero no se incluirá en la firma). No completa los campos 192 * no obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier' y 193 * 'signatureProductionPlace'.<br><br> 194 * 195 * La referencia a la que apuntará la firma será el path del fichero. 196 * 197 * @param manager Dispositivo criptográfico que realizará la firma 198 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 199 * @param document Fichero a firmar 200 * @param digitalSignatureAlgorithm Algoritmo de firma (si nulo algoritmo por defecto) 201 * @param dof Información para construir el tag DataObjectFormat (puede ser null) 202 * @param claimedRoles Roles de la firma (puede ser null) 203 * @return Firma XADES-BES 204 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 205 * para realizar la firma 206 * @throws SignatureException No se puede realizar la firma 207 * @throws NoDocumentToSignException El fichero a firmar no existe o es nulo 208 * @deprecated Usar {@link #signDetached(DeviceManager,String,IDocument,String,XAdESDetachedSignatureOptions) signDetached} 209 */ 210 public static XAdESBESSignature signDetached (DeviceManager manager, String alias, File document, 211 String digitalSignatureAlgorithm, XAdESDataObjectFormat dof, String[] claimedRoles) 212 throws LoadingObjectException, SignatureException, NoDocumentToSignException { 213 214 logger.debug("[XAdESBESSignature.signDetached]::Entrada::" + Arrays.asList(new Object[] { manager, alias, document, digitalSignatureAlgorithm, dof, claimedRoles })); 215 216 //-- Obtener el document de Arangi y llamar a la firma attached 217 FileDocument fileDocument; 218 try { 219 fileDocument = new FileDocument(document); 220 } catch (InitDocumentException e) { 221 logger.info("[XAdESBESSignature.signAttached]::El fichero a firmar no existe o es nulo:: " + document); 222 throw new NoDocumentToSignException("El fichero a firmar no existe o es nulo: " + document); 223 } 224 225 //-- Obtener la referencia al fichero 226 String reference = UtilidadFicheros.relativizeRute("#", document); 227 228 return signDetached(manager, alias, fileDocument, digitalSignatureAlgorithm, reference, dof, claimedRoles); 229 230 } 231 232 /** 233 * Realiza una firma XAdES-BES detached (el fichero no se incluirá en la firma). No completa los campos 234 * no obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier', 235 * 'signatureProductionPlace' y 'signerRole'.<br><br> 236 * 237 * La referencia a la que apuntará la firma será la URL del documento. 238 * 239 * @param manager Dispositivo criptográfico que realizará la firma 240 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 241 * @param urlDocument Documento a firmar. Se encuentra en una URL accesible. 242 * @return Firma XADES-BES 243 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 244 * para realizar la firma 245 * @throws SignatureException No se puede realizar la firma 246 * @throws NoDocumentToSignException La URL es nula o no existe 247 * @deprecated Usar {@link #signDetached(DeviceManager,String,IDocument,String,XAdESDetachedSignatureOptions) signDetached} 248 */ 249 public static XAdESBESSignature signDetached (DeviceManager manager, String alias, URL urlDocument) throws LoadingObjectException, SignatureException, NoDocumentToSignException { 250 return signDetached(manager, alias, urlDocument, null, null, null); 251 } 252 253 /** 254 * Realiza una firma XAdES-BES detached (el fichero no se incluirá en la firma). No completa los campos 255 * no obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier' y 256 * 'signatureProductionPlace'.<br><br> 257 * 258 * La referencia a la que apuntará la firma será la URL del documento. 259 * 260 * @param manager Dispositivo criptográfico que realizará la firma 261 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 262 * @param urlDocument Documento a firmar. Se encuentra en una URL accesible. 263 * @param digitalSignatureAlgorithm Algoritmo de firma (si nulo algoritmo por defecto) 264 * @param dof Información para construir el tag DataObjectFormat (puede ser null) 265 * @param claimedRoles Roles de la firma (puede ser null) 266 * @return Firma XADES-BES 267 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 268 * para realizar la firma 269 * @throws SignatureException No se puede realizar la firma 270 * @throws NoDocumentToSignException La URL es nula o no existe 271 * @deprecated Usar {@link #signDetached(DeviceManager,String,IDocument,String,XAdESDetachedSignatureOptions) signDetached} 272 */ 273 public static XAdESBESSignature signDetached (DeviceManager manager, String alias, URL urlDocument, 274 String digitalSignatureAlgorithm, XAdESDataObjectFormat dof, String[] claimedRoles) 275 throws LoadingObjectException, SignatureException, NoDocumentToSignException { 276 277 logger.debug("[XAdESBESSignature.signDetached]::Entrada::" + Arrays.asList(new Object[] { manager, alias, urlDocument, digitalSignatureAlgorithm, dof, claimedRoles })); 278 279 //-- Obtener el document de Arangi y llamar a la firma attached 280 URLDocument document; 281 try { 282 document = new URLDocument(urlDocument); 283 } catch (InitDocumentException e) { 284 logger.info("[XAdESBESSignature.signAttached]::La URL a firmar no existe o es nula:: " + urlDocument); 285 throw new NoDocumentToSignException("La URL a firmar no existe o es nula: " + urlDocument); 286 } 287 288 //-- Obtener la referencia al fichero 289 String reference = urlDocument.toString(); 290 291 return signDetached(manager, alias, document, digitalSignatureAlgorithm, reference, dof, claimedRoles); 292 } 293 294 /** 295 * Realiza una firma XAdES-BES detached (el fichero no se incluirá en la firma). No completa los campos 296 * no obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier', 297 * 'signatureProductionPlace' y 'signerRole'.<br><br> 298 * 299 * @param manager Dispositivo criptográfico que realizará la firma 300 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 301 * @param document Contenido a firmar 302 * @param reference Referencia a la que apuntará la firma 303 * @return Firma XADES-BES 304 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 305 * para realizar la firma 306 * @throws SignatureException No se puede realizar la firma 307 * @deprecated Usar {@link #signDetached(DeviceManager,String,IDocument,String,XAdESDetachedSignatureOptions) signDetached} 308 */ 309 public static XAdESBESSignature signDetached (DeviceManager manager, String alias, IDocument document, String reference) throws LoadingObjectException, SignatureException { 310 return signDetached(manager, alias, document, null, reference, null, null); 311 312 } 313 314 /** 315 * Realiza una firma XAdES-BES detached (el fichero no se incluirá en la firma). No completa los campos 316 * no obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier' y 317 * 'signatureProductionPlace'.<br><br> 318 * 319 * @param manager Dispositivo criptográfico que realizará la firma 320 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 321 * @param document Contenido a firmar 322 * @param digitalSignatureAlgorithm Algoritmo de firma (si nulo algoritmo por defecto) 323 * @param reference Referencia a la que apuntará la firma 324 * @param dof Información para construir el tag DataObjectFormat (puede ser null) 325 * @param claimedRoles Roles de la firma (puede ser null) 326 * @return Firma XADES-BES 327 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 328 * para realizar la firma 329 * @throws SignatureException No se puede realizar la firma 330 * @deprecated Usar {@link #signDetached(DeviceManager,String,IDocument,String,XAdESDetachedSignatureOptions) signDetached} 331 */ 332 public static XAdESBESSignature signDetached (DeviceManager manager, String alias, IDocument document, 333 String digitalSignatureAlgorithm, String reference, XAdESDataObjectFormat dof, String[] claimedRoles) 334 throws LoadingObjectException, SignatureException { 335 336 logger.debug("[XAdESBESSignature.signDetached]::Entrada::" + Arrays.asList(new Object[] { manager, alias, document, digitalSignatureAlgorithm, reference, dof, claimedRoles })); 337 338 //-- Si la referencia es nula se asigna una por defecto 339 if (reference == null) { 340 logger.debug("[XAdESBESSignature.signDetached]::Referencia nula, se asigna como #no-reference"); 341 reference = "#no-reference"; 342 } 343 344 XAdESDetachedSignatureOptions options = new XAdESDetachedSignatureOptions(digitalSignatureAlgorithm, null, dof, claimedRoles, null, null); 345 return signDetached(manager, alias, document, reference, options); 346 347 } 348 349 /** 350 * Realiza una firma XAdES-BES detached (el fichero no se incluirá en la firma). 351 * 352 * @param manager Dispositivo criptográfico que realizará la firma 353 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 354 * @param document Contenido a firmar 355 * @param reference Referencia a la que apuntará la firma 356 * @param options Opciones de la firma 357 * @return Firma XADES-BES 358 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 359 * para realizar la firma 360 * @throws SignatureException No se puede realizar la firma 361 */ 362 public static XAdESBESSignature signDetached (DeviceManager manager, String alias, IDocument document, 363 String reference, XAdESDetachedSignatureOptions options) 364 throws LoadingObjectException, SignatureException { 365 366 logger.debug("[XAdESBESSignature.signDetached]::Entrada::" + Arrays.asList(new Object[] { manager, alias, document, reference, options })); 367 368 //-- Si la referencia es nula se asigna una por defecto 369 if (reference == null) { 370 logger.debug("[XAdESBESSignature.signDetached]::Referencia nula, se asigna como #no-reference"); 371 reference = "#no-reference"; 372 } 373 374 return (XAdESBESSignature) signDetached(manager, alias, document, reference, null, null, options, EnumFormatoFirma.XAdES_BES, XAdESBESSignature.class); 375 376 } 377 378 /** 379 * Realiza una firma XAdES-BES attached (el documento se incluye en la firma). No completa los campos no 380 * obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier', 'signatureProductionPlace' 381 * y 'signerRole'. 382 * 383 * Si el documento es un XML y los parámetros <code>idToSign</code> y <code>signatureParent</code> 384 * no son nulos la firma y los campos propios de XAdES se añadirán al XML. En caso contrario el fichero 385 * XAdES resultante seguirá la plantilla de Arangí, por ejemplo:<br> 386 * <code> 387 * <arangi-xades><br> 388 * <document>...</document> 389 * <ds:Signature>...</ds:Signature> 390 * </arangi-xades><br> 391 * </code> 392 * 393 * @param manager Dispositivo criptográfico que realizará la firma 394 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 395 * @param document Documento a firmar 396 * @param idToSign Valor del atributo 'ID' que indica lo que se firmará dentro del documento. Si tiene 397 * valor nulo el XML de la firma tendrá el formato por defecto de las firmas XAdES de Arangí. 398 * @param signatureParent Nombre del tag que será el padre de los nodos de firma. Si tiene valor nulo 399 * la firma colgará del nodo raíz. 400 * @return Firma XADES-BES 401 * @throws XMLDocumentException Error montando el fichero XML 402 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 403 * para realizar la firma 404 * @throws SignatureException No se puede realizar la firma 405 * @deprecated Usar {@link #signAttached(DeviceManager,String,IDocument,XAdESAttachedSignatureOptions) signAttached} 406 */ 407 public static XAdESBESSignature signAttached (DeviceManager manager, String alias, IDocument document, String idToSign, 408 String signatureParent) throws XMLDocumentException, LoadingObjectException, SignatureException { 409 return signAttached(manager, alias, document, null, idToSign, signatureParent, null, null); 410 } 411 412 /** 413 * Realiza una firma XAdES-BES attached (el documento se incluye en la firma). No completa los campos no 414 * obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier' y 'signatureProductionPlace' 415 * 416 * Si el documento es un XML y los parámetros <code>idToSign</code> y <code>signatureParent</code> 417 * no son nulos la firma y los campos propios de XAdES se añadirán al XML. En caso contrario el fichero 418 * XAdES resultante seguirá la plantilla de Arangí, por ejemplo:<br> 419 * <code> 420 * <arangi-xades><br> 421 * <document>...</document> 422 * <ds:Signature>...</ds:Signature> 423 * </arangi-xades><br> 424 * </code> 425 * 426 * @param manager Dispositivo criptográfico que realizará la firma 427 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 428 * @param document Documento a firmar 429 * @param digitalSignatureAlgorithm Algoritmo de firma (si nulo algoritmo por defecto) 430 * @param idToSign Valor del atributo 'ID' que indica lo que se firmará dentro del documento. Si tiene 431 * valor nulo el XML de la firma tendrá el formato por defecto de las firmas XAdES de Arangí. 432 * @param signatureParent Nombre del tag que será el padre de los nodos de firma. Si tiene valor nulo 433 * la firma colgará del nodo raíz. 434 * @param dof Información para construir el tag DataObjectFormat (puede ser null) 435 * @param claimedRoles Roles de la firma (puede ser null) 436 * @return Firma XADES-BES 437 * @throws XMLDocumentException Error montando el fichero XML 438 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 439 * para realizar la firma 440 * @throws SignatureException No se puede realizar la firma 441 * @deprecated Usar {@link #signAttached(DeviceManager,String,IDocument,XAdESAttachedSignatureOptions) signAttached} 442 */ 443 public static XAdESBESSignature signAttached (DeviceManager manager, String alias, IDocument document, 444 String digitalSignatureAlgorithm, String idToSign, String signatureParent, 445 XAdESDataObjectFormat dof, String[] claimedRoles) 446 throws XMLDocumentException, LoadingObjectException, SignatureException { 447 448 logger.debug("[XAdESBESSignature.signAttached]::Entrada::" + Arrays.asList(new Object[] { manager, alias, document, digitalSignatureAlgorithm, idToSign, signatureParent, dof, claimedRoles })); 449 450 XAdESAttachedNodeToSignObject nodeToSign = null; 451 if (idToSign != null) { 452 nodeToSign = new XAdESAttachedNodeToSignObject(idToSign); 453 } 454 XAdESAttachedSignatureOptions options = new XAdESAttachedSignatureOptions(digitalSignatureAlgorithm, null, dof, claimedRoles, null, null, nodeToSign, signatureParent); 455 return signAttached(manager, alias, document, options); 456 } 457 458 /** 459 * Realiza una firma XAdES-BES attached (el documento se incluye en la firma). No completa los campos no 460 * obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier', 'signatureProductionPlace' 461 * y 'signerRole'.<br><br> 462 * 463 * El fichero XAdES seguirá la plantilla de Arangí. Ejemplo:<br> 464 * <code> 465 * <arangi-xades><br> 466 * <document>...</document> 467 * <ds:Signature>...</ds:Signature> 468 * </arangi-xades><br> 469 * </code> 470 * 471 * @param manager Dispositivo criptográfico que realizará la firma 472 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 473 * @param document Documento a firmar 474 * @return Firma XADES-BES 475 * @throws XMLDocumentException Error montando el fichero XML 476 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 477 * para realizar la firma 478 * @throws SignatureException No se puede realizar la firma 479 * @deprecated Usar {@link #signAttached(DeviceManager,String,IDocument,XAdESAttachedSignatureOptions) signAttached} 480 */ 481 public static XAdESBESSignature signAttached (DeviceManager manager, String alias, IDocument document) throws XMLDocumentException, LoadingObjectException, SignatureException { 482 return signAttached(manager, alias, document, (String)null, null); 483 } 484 485 /** 486 * Realiza una firma XAdES-BES attached (el documento se incluye en la firma). No completa los campos no 487 * obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier' y 'signatureProductionPlace' 488 * <br><br> 489 * 490 * El fichero XAdES seguirá la plantilla de Arangí. Ejemplo:<br> 491 * <code> 492 * <arangi-xades><br> 493 * <document>...</document> 494 * <ds:Signature>...</ds:Signature> 495 * </arangi-xades><br> 496 * </code> 497 * 498 * @param manager Dispositivo criptográfico que realizará la firma 499 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 500 * @param document Documento a firmar 501 * @param digitalSignatureAlgorithm Algoritmo de firma (si nulo algoritmo por defecto) 502 * @param dof Información para construir el tag DataObjectFormat (puede ser null) 503 * @param claimedRoles Roles de la firma (puede ser null) 504 * @return Firma XADES-BES 505 * @throws XMLDocumentException Error montando el fichero XML 506 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 507 * para realizar la firma 508 * @throws SignatureException No se puede realizar la firma 509 * @deprecated Usar {@link #signAttached(DeviceManager,String,IDocument,XAdESAttachedSignatureOptions) signAttached} 510 */ 511 public static XAdESBESSignature signAttached (DeviceManager manager, String alias, IDocument document, 512 String digitalSignatureAlgorithm, XAdESDataObjectFormat dof, String[] claimedRoles) 513 throws XMLDocumentException, LoadingObjectException, SignatureException { 514 515 logger.debug("[XAdESBESSignature.signAttached]::Entrada::" + Arrays.asList(new Object[] { manager, alias, document, dof, claimedRoles })); 516 517 XAdESAttachedSignatureOptions options = new XAdESAttachedSignatureOptions(digitalSignatureAlgorithm, null, dof, claimedRoles, null, null, null, null); 518 return signAttached(manager, alias, document, options); 519 } 520 521 /** 522 * Realiza una firma XAdES-BES attached (el fichero se incluirá en la firma). No completa los campos 523 * no obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier', 524 * 'signatureProductionPlace' y 'signerRole'.<br><br> 525 * 526 * @param manager Dispositivo criptográfico que realizará la firma 527 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 528 * @param document Fichero a firmar 529 * @return Firma XADES-BES 530 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 531 * para realizar la firma 532 * @throws SignatureException No se puede realizar la firma 533 * @throws NoDocumentToSignException El fichero a firmar no existe o es nulo 534 * @throws XMLDocumentException Error montando el fichero XML 535 * @deprecated Usar {@link #signAttached(DeviceManager,String,IDocument,XAdESAttachedSignatureOptions) signAttached} 536 */ 537 public static XAdESBESSignature signAttached (DeviceManager manager, String alias, File document) throws LoadingObjectException, SignatureException, NoDocumentToSignException, XMLDocumentException { 538 return signAttached(manager, alias, document, null, null, null); 539 } 540 541 /** 542 * Realiza una firma XAdES-BES attached (el fichero se incluirá en la firma). No completa los campos 543 * no obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier' y 544 * 'signatureProductionPlace'.<br><br> 545 * 546 * @param manager Dispositivo criptográfico que realizará la firma 547 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 548 * @param document Fichero a firmar 549 * @param digitalSignatureAlgorithm Algoritmo de firma (si nulo algoritmo por defecto) 550 * @param dof Información para construir el tag DataObjectFormat (puede ser null) 551 * @param claimedRoles Roles de la firma (puede ser null) 552 * @return Firma XADES-BES 553 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 554 * para realizar la firma 555 * @throws SignatureException No se puede realizar la firma 556 * @throws NoDocumentToSignException El fichero a firmar no existe o es nulo 557 * @throws XMLDocumentException Error montando el fichero XML 558 * @deprecated Usar {@link #signAttached(DeviceManager,String,IDocument,XAdESAttachedSignatureOptions) signAttached} 559 */ 560 public static XAdESBESSignature signAttached (DeviceManager manager, String alias, File document, 561 String digitalSignatureAlgorithm, XAdESDataObjectFormat dof, String[] claimedRoles) throws LoadingObjectException, SignatureException, NoDocumentToSignException, XMLDocumentException { 562 563 logger.debug("[XAdESBESSignature.signAttached]::Entrada::" + Arrays.asList(new Object[] { manager, alias, document, digitalSignatureAlgorithm, dof, claimedRoles })); 564 565 //-- Obtener el document de Arangi y llamar a la firma attached 566 FileDocument fileDocument; 567 try { 568 fileDocument = new FileDocument(document); 569 } catch (InitDocumentException e) { 570 logger.info("[XAdESBESSignature.signAttached]::El fichero a firmar no existe o es nulo:: " + document); 571 throw new NoDocumentToSignException("El fichero a firmar no existe o es nulo: " + document); 572 } 573 574 return signAttached(manager, alias, fileDocument, digitalSignatureAlgorithm, dof, claimedRoles); 575 576 } 577 578 /** 579 * Realiza una firma XAdES-BES attached (el fichero se incluirá en la firma). No completa los campos 580 * no obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier', 581 * 'signatureProductionPlace' y 'signerRole'.<br><br> 582 * 583 * @param manager Dispositivo criptográfico que realizará la firma 584 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 585 * @param document Documento a firmar. Se encuentra en una URL accesible. 586 * @return Firma XADES-BES 587 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 588 * para realizar la firma 589 * @throws SignatureException No se puede realizar la firma 590 * @throws NoDocumentToSignException El fichero a firmar no existe o es nulo 591 * @throws XMLDocumentException Error montando el fichero XML 592 * @deprecated Usar {@link #signAttached(DeviceManager,String,IDocument,XAdESAttachedSignatureOptions) signAttached} 593 */ 594 public static XAdESBESSignature signAttached (DeviceManager manager, String alias, URL document) throws LoadingObjectException, SignatureException, NoDocumentToSignException, XMLDocumentException { 595 return signAttached(manager, alias, document, null, null, null); 596 597 } 598 599 /** 600 * Realiza una firma XAdES-BES attached (el fichero se incluirá en la firma). No completa los campos 601 * no obligatorios del tag 'SignedSignatureProperties':'signaturePolicyIdentifier' y 602 * 'signatureProductionPlace'.<br><br> 603 * 604 * @param manager Dispositivo criptográfico que realizará la firma 605 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 606 * @param document Documento a firmar. Se encuentra en una URL accesible. 607 * @param digitalSignatureAlgorithm Algoritmo de firma (si nulo algoritmo por defecto) 608 * @param dof Información para construir el tag DataObjectFormat (puede ser null) 609 * @param claimedRoles Roles de la firma (puede ser null) 610 * @return Firma XADES-BES 611 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 612 * para realizar la firma 613 * @throws SignatureException No se puede realizar la firma 614 * @throws NoDocumentToSignException El fichero a firmar no existe o es nulo 615 * @throws XMLDocumentException Error montando el fichero XML 616 * @deprecated Usar {@link #signAttached(DeviceManager,String,IDocument,XAdESAttachedSignatureOptions) signAttached} 617 */ 618 public static XAdESBESSignature signAttached (DeviceManager manager, String alias, URL document, 619 String digitalSignatureAlgorithm, XAdESDataObjectFormat dof, String[] claimedRoles) 620 throws LoadingObjectException, SignatureException, NoDocumentToSignException, XMLDocumentException { 621 622 logger.debug("[XAdESBESSignature.signAttached]::Entrada::" + Arrays.asList(new Object[] { manager, alias, document, digitalSignatureAlgorithm, dof, claimedRoles })); 623 624 //-- Obtener el document de Arangi y llamar a la firma attached 625 URLDocument urlDocument; 626 try { 627 urlDocument = new URLDocument(document); 628 } catch (InitDocumentException e) { 629 logger.info("[XAdESBESSignature.signAttached]::La URL a firmar no existe o es nula:: " + document); 630 throw new NoDocumentToSignException("La URL a firmar no existe o es nula: " + document); 631 } 632 633 return signAttached(manager, alias, urlDocument, digitalSignatureAlgorithm, dof, claimedRoles); 634 635 } 636 637 /** 638 * Realiza una firma XAdES-BES attached (el documento se incluye en la firma). 639 * 640 * @param manager Dispositivo criptográfico que realizará la firma 641 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 642 * @param document Documento a firmar 643 * @param options Opciones para la firma 644 * @return Firma XADES-BES 645 * @throws XMLDocumentException Error montando el fichero XML 646 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 647 * para realizar la firma 648 * @throws SignatureException No se puede realizar la firma 649 */ 650 public static XAdESBESSignature signAttached (DeviceManager manager, String alias, IDocument document, 651 XAdESAttachedSignatureOptions options) throws XMLDocumentException, LoadingObjectException, SignatureException { 652 653 logger.debug("[XAdESBESSignature.signAttached]::Entrada::" + Arrays.asList(new Object[] { manager, alias, document, options })); 654 655 return (XAdESBESSignature) signAttached(manager, alias, document, null, null, options, EnumFormatoFirma.XAdES_BES, XAdESBESSignature.class); 656 } 657 658 /** 659 * La definición de las contrafirmas en XAdES puede observarse en el punto 7.2.4 660 * del estándar de la ETSI.<br><br> 661 * 662 * Este método realiza una contrafirma para la última firma del XAdES. Es útil 663 * cuando se sabe que el XAdES contiene sólo una firma.<br><br> 664 * 665 * Como resultado el XAdES a la que hace referencia este objeto se modificará 666 * para añadir la contrafirma. 667 * 668 * @param manager Dispositivo criptográfico que realizará la contrafirma 669 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 670 * @throws LoadingObjectException No es posible obtener la clave privada o el 671 * certificado del alias 672 * @throws CounterSignatureException Errores durante el proceso de contrafirma 673 */ 674 public void counterSign (DeviceManager manager, String alias) throws LoadingObjectException, CounterSignatureException { 675 counterSign(manager, alias, null, null); 676 } 677 678 /** 679 * La definición de las contrafirmas en XAdES puede observarse en el punto 7.2.4 680 * del estándar de la ETSI.<br><br> 681 * 682 * Este método realiza una contrafirma para la firma cuyo certificado se pasa 683 * en el parámetro 'signatureToCounterSignCertificate'. Es útil cuando se quiere 684 * contrafirmar un XAdES que contiene varias firmas. Para saber qué firma se 685 * desea contrafirmar se puede llamar primero a 686 * {@link #getCertificates() getCertificates} para ver los certificados de cada 687 * una de las firmas que contiene el XAdES.<br><br> 688 * 689 * Como resultado el XAdES a la que hace referencia este objeto se modificará 690 * para añadir la contrafirma. 691 * 692 * @param manager Dispositivo criptográfico que realizará la contrafirma 693 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 694 * @param signatureToCounterSignCertificate Certificado de la firma que se 695 * contrafirmará 696 * @param digitalSignatureAlgorithm Algoritmo de firma (si nulo algoritmo por defecto) 697 * @throws LoadingObjectException No es posible obtener la clave privada o el 698 * certificado del alias 699 * @throws CounterSignatureException Errores durante el proceso de contrafirma 700 */ 701 public void counterSign (DeviceManager manager, String alias, Certificate signatureToCounterSignCertificate, 702 String digitalSignatureAlgorithm) throws LoadingObjectException, CounterSignatureException { 703 704 logger.debug("[XAdESBESSignature.counterSign]::Entrada::" + Arrays.asList(new Object[] { manager, alias })); 705 706 //-- El documento a firmar es la firma en la que nos encontramos 707 DataToSign dataToSign = new DataToSign(); 708 dataToSign.setXadesFormat(getXAdESSignatureFormat()); 709 dataToSign.setEsquema(DEFAULT_XADES_SCHEMA); 710 dataToSign.setXMLEncoding(DEFAULT_XML_ENCODING); 711 dataToSign.setEnveloped(true); 712 dataToSign.setDocument(this.xadesDocument); 713 714 Document doc; 715 try { 716 doc = ContraFirmaXML.counterSign(manager.getCertificate(alias), dataToSign, 717 signatureToCounterSignCertificate!=null?signatureToCounterSignCertificate.toX509Certificate():null, 718 manager.getPrivateKey(alias), digitalSignatureAlgorithm, null, DEFAULT_XADES_SCHEMA_URI); 719 } catch (LoadingObjectException e) { 720 logger.info("[XAdESBESSignature.counterSign]::No es posible obtener la clave privada del alias '" + alias + "'", e); 721 throw e; 722 } catch (SearchingException e) { 723 logger.info("[XAdESBESSignature.counterSign]::No es posible obtener el certificado del alias '" + alias + "'", e); 724 throw new LoadingObjectException ("No es posible obtener el certificado del alias '" + alias + "'", e); 725 } catch (CounterSignatureException e) { 726 logger.info("[XAdESBESSignature.counterSign]::No es posible realizar la contrafirma", e); 727 throw e; 728 } 729 730 logger.debug("[XAdESBESSignature.counterSign]::Se ha obtenido la contrafirma"); 731 this.xadesDocument = doc; 732 } 733 734 /** 735 * Añade una Cofirma a la firma XAdES-BES. Realizará una firma de las mismas características que 736 * la primera que encuentre (attached o dettached).<br><br> 737 * 738 * Si la firma es dettached i la referencia al documento que hay en la firma 739 * no es una URL será necesario usar el método {@link #coSign(DeviceManager, String, IDocument)} 740 * al que le proporcionaremos este documento. 741 * 742 * @param manager Dispositivo criptográfico que realizará la cofirma 743 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 744 * @throws SignatureNotFoundException No existe ninguna firma que cofirmar 745 * @throws NoDocumentToSignException El fichero a firmar no existe o es nulo 746 * @throws HashingException Error realizando el hash del documento 747 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 748 * para realizar la firma 749 * @throws SignatureException No ha sido posible parsear la firma XAdES o no se puede realizar la cofirma 750 * @throws NoCoincidentDocumentException El documento que se quiere firmar no se corresponde con el de 751 * la firma XAdES 752 */ 753 public void coSign (DeviceManager manager, String alias) throws SignatureNotFoundException, NoDocumentToSignException, HashingException, LoadingObjectException, SignatureException, NoCoincidentDocumentException{ 754 755 logger.debug("[XAdESBESSignature.coSign]::Entrada::" + Arrays.asList(new Object[] { manager, alias })); 756 coSign (manager, alias, null, null); 757 } 758 759 760 /** 761 * Añade una Cofirma a la firma XAdES-BES. Realizará una firma de las mismas características que 762 * la primera que encuentre (attached o dettached).<br><br> 763 * 764 * Este método es útil si la firma es dettached i la referencia al documento que hay en la firma no 765 * es una URL. 766 * 767 * @param manager Dispositivo criptográfico que realizará la cofirma 768 * @param alias Alias donde se encuentra la clave privada dentro del dispositivo 769 * @param signedDoc contenido a firmar. El mismo utilizado en la generación de las otras firmas. 770 * @param digitalSignatureAlgorithm Algoritmo de firma (si nulo algoritmo por defecto) 771 * @throws SignatureNotFoundException No existe ninguna firma que cofirmar 772 * @throws NoDocumentToSignException El fichero a firmar no existe o es nulo 773 * @throws HashingException Error realizando el hash del documento 774 * @throws LoadingObjectException No ha sido posible cargar la clave privada o el certificado usados 775 * para realizar la firma 776 * @throws SignatureException No ha sido posible parsear la firma XAdES o no se puede realizar la cofirma 777 * @throws NoCoincidentDocumentException El documento que se quiere firmar no se corresponde con el de 778 * la firma XAdES 779 */ 780 public void coSign (DeviceManager manager, String alias, IDocument signedDoc, String digitalSignatureAlgorithm) 781 throws SignatureNotFoundException, NoDocumentToSignException, HashingException, 782 LoadingObjectException, SignatureException, NoCoincidentDocumentException { 783 784 coSign(manager, alias, signedDoc, digitalSignatureAlgorithm, null, null, EnumFormatoFirma.XAdES_BES, XAdESBESSignature.class); 785 786 } 787 788 /** 789 * Devuelve una cadena de texto con el tipo de la firma 790 * 791 * @return Cadena de texto con el tipo de la firma 792 */ 793 public String getSignatureType () { 794 return SIGNATURE_TYPE; 795 } 796 797 //-- Implementación de XAdESSignature 798 799 @Override 800 protected int tratarResultadoValidacion(ResultadoValidacion resultadoValidacion) { 801 if (resultadoValidacion.isValidate()) { 802 if (resultadoValidacion.getLog().equalsIgnoreCase("Se aconseja validar el estado del certificado firmante")) { 803 //-- Comprobar la validez de los certificados 804 X509Certificate x509Certificate = (X509Certificate) resultadoValidacion.getDatosFirma().getCadenaFirma().getCertificates().get(0); 805 Certificate certificate = null; 806 try { 807 certificate = new Certificate (x509Certificate); 808 } catch (NormalizeCertificateException e) { 809 logger.debug("[XAdESBESSignature.tratarResultadoValidacion]::El certificado no ha podido ser normalizado: \n" + x509Certificate, e); 810 } 811 if (certificate == null || !certificate.isActive()) { 812 logger.debug("[XAdESBESSignature.tratarResultadoValidacion]::El certificado está caducado"); 813 return ValidationResult.RESULT_CERTIFICATE_NOT_ACTIVE; 814 } 815 logger.debug("[XAdESBESSignature.tratarResultadoValidacion]::La firma ha pasado la validación"); 816 return ValidationResult.RESULT_VALID; 817 } else { 818 //válido 819 logger.debug("[XAdESBESSignature.tratarResultadoValidacion]::La firma ha pasado la validación"); 820 return ValidationResult.RESULT_VALID; 821 } 822 } else if (resultadoValidacion.getNivelValido() == null || resultadoValidacion.getNivelValido().equals("")) { 823 if (resultadoValidacion.getLog().toLowerCase().indexOf("firma inválida") > -1) { 824 //certificado válido, el problema será con la firma 825 logger.debug("[XAdESBESSignature.tratarResultadoValidacion]::La firma no es válida"); 826 return ValidationResult.RESULT_SIGNATURE_NOT_MATCH_DATA; 827 } else { 828 //certificado caducado 829 logger.debug("[XAdESBESSignature.tratarResultadoValidacion]::El certificado está caducado"); 830 return ValidationResult.RESULT_CERTIFICATE_NOT_ACTIVE; 831 } 832 } else if (resultadoValidacion.getResultado() == ResultadoEnum.INVALID) { 833 if (resultadoValidacion.getLog() != null && resultadoValidacion.getLog().indexOf("El certificado firmante ha caducado") > -1) { 834 //certificado caducado 835 logger.debug("[XAdESBESSignature.tratarResultadoValidacion]::El certificado está caducado"); 836 return ValidationResult.RESULT_CERTIFICATE_NOT_ACTIVE; 837 } else { 838 //revocado 839 logger.debug("[XAdESBESSignature.tratarResultadoValidacion]::El certificado de la firma está revocado"); 840 return ValidationResult.RESULT_CERTIFICATE_REVOKED; 841 } 842 } else { 843 //desconocido 844 logger.debug("[XAdESBESSignature.tratarResultadoValidacion]::La firma no ha pasado la validación"); 845 return ValidationResult.RESULT_CERTIFICATE_UNKNOWN; 846 } 847 } 848 849 /** 850 * Formato de firma: XAdES-BES 851 */ 852 protected EnumFormatoFirma getXAdESSignatureFormat () { 853 return EnumFormatoFirma.XAdES_BES; 854 } 855 856 //-- Métodos privados 857 858 859 }