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
Un algorithme de signature numérique permet d'assurer l'analogue de
l'opération de signature manuscrite d'un document sur papier:
il est difficile d'"imiter" une signature, si bien qu'un document numérique
accompagné d'une signature est authentifié.
Ce concept de signature numérique permet de mettre en oeuvre des
outils de sécurité pour l'un des principaux moteurs économiques de
l'informatique actuelle: le commerce électronique.
Le projet de norme ISO 14888 propose plusieurs procédés, dont le
"procédé de Pointcheval-Vaudenay".
On se propose d'implémenter celui-ci en Java.
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.
- Un nombre premier .
- Un nombre premier qui est facteur de .
- Un entier compris entre 2 et et d'ordre modulo
(on a ).
Pour fixer les idées, on suppose et .
En outre, on suppose que chaque utilisateur détient un couple d'entiers
liés par la relation
On impose .
Chaque utilisateur détient sa clef secrète.
On suppose que les clefs sont publiées dans un
"annuaire électronique".
On note, qu'étant donné , il est très difficile de retrouver .
(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 .
Le procédé de signature permet, à partir des paramètres ,
de et de , de calculer un couple que l'on appelle
"signature de ".
Dans ce couple, on a et .
La longueur de la signature ne dépend donc pas de la taille du message.
On note que n'est pas déterminée par : il peut y avoir
plusieurs signatures possibles pour un même message.
Un autre procédé de vérification permet, à partir des paramètres
, de , de et de de vérifier que la signature est
correcte.
Dans la section suivante, on définit une "fonction de hachage" qui
permet de calculer un entier à partir d'une chaîne de bits
quelconque.
Le procédé de signature fonctionne ainsi.
- On tire un nombre aléatoire tel que .
- On calcule .
- On calcule
Dans ce calcul, la notation représente la concaténation
des chaînes de caractères qui représentent l'entier et
le message .
Pour vérifier une signature de avec la clef , on procède
ainsi.
- On vérifie et .
- On vérifie
Le calcul de nécessite une convention pour représentater sous
la forme d'une chaîne de caractères.
Dans le cas où est de 160 bits, on représentera sous la forme
d'une chaîne de caractères ASCII (en lettres minuscules) sur 40
caractères.
Par exemple, si , on utilise la chaîne
Si l'on a
on utilise
De même, la signature devra être représentée suivant la même
convention standard, soit sur 80 caractères hexadécimaux .
Fonction de Hachage
On suppose que l'on dispose d'une chaîne de caractère qui
représente un message.
Une fonction de hachage cryptographique est une fonction qui, pour tout
message de longueur arbitraire, calcule une "empreinte numérique"
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 en une
chaîne .
On note la longueur (en bits) de
.
Si l'on représente sous la forme
d'une chaîne de 64 bits,
soit 16 chiffres hexadécimaux (par exemple, si contient 419 bits, on note
.
On complète par un bit "1
", suivi d'un nombre variable de bits
"0
" puis de .
Le nombre de bits nuls doit être minimal pour que la chaîne finale soit
de longueur multiple de 512.
On a donc
où est constituée d'un bit
"1
" suivi d'un certain nombre de bits "0
".
La chaîne est ensuite découpée en blocs
de
512 bits (128 chiffres hexadécimaux), soit
De même, chaque chaîne
est découpée en 16 blocs
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.
- AND: et bit-à-bit.
- OR: ou bit-à-bit.
- XOR: ou exclusif bit-à-bit.
- NOT: complément à 1 bit-à-bit.
- : addition modulo .
- : rotation circulaire de bits vers la gauche.
(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 , ainsi que cinq registres
et que 80
registres .
On traite itérativement chaque bloc de 512 bits
, soit chaque bloc
de 16 mots de 32 bits
.
On effectue les étapes suivantes.
- initialiser
- pour jusqu'à :
- initialiser pour
- pour jusqu'à 79:
- initialiser , , ,
- pour jusqu'à 79:
- effectuer dans la variable temporaire
- effectuer , , , ,
- effectuer , ,
Le résultat du hachage est alors
Par exemple, si "abc"
, le message 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
0000000000000018
en hexadécimal.
On obtient donc
qui fait exactement 512 bits, soit
61626380
, pour et
00000018
.
Les 80 itérations conduisent aux résultats suivants dans les registres
.
|
|
|
|
|
|
0 |
0116fc33 |
67452301 |
7bf36ae2 |
98badcfe |
10325476 |
1 |
8990536d |
0116fc33 |
59d148c0 |
7bf36ae2 |
98badcfe |
2 |
a1390f08 |
8990536d |
c045bf0c |
59d148c0 |
7bf36ae2 |
3 |
cdd8e11b |
a1390f08 |
626414db |
c045bf0c |
59d148c0 |
4 |
cfd499de |
cdd8e11b |
284e43c2 |
626414db |
c045bf0c |
5 |
3fc7ca40 |
cfd499de |
f3763846 |
284e43c2 |
626414db |
6 |
993e30c1 |
3fc7ca40 |
b3f52677 |
f3763846 |
284e43c2 |
7 |
9e8c07d4 |
993e30c1 |
0ff1f290 |
b3f52677 |
f3763846 |
8 |
4b6ae328 |
9e8c07d4 |
664f8c30 |
0ff1f290 |
b3f52677 |
9 |
8351f929 |
4b6ae328 |
27a301f5 |
664f8c30 |
0ff1f290 |
10 |
fbda9e89 |
8351f929 |
12dab8ca |
27a301f5 |
664f8c30 |
11 |
63188fe4 |
fbda9e89 |
60d47e4a |
12dab8ca |
27a301f5 |
12 |
4607b664 |
63188fe4 |
7ef6a7a2 |
60d47e4a |
12dab8ca |
13 |
9128f695 |
4607b664 |
18c623f9 |
7ef6a7a2 |
60d47e4a |
14 |
196bee77 |
9128f695 |
1181ed99 |
18c623f9 |
7ef6a7a2 |
15 |
20bdd62f |
196bee77 |
644a3da5 |
1181ed99 |
18c623f9 |
16 |
4e925823 |
20bdd62f |
c65afb9d |
644a3da5 |
1181ed99 |
17 |
82aa6728 |
4e925823 |
c82f758b |
c65afb9d |
644a3da5 |
18 |
dc64901d |
82aa6728 |
d3a49608 |
c82f758b |
c65afb9d |
19 |
fd9e1d7d |
dc64901d |
20aa99ca |
d3a49608 |
c82f758b |
20 |
1a37b0ca |
fd9e1d7d |
77192407 |
20aa99ca |
d3a49608 |
|
|
|
|
|
|
78 |
5738d5e1 |
860d21cc |
681e6df6 |
d8fdf6ad |
d7b9da25 |
79 |
42541b35 |
5738d5e1 |
21834873 |
681e6df6 |
d8fdf6ad |
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:
où , où est la chaîne
et où 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.
-
Signature -p par.key
:
engendre les paramètres , et et les écrit dans un fichier
par.key
.
-
Signature -f par.key -g sec.key pub.key
:
engendre une paire à partir des paramètres situés dans le fichier
par.key
, et écrit et dans les fichiers séparés
sec.key
et pub.key
.
-
Signature -f par.key -s sec.key -m mes
:
engendre une signature (et l'affiche dans un format standard) pour le message
situé dans le fichier mes
au moyen des paramètres et de la clef
secrète contenus dans les fichiers par.key
et sec.key
.
-
Signature -f par.key -s sec.key "str"
:
même chose, mais pour un message court représenté par la chaîne
"str"
.
-
Signature -f par.key -k pub.key -m mes
"sig"
:
vérifie la signature "sig"
du fichier mes
.
-
Signature -f par.key -k pub.key "str"
"sig"
:
même chose, mais pour un message court représenté par la chaîne
"str"
.
-
Signature -h -m mes
:
calcule l'empreinte numérique du fichier mes
.
-
Signature -h "str"
:
même chose, mais pour un message court représenté par la chaîne
"str"
.
Problème de la Sécurité
Dans cette question, on supprime l'intervention de dans le calcul
de .
On a alors
Montrer que l'on peut construire des paramètres tels
que forme un jeu de paramètres valides, que et sont différents et que
Pour un jeu de clefs quelconque, calculer une signature de
.
Vérifier que est une signature valide de pour la clef publique
.
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
-
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.
-
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.
-
ISO/IEC 14888 Final Draft,
Information Technology - Security Techniques -
Digital Signatures with Appendix.
International Organization for Standardization, Berlin, Germany, 1998.
-
D. Pointcheval, S. Vaudenay.
On
Provable Security for Digital Signature Algorithms.
Rapport LIENS 96-17, Ecole Normale Supérieure, 1996.
-
C. P. Schnorr.
Efficient Signature Generation by Smart Cards.
Journal of Cryptology, vol. 4, pp. 161-174, 1991.
-
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.
-
Sur la page 80, la formule
a été malencontreusement remplacée par
(erreur de position de parenthèse).
-
Sur la page 78, la formule
a été malencontreusement remplacée par
(q à la place de p).