Ce document a été proposé comme sujet de projet informatique pour les élèves du tronc commun de l'Ecole Polytechnique en 1998-99. Sa difficulté est "moyenne" (**).

Penser à consulter l'erratum à la fin de ce document.

Procédé de Signature Numérique

Auteur: Serge Vaudenay
Ecole Normale Supérieure - CNRS

Préambule

Dans ce projet, on cherche à implémenter le procédé de signature de Pointcheval-Vaudenay avec l'algorithme de hachage SHA-1 proposé par la chambre de commerce du gouvernement américain.

Principe de la Signature Numérique

Pour mettre en place le système proposé, on suppose définis les paramètres suivants. Pour fixer les idées, on suppose 2511<p<2512 et 2159<q<2160.

En outre, on suppose que chaque utilisateur détient un couple d'entiers (x,y) liés par la relation

On impose 0<x<q. Chaque utilisateur détient sa clef x secrète. On suppose que les clefs y sont publiées dans un "annuaire électronique". On note, qu'étant donné y, il est très difficile de retrouver x. (En fait, aucun algorithme connu ne permet de faire ce calcul en un temps raisonnable pour ces tailles de paramètres.)

Un message numérique se présente sous la forme d'une chaîne de bits m=m1 ... mn.

Le procédé de signature permet, à partir des paramètres (p,q,g), de x et de m, de calculer un couple sigma=(r,s) que l'on appelle "signature de m". Dans ce couple, on a 0<=r<q et 0<=s<q. La longueur de la signature ne dépend donc pas de la taille n du message. On note que sigma n'est pas déterminée par m: il peut y avoir plusieurs signatures possibles pour un même message.

Un autre procédé de vérification permet, à partir des paramètres (p,q,g), de y, de m et de sigma de vérifier que la signature est correcte.

Dans la section suivante, on définit une "fonction de hachage" h qui permet de calculer un entier h(c) à partir d'une chaîne de bits c quelconque. Le procédé de signature fonctionne ainsi.

  1. On tire un nombre k aléatoire tel que 0<k<q.
  2. On calcule r=(gk mod p) mod q.
  3. On calcule
Dans ce calcul, la notation r||m représente la concaténation des chaînes de caractères qui représentent l'entier r et le message m.

Pour vérifier une signature (r,s) de m avec la clef y, on procède ainsi.

  1. On vérifie 0<r<q et 0<s<q.
  2. On vérifie

Le calcul de r||m nécessite une convention pour représentater r sous la forme d'une chaîne de caractères. Dans le cas où q est de 160 bits, on représentera r sous la forme d'une chaîne de caractères ASCII (en lettres minuscules) sur 40 caractères. Par exemple, si r=11134, on utilise la chaîne

Si l'on a on utilise

De même, la signature (r,s) devra être représentée suivant la même convention standard, soit sur 80 caractères hexadécimaux r||s.

Fonction de Hachage

On suppose que l'on dispose d'une chaîne de caractère m qui représente un message. Une fonction de hachage cryptographique est une fonction qui, pour tout message m de longueur arbitraire, calcule une "empreinte numérique" h(m) qui est une chaîne de longueur fixée (ici, 160 bits, soit 40 chiffres hexadécimaux). Dans le cas de la signature numérique, cette chaîne est ensuite traitée comme un entier de 160 bits.

Afin d'effectuer le hachage, on effectue un premier codage de m en une chaîne m'. On note l(m) la longueur (en bits) de m. Si l'on représente l(m) sous la forme d'une chaîne de 64 bits, soit 16 chiffres hexadécimaux (par exemple, si m contient 419 bits, on note l(m)="00000000000001a3". On complète m par un bit "1", suivi d'un nombre variable de bits "0" puis de l(m). Le nombre de bits nuls doit être minimal pour que la chaîne finale soit de longueur multiple de 512. On a donc

pad est constituée d'un bit "1" suivi d'un certain nombre de bits "0".

La chaîne m' est ensuite découpée n en blocs m1,...,mn de 512 bits (128 chiffres hexadécimaux), soit

De même, chaque chaîne mi est découpée en 16 blocs mi,1,...,mi,16 de 32 bits (8 chiffres hexadécimaux), soit

Dans la suite, on effectue des opérations sur des chaînes de 32 bits. Les opérations utilisées sont les suivantes.

(L'opération <<< de Java effectue la rotation sur 64 bits.)

Une autre méthode consiste à utiliser des entiers de type short, donc des entiers signés de 32 bits. On peut alors utiliser les opérations &, |, ^, ~, +, <<<. Il faudra cependant prendre soin de bien représenter des entiers non signés.

Dans la suite, on définit les fonctions suivantes:

ainsi que les constantes suivantes:

On utilise cinq registres de 32 bits a,b,c,d,e, ainsi que cinq registres h0,...,h4 et que 80 registres w0,...,w79. On traite itérativement chaque bloc de 512 bits mi, soit chaque bloc de 16 mots de 32 bits mi,1,...,mi,16. On effectue les étapes suivantes.

  1. initialiser
  2. pour i=1 jusqu'à n:
    1. initialiser wt=mi,t+1 pour t=0,...,15
    2. pour t=16 jusqu'à 79:
    3. initialiser a=h0, b=h1, ..., e=h4
    4. pour t=0 jusqu'à 79:
      1. effectuer x=S5(a)+ft(b,c,d)+e+wt+kt dans la variable temporaire x
      2. effectuer e=d, d=c, c=S30(b), b=a, a=x
    5. effectuer h0=h0+a, ..., h4=h4+e
Le résultat du hachage est alors

Par exemple, si m="abc", le message m représente en fait la chaîne de bits 01100001 01100010 01100011, soit 616263 en hexadécimal. C'est une chaîne de 24 bits, il faut donc la compléter par un bit "1", 423 bits "0", et la chaîne l(m)=0000000000000018 en hexadécimal. On obtient donc

qui fait exactement 512 bits, soit m1,1=61626380, mi,j=0 pour 2<= j<= 15 et m1,16=00000018. Les 80 itérations conduisent aux résultats suivants dans les registres a,b,c,d,e. On effectue ensuite et l'empreinte numérique est finalement

Pour tester si une implémentation de cette fonction est correcte, on pourra effectuer les trois tests suivants:

m1="abc", où m2 est la chaîne et où m3 est la chaîne composée de 1 million de caractères égaux à "a".

Travail Demandé

Mise en Oeuvre

Faire une application Signature qui permet les utilisations suivantes.

Problème de la Sécurité

Dans cette question, on supprime l'intervention de r dans le calcul de h(r||m). On a alors Montrer que l'on peut construire des paramètres p,q,g,m1,m2 tels que p,q,g forme un jeu de paramètres valides, que m1 et m2 sont différents et que Pour un jeu de clefs (x,y) quelconque, calculer une signature (r,s) de m1. Vérifier que (r,s) est une signature valide de m2 pour la clef publique y. Que penser d'une telle propriété?

Librairie Utiles

Dans la librairie standard java.math est définie la classe BigInteger qui permet de faire des opérations sur des grands nombres. Notamment, on y trouve un test de primalité. Si l'on ne souhaite pas utiliser cette librairie, on devra implémenter le test de Miller-Rabin.

Pour lire un fichier texte ligne par ligne, on pourra utiliser la classe RandomAccessFile. De même, la classe FileOutputStream permet d'écrire dans un fichier.

Références

  1. FIPS 180-1, Secure Hash Standard. U.S. Department of Commerce - National Institute of Standards and Technology, National Technical Information Service, Springfield, Virginia. Federal Information Processing Standards 180-1, 1995.
  2. FIPS 186, Digital Signature Standard. U.S. Department of Commerce - National Institute of Standards and Technology, National Technical Information Service, Springfield, Virginia. Federal Information Processing Standards 186, 1994.
  3. ISO/IEC 14888 Final Draft, Information Technology - Security Techniques - Digital Signatures with Appendix. International Organization for Standardization, Berlin, Germany, 1998.
  4. D. Pointcheval, S. Vaudenay. On Provable Security for Digital Signature Algorithms. Rapport LIENS 96-17, Ecole Normale Supérieure, 1996.
  5. C. P. Schnorr. Efficient Signature Generation by Smart Cards. Journal of Cryptology, vol. 4, pp. 161-174, 1991.
  6. S. Vaudenay. Hidden Collisions on DSS. In Advances in Cryptology CRYPTO'96, Santa Barbara, Californie, U.S.A., Lectures Notes in Computer Science 1109, pp. 83-88, Springer-Verlag, 1996.


Erratum