Firmando Código

En un par de entradas voy a abordar cómo crear y desplegar una aplicación con tecnología Java Web Start con la especificación JNLP (Java Network Launching Protocol).
La idea, a grandes rasgos, es crear una aplicación, un jar normal y corriente, enlazarla en la web para que se ejecute de forma local. La aplicación será cacheada en la máquina, pudiendo crear un enlace o un acceso directo y que cuando se ejecute compruebe si es la última versión, si no lo es se bajará la última versión y todo ello dentro de un contexto de seguridad.
El contexto de seguridad es que la aplicación "jnlp" se ejecutará en una sandbox si proviene de una fuente desconocida, esto es, no podrá acceder a los recursos de la máquina, por ejemplo escribir un archivo. En ese caso utilizar la tecnología Java Web Start puede no ser ni la mejor ni la más rápida opción.
La forma de que una aplicación java sea de fuente no desconocida es hacer que sea comprobable su autoria, para lo cual es preciso firmar el código ,y como no podía ser de otra manera en este blog, utilizaré un plugin de maven que nos hace ese trabajo.
VAmos al tajo:
Crearemos una aplicación "Hello World" con Maven, tal y como viene en esta entrada, y tunaremos el main para que haga algo un poco más complejo, volcar las propiedades del sistema en un archivo "xml" y a un archivo properties.
El main quedará algo como esto:

public static void main(String[] args) {
        String path= System.getProperty("user.home");
        Properties propis = System.getProperties();
        FileOutputStream outputStream;
        FileOutputStream outputStreamDos;
        try {
            outputStream = new FileOutputStream(path+"\\webstart.xml");
            outputStreamDos = new FileOutputStream(path+"\\webstart.properties");
            propis.store(outputStreamDos, "propiedades a properties");
            propis.storeToXML(outputStream, "propiedades a xml");           
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

El código no tiene nada de especial, salvo la opción simpática de escribir en la carpeta del usuario y así asegurarnos que se tendrá permisos de escritura y que el path existe. No tengo claro que esto funcione en versiones inferiores de java 1.5, pero me da pereza instalar una mvj 1.4 para probar. Los parseadores integrados de xml creo que existen desde la 1.5.
En la entrada anterior ya vimos como crear el jar indicando cual es la clase de entrada, la que contiene el main.

<plugin>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.3.1</version>
                <executions>
                    <execution>
                        <id>default-jar</id>
                        <phase>package</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>es.home.App</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>

 Esto nos permitirá crear un jar razonablemente correcto. Para hacerlo válido para una aplicación jnlp tenemos que firmarlo y para firmarlo necesitamos un certificado que esté en un almacen de certificados. La máquina virtual de java viene con una herramienta perfecta, rápida y eficiente: "keytool.jar" programada por alguien que odiaba a los usarios. Por lo tanto vamos a utilizar para crear un almacen y un certificado una herramienta libre y gratuita, con interfaz gráfico como es portecle que creo que no necesita mucha explicación para lo que queremos hacer. En el menú encontrarás de forma directa como crear un almacen de tipo jks, en mi caso lo he guardado en "C:/work/codigo.jks" y una vez en el almacen he creado una clave con el alias "andres" y en un alarde de originalidad las contraseñas para acceder al almacen y para la firma son ambas "andres"

Ahora solo queda añadir al pom el plugin con los datos necesarios: qué tiene que firmar, dónde está el almacen, cual es la contraseña del almacen, cual de los certificados (por el alias) debe utilizar y cual es la contraseña para utilizarlo.

    <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jarsigner-plugin</artifactId>
                <version>1.2</version>
                <executions>
                    <execution>
                        <id>sign</id>
                        <goals>
                            <goal>sign</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>verify</id>
                        <goals>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <includes>
                        <include>target/*.*</include>
                    </includes>
                    <keystore>C:/work/codigo.jks</keystore>
                    <alias>andres</alias>
                    <storepass>andres</storepass>
                    <keypass>andres</keypass>
                </configuration>
            </plugin>

Cuando hagamos un mvn package automáticamente nos firmará el codigo. Si abrimos el jar generador veremos que ahora tenemos en su interior, en la carpeta META-INF, algunos archivos con las firmas y los hash de los archivos incluidos.




Comentarios