Cyril Rabat


Génération de signature en Java

 25/11/2015     23/10/2017      Programmation Java      Programmation client/serveur      Sécurité   

Utilisation de RSA pour signer un fichier

   Cet article présente comment utiliser l'algorithme RSA pour signer un fichier.

Mots-clefs :   Java     signature     RSA   

L'archive suivante contient l'ensemble des fichiers de cet article :

 Sécurité - Signature fichier RSA.zip

Pour cet article, nous avons besoin de générer une paire de clés privée/publique à l'aide de RSA. Nous ne détaillerons pas cette étape (reportez-vous à l'article Chiffrement asymétrique en Java).

Génération de la signature

Le programme suivant permet de générer la signature du fichier. Nous utilisons la classe Signature qui a besoin d'une clé privée pour fonctionner. Il suffit ensuite de lire le fichier désiré et de mettre à jour la signature à l'aide des données contenues dans le fichier. La signature est ensuite sauvegardée dans un fichier.

import java.security.Signature;
import java.security.SignatureException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.io.FileOutputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.FileInputStream;
 
/**
 * Classe permettant de signer un fichier avec une clé privée stockée dans
 * un fichier. La signature est sauvegardée dans un fichier.
 * @author Cyril Rabat
 * @version 23/10/2017
 */
public class SignatureFichier {
 
    /**
     * Méthode principale.
     * @param args[0] nom du fichier contenant la clé privée
     * @param args[1] nom du fichier à signer
     * @param args[2] nom du fichier dans lequel sauvegarder la signature
     */
    public static void main(String[] args) {
        // Vérification des arguments
        if(args.length != 3) {
            System.err.println("Utilisation :");
            System.err.println("  java SignatureFichier privee fichier signature");
            System.err.println("    où :");
            System.err.println("      - privee    : nom du fichier qui contient la clé privée");
            System.err.println("      - fichier   : nom du fichier qui doit être signé");
            System.err.println("      - signature : nom du fichier qui contiendra la signature");
            System.exit(-1);
        }
 
        // Reconstruction de la clé
        PrivateKey clePrivee = GestionClesRSA.lectureClePrivee(args[0]);
 
        // Création de la signature
        Signature signature = null;
        try {
            signature = Signature.getInstance("SHA1withRSA");
        } catch(NoSuchAlgorithmException e) {
            System.err.println("Erreur lors de l'initialisation de la signature : " + e);
            System.exit(-1);
        }
 
        // Initialisation de la signature
        try { 
            signature.initSign(clePrivee);
        } catch(InvalidKeyException e) {
            System.err.println("Clé privée invalide : " + e);
            System.exit(-1);
        }
 
        // Mise-à-jour de la signature par rapport au contenu du fichier
        try {
            BufferedInputStream fichier = new BufferedInputStream(new FileInputStream(args[1]));
            byte[] tampon = new byte[1024];
            int n;
            while (fichier.available() != 0) {
            n = fichier.read(tampon);
            signature.update(tampon, 0, n);
            }
            fichier.close();
        } catch(IOException e) {
            System.err.println("Erreur lors de la lecture du fichier à signer : " + e);
            System.exit(-1);
        }
        catch(SignatureException e) {
            System.err.println("Erreur lors de la mise-à-jour de la signature : " + e);
            System.exit(-1);
        }
 
        // Sauvegarde de la signature du fichier
        try {
            FileOutputStream fichier = new FileOutputStream(args[2]);
            fichier.write(signature.sign());
            fichier.close();
        } catch(SignatureException e) {
            System.err.println("Erreur lors de la récupération de la signature : " + e);
            System.exit(-1);
        } catch(IOException e) {
            System.err.println("Erreur lors de la sauvegarde de la signature : " + e);
            System.exit(-1);
        }
    }
 
}

 Télécharger le fichier

Vérification de la signature

Le programme suivant permet de vérifier la signature d'un fichier. Il a besoin de la clé publique (ou l'inverse suivant le choix réalisé lors de la génération). Il procède de même que pour la génération de la signature. La méthode verify permet de réaliser la comparaison avec la signature sauvegardée dans un fichier.

import java.security.Signature;
import java.security.SignatureException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
 
/**
 * Classe permettant de vérifier la signature d'un fichier à partir de la clé publique.
 * @author Cyril Rabat
 * @version 23/10/2017
 */
public class VerificationSignature {
 
    /**
     * Méthode principale.
     * @param args[0] nom du fichier dont on veut vérifier la signature
     * @param args[1] nom du fichier contenant la signature
     * @param args[2] nom du fichier contenant la clé publique
     */
    public static void main(String[] args) {
        // Vérification des arguments
        if(args.length != 3) {
            System.err.println("Utilisation :");
            System.err.println("  java VerificationSignature fichier signature publique");
            System.err.println("    où :");
            System.err.println("      - fichier   : nom du fichier dont on vérifie la signature");
            System.err.println("      - signature : nom du fichier qui contient la signature");
            System.err.println("      - publique  : nom du fichier qui contient la clé publique");
            System.exit(-1);
        }
 
        // Reconstruction de la clé
        PublicKey clePublique = GestionClesRSA.lectureClePublique(args[2]);
 
        // Lecture de la signature
        byte[] signatureFournie = null;
        try {
            FileInputStream fichier = new FileInputStream(args[1]);
            signatureFournie = new byte[fichier.available()]; 
            fichier.read(signatureFournie);
            fichier.close();
        } catch(IOException e) {
            System.err.println("Erreur lors de la lecture de la signature : " + e);
            System.exit(-1);
        }
 
        // Création de la signature
        Signature signature = null;
        try {
            signature = Signature.getInstance("SHA1withRSA");
        } catch(NoSuchAlgorithmException e) {
            System.err.println("Erreur lors de l'initialisation de la signature : " + e);
            System.exit(-1);
        }
 
        // Initialisation de la signature
        try {
            signature.initVerify(clePublique);
        } catch(InvalidKeyException e) {
            System.err.println("Cle publique invalide : " + e);
            System.exit(-1);
        }
 
        // Mise-à-jour de la signature par rapport au contenu du fichier
        try {
            BufferedInputStream fichier = new BufferedInputStream(new FileInputStream(args[0]));
            byte[] tampon = new byte[1024];
            int n;
            while (fichier.available() != 0) {
            n = fichier.read(tampon);
            signature.update(tampon, 0, n);
            }
            fichier.close();
        } catch(IOException e) {
            System.err.println("Erreur lors de la lecture du fichier à vérifier : " + e);
            System.exit(-1);
        }
        catch(SignatureException e) {
            System.err.println("Erreur lors de la mise-à-jour de la signature : " + e);
            System.exit(-1);
        }
 
        // Comparaison des deux signatures
        try {
            if(signature.verify(signatureFournie))
            System.out.println("Fichier OK");
            else
            System.out.println("Fichier invalide");
        } catch(SignatureException e) {
            System.err.println("Erreur lors de la vérification des signatures : " + e);
            System.exit(-1);
        }
    }
 
}

 Télécharger le fichier

Utilisation

Dans un premier temps, nous devons générer les clés privée/publique à l'aide du programme GenerationClesRSA (voir Chiffrement asymétrique en Java) avec la commande suivante :

java GenerationClesRSA privee.bin publique.bin

Nous pouvons maintenant générer la signature d'un fichier à l'aide de la commande suivante (ici, nous choisissons un fichier source Java) :

java SignatureFichier privee.bin SignatureFichier.java signature.bin

Nous avons passé en paramètre le fichier SignatureFichier.java. La signature est sauvegardée dans le fichier signature.bin. Pour vérifier que la signature est correcte, tapez simplement :

java VerificationSignature SignatureFichier.java signature.bin publique.bin

Articles connexes


Version de cette page Mercredi 16 Décembre 2015

© Cyril Rabat 2016

Connexion

Mot de passe perdu

Dernières nouvelles

Aucune pour le moment

Contact

Courriel :
cyril.rabat [at] univ-reims.fr

Téléphone :
+33-326-91-33-81

Fax :
+33-326-91-33-97

Facebook :
lien Facebook direct