Ceci est une ancienne révision du document !


Signature en Java

Java gère les clés et les certificats dans des fichiers protégés appelés keystore. Il existe une keystore par défaut qui contient les certificats de confiance :

$JAVA_HOME/jre/lib/security/cacerts

La commande keytool permet de manipuler (lister et supprimer les clés, en créer et en importer) d’un keystore.

  • Lister les clés du keystore par défaut (mot de passe vide)
    • keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts

Les personnels et étudiants des universités peuvent obtenir des certificats X.509 officiels ici : https://tcs-personal-portal.terena.org/

A l’heure actuelle les certificats proposés ne contiennent pas l’attribut indiquant qu’ils peuvent servir à signer du code mais uniquement des emails. Cela provoque pour le moment un avertissement lors de l’utilisation.

Un fois un certificat obtenu et installé dans le navigateur, exporter le au format pkcs12 (.p12). Il est alors possible de l’importer dans un keystore :

  keytool -importkeystore \
        -destkeystore ...  -deststorepass ...  -destkeypass ... \
        -srckeystore ... -srcstoretype PKCS12 -srcstorepass ... \
        -srcalias "id terena de ..." \
        -destalias "..."

Les valeurs des paramètres (…) sont à remplacer dans l’ordre par : le chemin vers le fichier qui contiendra le keystore (~/.keystore/test.keystore), le mot de passe du keystore, le mot de passe de la future clé dans le keystore, le chemin vers le fichier .p12 contenant le certificat, son mot de passe, l’alias utilisé pour ce certificat dans la source (à vérifier avec le viewer de certificat du navigateur), l’alias qui sera associé au certificat dans le keystore (par exemple votre email certifié).

Une alternative est d’utiliser une certificat auto signé :

keytool -dname "CN=DOE john, OU=dpt-info, O=UTLN, L=La Garde, ST=PACA, C=FR" -storepass password -keypass password -alias johnkey -genkeypair -keystore keystore

Dans le ~/.m2/settings.xml (donc propre à chaque utilisateur et non commun au projet), il est possible d’indiquer le chemin, l’alias et de mot de passe permettant d’accéder au certificat qui sera utilisé par maven.

<properties>
  <jarsigner.keystore>...</jarsigner.keystore>
  <jarsigner.alias>...</jarsigner.alias>
  <jarsigner.storepass>...</jarsigner.storepass>
</properties>

Ensuite dans le projet on peut indiquer (dans le pom parent) que le plugin de signature doit être utilisé.

<!-- Signature des jar -->
            <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>
                </executions>
            </plugin>

Puis dans chaque module contenant un ou plusieurs artefact à signer, on indiquer son nom (élément archive).

<plugin>                                                           
 <groupId>org.apache.maven.plugins</groupId>                        
 <artifactId>maven-jarsigner-plugin</artifactId>                    
 <configuration>                                                    
  <archive>${project.build.directory}/${project.build.finalName}.jar</archive>                                                                     
 </configuration>                                                   
</plugin>

Il peut être utile de signer les compilations standards avec un certificat autosigné commun et uniquement certaines avec un certificat de confiance. Pour faire cela, il est assez simple de définir un profil dans le pom parent du projet qui fixe les paramètres d’un keystore par défaut et de définir un profile dans le settings.xml pour indiquer l’autre keystore.

La difficulté principale est lié au partage du keystore commun.

  1. L’utilisation d’un chemin absolu dans le pom.xml casse le partage simple entre utilisateurs et/ou le serveur d’intégration continue.
  2. L’utilisation d’un chemin asbolu dans le settings.xml est très lourde

Une solution assez élégante est de mettre le keystore dans un artefact, d’en faire une dépendance des projets et de l’extraire avant la signature cf. http://maksim.sorokin.dk/it/2010/08/19/signing-jars-on-a-build-server/