25 mayo 2009

sand.cranf.net

archivado en: Java Proyectos

Como avisé en este post, estos días tenía el glob poco activo porque andaba entretenido programando un nuevo proyecto web.

Este fin de semana lo acabé. Y tras unas pequeñas pruebas con usuarios, ya está lo bastante maduro como para hacerlo público.

Prefiero no explicar mucho. Simplemente jueguen generando paisajes con http://sand.cranf.net.

arena

PS: Si por algún motivo tenéis problemas, es que no tenéis instalada la máquina virtual de java en la versión 1.6 (también conocida como java 6 a secas).

  • RSS
  • Facebook
  • Meneame
  • Twitter
  • MySpace
  • Digg
  • del.icio.us
  • BarraPunto
  • Bitacoras.com
  • Slashdot
  • StumbleUpon
  • Technorati
  • Wikio
  • Google Bookmarks
archivado en: Java Proyectos

27 abril 2009

digital signature KeySelector

archivado en: Java

A la hora de validar una firma digital XML, encontramos que es necesario pasarle como parámetro a DOMValidateContext un KeySelector. ¿Pero qué es esto? Nada tan especial, en el fondo.

La cuestión es que para establecer la validez de la firma de un XML necesitamos por narices disponer de la clave pública del firmante… que suele venir en el propio XML empotrada de alguna manera. Java no es tan listo como para encontrar por sí mismo las claves dentro del XML que está analizando, con lo que le tenemos que ayudar. Por eso definimos una clase como extensión de KeySelector que le dice al DOMValidateContext dónde tiene que buscar. De todos modos, si no queremos hacerlo, siempre podemos buscar previamente nosotros la clave y pasársela como parámetro. Pero si podemos implementar un KeySelector, mejor.

Otras implementaciones de la misma clase presentes en internet buscan los valores del módulo y exponente de la clave pública en tags específicos del estándar de firma de XML. Esto a veces da problemas. Por ejemplo: aunque módulo y exponente se deben almacenar como ds:cryptobynary (es decir, valor binario codificado como base64) en ocasiones podemos encontrarnos patadas como el valor en ASCII pasado a base64.

Esta implementación (que se debe introducir como clase interna en nuestra clase verificadora) sin embargo busca en primer lugar dentro de una clave ds:X509 los valores de módulo y exponente escondidos dentro del certificado, y sólo si no los encuentra busca en los otros tags interiores de ds:KeyInfo. En teoría esto debería funcionar con cualquier fichero XAdES.

private static class X509KeySelector extends KeySelector {
		/**
		 * Permite al objeto DOMValidateContext (necesario en el proceso de
		 * analizar un XAdES) buscar una clave X509 dentro de un objeto KeyInfo.
		 * En otras implementaciones se busca como tags aparte. En esta, se
		 * intenta extraer del propio certificado presente en el XML ya que
		 * puede estar almacenado como crypto-ASCII en vez de como
		 * crypto-binary. {@inheritDoc}
		 *
		 * @see javax.xml.crypto.KeySelector#select(javax.xml.crypto.dsig.keyinfo
		 *      .KeyInfo, javax.xml.crypto.KeySelector.Purpose,
		 *      javax.xml.crypto.AlgorithmMethod,
		 *      javax.xml.crypto.XMLCryptoContext)
		 */
		@SuppressWarnings("unchecked")
		public KeySelectorResult select(KeyInfo keyInfo,
				KeySelector.Purpose purpose, AlgorithmMethod method,
				XMLCryptoContext context) throws KeySelectorException {
			// ya que los valores de modulus y exponent presentes en xades
			// pueden estar codificados como ASCII+base64, los saco directamente
			// del certificado adjunto
			PublicKey localkey = null;
			X509Certificate lx509 = getCertificadoDesdeKeyInfo(keyInfo);

			if (lx509 == null) {// si no encontró certificado, leemos otros
				// valores de keyInfo
				List list = keyInfo.getContent();
				for (int i = 0; i < list.size(); i++) {
					XMLStructure xmlStructure = (XMLStructure) list.get(i);
					if (xmlStructure instanceof KeyValue) {
						try {
							localkey = ((KeyValue) xmlStructure).getPublicKey();
						} catch (KeyException ke) {
							throw new KeySelectorException(ke);
						}
					}
				}
			} else {// si encontró certificado, preferimos leer de ahí
				localkey = lx509.getPublicKey();
			}

			final PublicKey key = localkey;
			// Asegurarse de que el método es compatible con el
			// algoritmo
			if (algEquals(method.getAlgorithm(), key.getAlgorithm())) {
				return new KeySelectorResult() {
					public Key getKey() {
						return key;
					}
				};
			}
			// si el algoritmo no es compatible...
			throw new KeySelectorException("Clave no encontrada");
		}

		/**
		 * Comprueba si se especifica clave RSA o DSA.
		 *
		 * @param algURI
		 * @param algName
		 * @return true en caso de encontrar cualquiera de los dos algoritmos
		 *         criptográficos especificados en el KeyInfo.
		 */
		static boolean algEquals(String algURI, String algName) {
			if ((algName.equalsIgnoreCase("DSA") && algURI
					.equalsIgnoreCase(SignatureMethod.DSA_SHA1))
					|| (algName.equalsIgnoreCase("RSA") && algURI
							.equalsIgnoreCase(SignatureMethod.RSA_SHA1))) {
				return true;
			} else {
				return false;
			}
		}
	}

	/**
	 * Devuelve el objeto X509certificate contenido dentro del KeyInfo
	 * especificado.
	 *
	 * @param pki
	 *            Instancia de KeyInfo a analizar.
	 * @return El certificado, que puede ser null.
	 */
	@SuppressWarnings("unchecked")
	private static X509Certificate getCertificadoDesdeKeyInfo(KeyInfo pki) {
		X509Data x509data = null;
		X509Certificate x509cert = null;

		// miramos si encontramos objeto x509data
		List klist = pki.getContent();
		for (int i = 0; i < klist.size(); i++) {
			XMLStructure xmlStructure = (XMLStructure) klist.get(i);
			// System.out.println(xmlStructure.getClass());
			if (xmlStructure instanceof X509Data) {
				x509data = (X509Data) xmlStructure;
			}
		}

		// miramos ahora si encontramos un certificado x509
		if (x509data != null) {
			List xlist = x509data.getContent();
			for (int i = 0; i < xlist.size(); i++) {
				Object contenido = (Object) xlist.get(i);
				// System.out.println(contenido.getClass());
				if (contenido instanceof X509Certificate) {
					x509cert = (X509Certificate) contenido;
				}
			}
		}
		return x509cert;
	}
  • RSS
  • Facebook
  • Meneame
  • Twitter
  • MySpace
  • Digg
  • del.icio.us
  • BarraPunto
  • Bitacoras.com
  • Slashdot
  • StumbleUpon
  • Technorati
  • Wikio
  • Google Bookmarks
archivado en: Java
índice   cranf.net   wordnadapress
1