PROCEDE CRYPTOSRAPHIQUE D'EXPONENTIATION MODULAIRE PROTE6E CONTRE LES ATTAQUES DE TYPE DPA
Dans le domaine de la protection des algorithmes cryptographiques contre les attaques DPA, l'invention concerne un procédé au cours duquel on réalise une exponentiation modulaire de type xΛd, avec d un exposant entier de m+1 bits, en balayant les bits de d de gauche à droite dans une boucle indicée par i variant de m à 0 et en calculant et en mémorisant dans un accumulateur (RO) , à chaque tour de rang i, un résultat partiel actualisé égal à x b{i). b(i) correspond aux m-i+1 bits de poids les plus forts de l'exposant d : b(i) = dm->i. Le nombre constitué des bits de poids j à k de d est défini par : dk->j= (dk, .... d )2 = ∑ =j d±.2Λ (i - j) .
L'exponentiation modulaire est une des opérations élémentaires utilisés dans de nombreux cryptosystèmes, tels que les cryptosystèmes RSA (Rivest, Shamir and Adleman) ou les cryptosystèmes DH (Diffie and Hellman) . Pour de telles applications, x est par exemple un message à chiffrer ou déchiffrer, à signer ou à authentifier, et d est par exemple une clé publique, une clé secrète, ou une partie d'une telle clé.
Depuis l'invention de la cryptographie à clé publique par Diffie et Hellman, de nombreux cryptosystèmes à clé publique ont été proposés. Parmi ceux qui résistent à l'analyse cryptographique, le cryptosystème RSA est sans aucun doute le plus largement utilisé. Sa sécurité intrinsèque réside dans la difficulté de factoriser des grands nombres entiers. En dépit d'intensives recherches, le problème de la factorisation est encore considéré comme un important problème, rendant le cryptosystème RSA
sûr pour des applications sensibles comme par exemple le chiffrement de données ou la signature digitale.
Aussi, plutôt que de tenter de casser l'algorithme RSA à un niveau mathématique, les cryptographes se sont intéressés aux implémentations concrètes des cryptosystèmes RSA. Ceci a conduit à l'essor des attaques par fautes et des attaques à canaux cachés, visant à découvrir notamment des informations confidentielles (comme par exemple des clés ou des parties des clés) manipulées au cours de l'une ou de l'autre des étapes mises en œuvre par le dispositif de calcul exécutant une opération cryptographique .
Les attaques à canaux cachés les plus connues sont dites simples ou différentielles. On entend par attaque à canal caché simple (SPA) ou différentielle (DPA) , une attaque basée sur la mesure d'une grandeur physique depuis l'extérieur du dispositif, dont l'analyse directe (attaque simple SPA) ou l'analyse selon une méthode statistique (attaque différentielle DPA) permet de découvrir des informations manipulées dans le dispositif.
Ces attaques ont notamment été dévoilées par Paul Kocher (Advances in Cryptology - CRYPTO' 99, vol. 1666 of Lecture
Notes in Computer Science, pp.388-397. Springer-Verlag,
1999) .
Parmi les grandeurs physiques qui peuvent être exploitées à ces fins, on peut citer le temps d'exécution, la consommation en courant, le champ électromagnétique rayonné par la partie du composant utilisée pour exécuter le calcul, etc. Ces attaques sont basées sur le fait que, au cours de l'exécution d'un algorithme, la manipulation d'un bit, c'est à dire son utilisation par une instruction particulière, laisse une empreinte
particulière sur la grandeur physique considérée, selon la valeur de ce bit et / ou selon l'instruction.
Il existe deux familles d'implémentations des algorithmes d'exponentiation permettant d'évaluer la valeur de y = xAd mod N : les implémentations dites de droite à gauche et les implémentations dites de gauche à droite.
Dans les implémentations de gauche à droite, on balaye les bits de l'exposant depuis le bit de poids le plus fort jusqu'au bit de poids le plus faible. Dans cette deuxième famille d'algorithmes d'exponentiation, est notamment connu l'algorithme SAM (pour Square And Multiply ou élever au carré et multiplier) et ses variantes telles que les algorithmes à fenêtre glissante. Par rapport aux algorithmes dits de droite à gauche, les algorithmes de gauche à droite nécessitent moins de mémoire et permettent l'utilisation de puissances xAi précalculées pour accélérer le calcul de y. Tous les algorithmes de gauche à droite ont en commun l'utilisation d'un accumulateur (ou registre) qu'on actualise tout au long du calcul pour mémoriser la valeur de xΛ dm_> mod N pour des valeurs décroissantes de i jusqu'à ce que l'accumulateur contienne la valeur finale y = xA dm_>0 = xA d mod . dk_>j est le mot constitué des bits de poids j à k de d.
Le principe général de l'algorithme SAM est le suivant. On note d = (dm, ... , d0)2 =
, la représentation binaire de l'exposant d, avec di e {0, 1}, le bit de poids i de d. Pour chaque bit de d, l'algorithme SAM mémorise dans un accumulateur (registre R0) un résultat actualisé calculé à partir de la relation de récurrence
χΛ m->i = (χΛ dm->i+l) *xΛdi, avec xAdm->m = xAdm, ce qui est résumé par l'algorithme ci-dessous : Entrée : x, d = (dm, ... , d0)2 Sortie : y = x d mod N RO <- 1 ; R2 <- x, i <- m tant que i > 0, faire : RO <- ROxRO mod N si d± = 1 alors RO <- RθχR2 mod N i <- i-1 fin tant que retourner R0
R0 <- x signifie que l'on mémorise dans le registre R0 la valeur de x. ROxRO signifie que l'on réalise une mise au carré du contenu du registre R0. R0χR2 signifie qu'on réalise le produit du contenu du registre R0 par le contenu du registre R2. Enfin, dι->j fait référence aux bits de rang j à i de d.
Pour prévenir les attaques d'implémentation, il est connu qu'il faut rendre les algorithmes aléatoires. Dans le cas du cryptosystème RSA, on connaît actuellement deux types de contre-mesures pour rendre aléatoire le calcul de y = xAd mod N.
Le premier type de contre-mesure consiste à rendre aléatoire les données d'entrée de l'algorithme.
Un premier exemple de cette première contre-mesure consiste à rendre aléatoire la donnée x avant de réaliser l'exponentiation modulaire, en ajoutant à x un terme aléatoire et à faire les calculs modulo 2Ak N, avant un modulo N final : x <- x + rl.N, avec ri un nombre aléatoire de k-bits
et à faire les calculs modulo (2Ak) .N, avant une réduction modulo N finale. Cette première contre-mesure, décrite par P. Kocher, présente l'avantage d'être indépendante de l'algorithme d'exponentiation.
Un deuxième exemple de cette première contre-mesure consiste à rendre aléatoire l'exposant d avant de réaliser l'exponentiation modulaire, en lui ajoutant un terme aléatoire : d <- d + r2.φ(N), r2 un nombre aléatoire de k-bits .
Le plus souvent, ces deux solutions sont combinées pour réaliser l'opération y = y mod N avec y = xA d mod(2 .N) .
Un troisième exemple de cette première contre-mesure utilisée seule par exemple lorsque x est le résultat d'un formatage probabiliste (par exemple à l'aide de la fonction PSS ou Probabilistic Signature Scheme) , car dans ce cas, x est déjà masqué et on calcule directement y = xA d mod N avec d = d + r2.φ(N) avec r2 aléatoire.
Malheureusement, une telle randomisation de l'exposant d est limitée à des implémentations particulières, appelées implémentations CRT, du cryptosystème RSA car la valeur de la constante d'Euler φ(N) n'est généralement pas connue de l'algorithme d'exponentiation privé dans sa version standard (c'est-à-dire non CRT) .
La deuxième contre-mesure consiste à rendre l'algorithme d'exponentiation lui-même aléatoire. La meilleure mise en pratique de la 2ème contre-mesure est l'algorithme MIST de Walter. L'algorithme MIST génère de manière aléatoire une nouvelle chaîne d'addition pour l'exposant d pour réaliser xAd mod N. Pour minimiser le nombre de registres, la chaîne d'addition est réalisée à la volée
par l'intermédiaire d'une adaptation d'un algorithme d'exponentiation basé sur des chaînes de divisions. Un autre exemple est une version améliorée d'un algorithme à fenêtre glissante (voir Kouichi Itoh, Jun Yajima, Masahiko Takenaka and Naoya Torii . DPA countermeasures by improving the window method CHES 2002, volume 2523 of Lecture Notes in computer Science, pages 303-317, Springer Verlag 2002) . Comparé à la première contre- mesure, ceci permet de rendre aléatoire l'exponentiation sans avoir besoin de connaître φ (N) mais nécessite un algorithme de division sécurisé pour calculer les chaînes de divisions et cause des soucis de gestion des calculs non négligeables .
L'invention propose un nouveau procédé pour rendre aléatoire l'exécution d'une exponentiation modulaire, dans le but de prévenir les attaques différentielles (DPA) , présentant les avantages des deux contre-mesures connues : comme dans la première contre-mesure, le procédé selon l'invention n'impose pas d'algorithme d'exponentiation particulier et s'applique à tout algorithme d'exponentiation, et comme dans la deuxième contre-mesure, dans l'invention, l'algorithme lui-même est rendu aléatoire, et non plus seulement les données qu'il manipule. Ainsi, l'algorithme n'a pas besoin de connaître φ (N) et / ou la clé publique e dans une exponentiation RSA (la clé e est souvent indisponible à l'algorithme de signature ou de déchiffrement).
Le procédé selon l'invention introduit le concept de exponentiation auto-aléatoire, signifiant que l'exposant d est utilisé lui-même comme une source additionnelle d'aléatoirité dans le processus d'exponentiation.
Ainsi, l'invention concerne un procédé cryptographique au cours duquel on réalise une exponentiation modulaire de
type xAd, avec d un exposant entier de m+1 bits, en balayant les bits de d de gauche à droite dans une boucle indicée par i décrémenté de m à 0 par pas de 1 et en calculant et en mémorisant dans un accumulateur, à chaque tour de rang i, un résultat partiel actualisé égal à xAb(i), b(i) étant les m-i+1 bits de poids les plus forts de l'exposant d.
Le procédé selon l'invention est caractérisé en ce que :
- à la fin d'un tour de rang i(j) (i = i(0)) choisi aléatoirement, on réalise une étape El de randomisation au cours de laquelle : El : on soustrait un nombre z (z= b(i(j)), z = b(i(j)) .2τ, z = u) aléatoire à une partie des bits de d non encore utilisés (di-ι->o) dans le procédé
- puis, après avoir utilisé les bits de d modifiés par l'étape de randomisation El, on réalise une étape de consolidation E2 au cours de laquelle : E2 : on mémorise (RO <- RlxRO) dans l'accumulateur (RO) le résultat de la multiplication du contenu de l'accumulateur (xAb(i)) par un nombre fonction de x z mémorisé dans un registre (Ri) .
D'un point de vue pratique, au cours de l'étape El, le nombre z est soustrait au contenu d'un registre dans lequel est mémorisé initialement l'exposant d, et le résultat de la soustraction est mémorisé dans le même registre, puis on continue de balayer les bits de b.
Pour que le résultat de l'exponentiation xAd mod N soit correct à la fin du procédé, l'étape de randomisation El, ne doit pas modifier les bits de d déjà utilisés dans le calcul (on rappelle que le procédé utilise un algorithme de gauche à droite). L'index i(j) auquel on réalise la
randomisation El, choisi aléatoirement, doit donc être choisi tel que les m-i (j ) +1 bits de poids les plus forts du registre contenant initialement l'exposant d restent inchangés lors de 1 ' étape El . On appellera par la suite cette condition une condition de "consistance".
L'idée essentielle de l'invention st ainsi d'utiliser un découpage du calcul de xAd mod N de la forme : xAd = xA(d-z)*x z (décrit dans la demande de brevet français n° 02 04117 (n° à confirmer) avec z un nombre aléatoire utilisé comme moyen de masquage de l'exposant d. On choisit de préférence des valeurs de z appropriées telles que xAz puisse être obtenu facilement à partir de xAb déjà calculé par ailleurs au cours du procédé. A noter qu'un choix totalement aléatoire de z entraîne un quasi doublement du temps de calcul .
Le procédé selon l'invention s'applique indépendamment de l'algorithme d'exponentiation de gauche à droite. Par ailleurs, le rang i(j) auquel on réalise l'étape El est choisi aléatoire donc le procédé lui-même est aléatoire, et non pas seulement les données qu'il manipule.
Le procédé selon l'invention est également efficace en termes de place (il ne nécessite qu'un seul registre de calcul supplémentaire) et en terme de temps de calcul, comme on le verra mieux par la suite dans 1 'exemple de l'algorithme SAM.
Le procédé selon l'invention est encore facile à mettre en œuvre quel que soit l'algorithme auquel il est appliqué : il ne repose sur aucune propriété de groupe et sa mise en œuvre ne nécessite pas de connaître au
préalable l'ordre du groupe dans lequel l'exponentiation est réalisée.
Enfin, le procédé selon l'invention peut être utilisé conjointement avec d'autres mesures de protection des algorithmes, comme par exemple les contre mesures dévoilées par P. Kocher et rappelées précédemment.
L'étape El de randomisation peut être réalisée une seule fois au cours du procédé. L'étape El peut également être réalisée plusieurs fois, à la fin de différents tours de rang i(j) (c'est-à-dire au rang i = i(0), puis au rang i = i(l), ..., puis enfin au rang i = i(f)) choisis aléatoirement entre 0 et m. L'idée est ici d'améliorer encore la sécurité du procédé en utilisant la relation : xAd = xA (d-zl-z2-...-zf) χχAzlχχAz2χ ... χχAzf = xA( ( (d-zl)-z2)-...-zf) x ( (xAzl) χχAz2) x ... χχAzf
On peut choisir au début du procédé le ou les rangs i(j) aléatoires auxquels on réalise une randomisation El. Par exemple, au début du procédé, on détermine un ensemble prédéfini {i(0), i(l), ..., i(f)} de f+1 (f étant aléatoire ou non) valeurs de l'index i pour lesquelles on souhaite réaliser une randomisation El. Dans ce cas, à chaque tour, on décide de réaliser ou non une randomisation El selon que l'index courant i fait partie ou non de l'ensemble prédéfini.
On peut aussi choisir aléatoirement au début de chaque tour i de réaliser ou non l'étape El de randomisation. Dans ce cas, on utilise par exemple une variable booléenne p, tirée aléatoirement à la fin de chaque tour d' index i .
Différents modes de réalisation de l'invention vont maintenant être décrits, qui diffèrent l'un de l'autre essentiellement par le mode de réalisation de l'étape El, et notamment par le choix de z et par le choix de la partie de d à laquelle on soustrait z .
Selon un premier mode de réalisation, on choisit de réaliser l'étape de consolidation une seule fois à la fin du procédé. Ceci impose de soustraire z systématiquement aux bits de poids les plus faibles de l'exposant d, de sorte à obtenir un résultat correct à la fin du procédé.
Selon une première variante de ce mode de réalisation, on choisit z ≈ b(i(j)) = dm->i(j) pour un nombre aléatoire i(j) choisi et, au cours de l'étape de randomisation El, on soustrait b(i(j)) à d, c'est-à-dire aux bits de poids les plus faibles de d.
Le choix z = b(i(j)) est particulièrement avantageux puisque xAb(i(j)) = xAdιrL_>i(j) est déjà disponible dans l'accumulateur à la fin du tour i(j) et n'a donc pas besoin d'être calculé. La variable i(j) est choisie telle que les bits de poids i(j) à m du nombre d-b(i(j)) soient égaux aux bits de poids i(j) du nombre d, de sorte que les m-i(j)+l premiers tours du calcul de xAd sont identiques aux m-i(j)+l premiers tours du calcul de xA (d- b(i(j))) (condition de consistance). A la fin du tour i(j), on calcule d-z = d-b(i(j)) et on mémorise le contenu de l'accumulateur xAb dans le registre (El) .
Dans un exemple particulier, une variable booléenne p est utilisée pour déterminer, à la fin de chaque tour d'index i, si on réalise ou non une randomisation. Si p prend une valeur active, alors on réalise l'étape El : on remplace le nombre d par le nombre d-b(i(j)) et on mémorise xAb(i (j) ) .
Comme dans l'algorithme de gauche à droite classique, l'accumulateur RO est utilisé pour conserver la valeur de xAdm->i, à chaque tour d'index i. On utilise le registre Ri pour conserver le produit : IIj χA dm_>i(j) .
Le tout appliqué à l'algorithme SAM connu, on obtient le l'algorithme I suivant : Entrée : x, d = (dm, ... , d0)2 Sortie : y = xAd mod N RO <- 1 ; RI <- 1 ; R2 <- x ; i <- m tant que i > 0, faire : R0 <- ROxRO mod N si d± = 1 alors R0 <- R0χR2 mod N p <- R{0, 1} si ( (p = 1) ET
> dm→i alors d <- d - dm→i RI <- RlxRO mod N fin si i <- i-1 fin tant que R0 <- ROxRl mod N retourner R0
p <- R{0, 1} signifie que l'on choisit la valeur de p aléatoirement dans l'ensemble {0, 1}. p est ainsi une variable booléenne aléatoire.
L'étape de randomisation El (d <- d - dm_>i(j) ; Ri <- RlxRO mod N) est réalisée uniquement si p = 1 (c'est-à-
dire si une randomisation doit être réalisée) et si di(j)_ i->0 ≥ dm_>i (j ) .
La condition di(j)_ι_>o ≥ dm->i(j) signifie que les bits de poids 0 à i-1 de d sont supérieurs à b(i(j)), b(i(j)) étant égal aux bits de poids i(j) à m de d. Ceci permet de garantir que les m-i+1 bits de poids les plus forts de d-b(i(j)) sont identiques aux m-i+1 bits de poids forts de d, et donc que les m-i+1 premiers tours du calcul de x d sont identiques aux m-i+1 premiers tours du calcul de xA(d-b(i(j))) .
La condition de "consistance" (di(j)-ι->o ≥ dm->i(j)) implique que seulement les bits de poids faibles de l'exposant d sont rendus aléatoires. De plus, on remarque que l'étape de randomisation d <- d - dm_>i(j) modifie uniquement les (m-i(j)+l) bits les moins significatifs de d.
A noter que, dans l'algorithme I, comme à l'itération i = i(j) l'étape de mise à jour d <- d - dm->ι ne modifie pas les (m-i+1) bits les plus significatifs de d, cette étape peut être remplacée par 1 ' étape équivalente :
Selon une deuxième variante du premier mode de réalisation, on choisit z égal g.b(i), avec g un nombre aléatoire tel que di(j)_ι->o ≥ g.dm->i(j) . On utilise dans ce cas la relation x d = xA(d-z) .x z = xA (d- g.b(i) ) . (xAb(i) )9. et, d'un point de vue pratique, pour réaliser une randomisation El à la fin du tour d'index i(j) : - on calcule z = g.b(i) et on soustrait le résultat à l'exposant d,
- le registre Ri est mis à jour en multipliant son contenu par le contenu de l'accumulateur (xΛb(i)) exposé à la puissance g. Ce qui concrètement peut être réalisé par l'instruction RI <- RlχR0Ag mod N.
On choisit de préférence g = 2τ, τ étant un nombre entier aléatoire. Ceci simplifie considérablement les calculs car le calcul de g.b(i) = g.dm_>i(j) revient à un simple décalage de bits et l'évaluation de (xAb(i))Ag mod N revient à réaliser le calcul de τ carrés .
Puisque multiplier par 2τ revient à un décalage de bits, l'instruction d <- d - 2τ.dm->i qui calcule d-g.b(i) peut être remplacée par dm->τ <- d->τ - dm->ι ou mieux, par l'instruction équivalente di-ι->τ <- di-ι_>τ - dm->i.
De plus, comme pour les autres modes de réalisation, on doit vérifier que à l'itération i=i (j ) , dι-ι->o ≥ 2τ.dm->i. Cette condition de consistance peut être remplacée par un test équivalent mais plus efficace : di-i-^ ≥ dm-i.
De préférence, on choisit τ aléatoire dans l'ensemble {0, ..., T}. La borne T est- choisie comme le meilleur compromis entre la randomisation des bits les plus significatifs de d et l'efficacité (en terme de temps de calcul notamment) du calcul des τ carrés .
Dans l'exemple particulier de l'algorithme SAM, on obtient finalement 1 ' algorithme I ' suivant . Entrée : x, d = (dm, ... , d0)2 Sortie : y = xAd mod N RO <- 1 ; RI <- 1 ; R2 <- x ; i <- m tant que i > 0, faire : RO <- ROxRO mod N si d± = 1 alors RO <- R0χR2 mod N p <- R{0, 1} ; τ <- R{0, ..., T} si ( (p = 1) ET (d±_1→τ > dm_jL)) alors di-i→τ *~ i_ι_>τ - m_>i R3 <- R0 tant que (τ > 0) faire R3 <- R3A2 mod N ; τ <- τ-1 fin tant que RI <- RlxR3 mod N fin si i <- i-1 fin tant que R0 <- ROxRl mod N retourner R0
Un avantage de l'algorithme I' est qu'on randomise en partie la moitié supérieure de d et qu'on ajoute en conséquence de l'entropie (c'est-à-dire de l'aléatoirité) . Par contre, un registre supplémentaire R3 est nécessaire pour calculer R0A2τ.
Les algorithmes I et I ' peuvent être suffisants pour protéger les exposants dans certains cas. Par exemple, en raison de sa construction, le cryptosystème RSA dévoile toujours la moitié la plus significative de l'exposant d privé si l'exposant public correspondant est petit. Rendre aléatoire les bits de poids forts de d
n'apporterait donc aucune protection pour un tel algorithme.
Toutefois, pour d'autres algorithmes et dans d'autres situations, rendre aléatoire tous les bits de d apporterait une sécurité supplémentaire .
Pour cela, on. propose, dans un deuxième mode de réalisation, de choisir z = b(i(j)) = dm_>i(j) pour un nombre aléatoire i(j) et, au cours de l'étape El, on soustrait b(i) non plus à d, mais à une partie des bits de d correspondant aux bits de d de poids i(j)-c(j) à i(j)-l, c(j) étant un nombre entier tel que i (j )>c (j ) >0. Ceci peut être exprimé par 1 ' instruction suivante : dm->i(j)-c(j) <- dm_>i(j)-c(j) - dm->i(j)
Préférentiellement, comme lors de l'étape El d'une randomisation au rang i (j ) , on modifie les bits de poids i(j) _ c(j) à i(j) - 1 de d et on choisit de ne réaliser qu'une seule randomisation à la fois, et on choisit de réaliser une étape de consolidation à la fin du rang utilisant le dernier bit de d modifié lors de l'étape de randomisation El précédente (et non plus à la fin du procédé), c'est à dire après l'évaluation du résultat partiel xA (dm->ι (j)-c(j) ) πiod N.
Ceci revient à imposer la condition i(j+l) < i(j) - c(j), i(j+l) étant l'index de la randomisation suivante. Ceci permet de ne pas utiliser de registres supplémentaires pour mémoriser les bits de l'exposant qui ont été modifiés lors d'une randomisation précédente. Egalement, on choisit i(j) - c(j) < 0, de sorte que i(j) - c(j) puisse être utilisé pour définir le rang d'un bit de d pour le calcul de xA (dm->i (j)-c(j) ) m° N.
Ces deux conditions peuvent être concrétisées par l'utilisation d'un sémaphore booléen σ qui indique si une mise à jour est autorisée ou pas : σ a une valeur inactive tant que i > i(j) - c(j) et est activée lorsque i< i(j) - c(j). Elle devient de plus inutilisable dès que i(j) - c(j) < 0.
Les (m-i(j)+l) bits de poids les plus forts de d restent inchangés lors de l'étape de randomisation si (condition de consistance) : di(j)-ι→i(j)-c(j) ≥ dm→i(j) (i(j) - 1) - (i(j) - c(j) ) > m - i(j) <=> c(j) > m - i(j) + 1
Selon une première variante du deuxième mode de réalisation, on choisit c(j) égal à m-i(j)+l. Avec la condition i (j ) > c(j) ≥ 0, la condition c(j) > m - i(j) + 1 est vérifiée si 2.i(j) >' m+1.
L'algorithme SAM modifié selon cette variante peut alors s'écrire (algorithme II) : Entrée : x, d = (dm, ... , d0)2 Sortie : y = xAd mod N RO <- 1 ; Ri <- 1 ; R2 <- x ; i <- m ; c <- -1 ; σ <- 1 tant que i > 0, faire : RO <- ROxRO mod N si di = 1 alors RO <- R0xR2 mod N fin si si (2i > m+1) ET (σ = 1) alors c <- m-i+1 sinon σ = 0 fin si p <- R{0, 1} ε <- p ET (di-i -> i-c ≥ dm->ι) ET σ si ε = 1 alors RI <- R0 ; σ <- 0 di-i -> i-c <- di-i _> i_c - dm -> i fin si si c = 0 alors R0 <- ROxRl mod N ; σ <- 1 fin si c <- c-1 ; i <- i-1 fin tant que retourner R0
On notera que l'algorithme I correspond à l'algorithme II dans le cas où c(j) = i(j) pour tout j. On notera également que dans l'algorithme II, la condition de consistance ( dj_M)_;|_→.j_M)_C(j) >
est satisfaite durant la première partie de l'algorithme, en considérant de manière approximative que djΛj)_ι.→i(j)_C(j) et dm→i(j) sont des nombres aléatoires de (m-i(j)+l) bits. On notera, dans cet algorithme, que tous les bits de l'exposant sont randomisés .
Selon une deuxième variante du deuxième mode de réalisation, on choisit c(j) aléatoire et compris entre i (j) et m-i (j) +1.
On a vu précédemment que la condition c(j) ≥ m - i(j) + 1 doit être vérifiée. En posant c(j) = m - i(j) + 1 + V(j), on doit donc vérifier V(j) > 0. Par ailleurs, avec la condition i(j) ≥ c(j) > 0, il vient 2.i(j) > m+l+V(j). Donc la plus grande valeur possible pour V(j) est 2.i(j)- m-1 et donc, comme V(j) >0, le paramètre c(j) = m- i(j)+l+v(j) peut prendre toute valeur dans l'ensemble {m- i(j)+l, ..., i(j)}. On peut alors généraliser l'algorithme II en choisissant c(j) aléatoire dans l'ensemble {m- i(j)+l, ..., i(j) } .
Dans l'exemple particulier de l'algorithme II cela revient à remplacer l'instruction : si (2i > m+1) ET (σ = 1) alors c <- m-i+1
par l'instruction : si (2i > m+1) ET (σ = 1) alors c <- R{m-i+l, i}
ce qui donne l'algorithme III suivant :
Entrée : x, d = (dm, ... , d0)2 Sortie : y = xAd mod N RO <- 1 ; RI <- 1 ; R2 <- x ; i <- m ; c <- -1 ; σ <- 1 tant que i > 0, faire : RO <- ROxRO mod N si di = 1 alors RO <- R0xR2 mod N fin si si (2i > m+1) ET (σ = 1) alors c <- R{m-i+l, i} sinon σ = 0 fin si p <- R{0, 1} ε <- p ET (di-i -> i-c > dm_>i) ET σ si ε = 1 alors RI <- R0 ; σ <- 0 di-i -> i-c <- di-i -> i-c - dm -> i fin si si c = 0 alors R0 <- ROxRl mod N ; σ <- 1 fin si c <- c-1 ; i <- i-1 fin tant que retourner R0
Une valeur plus grande pour V(j) augmente la probabilité de succès pour la condition de consistance (et donc pour le choix d'une randomisation) . D'un autre côté, cela réduit également les valeurs possibles de l'indexe i vérifiant la condition 2.1 (j) ≥ m+l+V(j).
La fréquence d'occurrence de la valeur p = 0 de la variable booléenne p est un paramètre du procédé permettant de choisir le meilleur compromis entre
performance et sécurité, en fonction de l'application envisagée : plus on réalise d'étapes de randomisation, plus on pénalise le temps de calcul global ; inversement, moins on réalise d'étapes de randomisation, plus on facilite les attaques par recherche exhaustive.
Un bon moyen pour minimiser le coût des opérations additionnelles consiste à modifier légèrement le générateur de nombres aléatoires produisant le nombre p de sorte que, lorsque le poids de Hamming de d-z (z peut avoir différentes valeurs en fonction de b(i), selon le mode de réalisation envisagé) est plus faible que le poids de Hamming de d, p a une plus forte probabilité de valoir 1, et inversement. Avec cette astuce, l'algorithme va tendre à sélectionner le cas ayant le plus faible poids de Hamming, c'est-à-dire la branche la plus rapide.
On note seulement que cet algorithme ne peut pas toujours sélectionner la branche la plus rapide, sinon, il deviendrait déterministe et donc facilement attaquable.
Selon un troisième mode de réalisation de l'invention, on choisit au début du procédé un nombre u aléatoire de v bits et on mémorise xAu dans le registre Ri . De préférence, le nombre u est modifié plusieurs fois au cours du procédé, pour augmenter le facteur aléatoire dans le procédé.
Puis, au cours du calcul, pour un rang i(j) donné, on se demande, pour un paquet w de v bits de d tel que w>u, si le calcul de xAw est plus coûteux (en terme de temps de calcul) que celui de xA(w-u)*xAu.
Pour répondre à cette question, il suffit de déterminer si H( ) > H( -u) + 1. H( ) est le poids de Hamming de w, il est représentatif du coût de l'opération xA . H( -u) est le poids de Hamming de x (w-u) , représentatif de xA (w-u) . Le terme " + 1" est représentatif du coût de la multiplication de xA (w-u) par x u (xAu étant mémorisé par ailleurs) .
Si le calcul de xAw est moins coûteux que le calcul de xA (w-u) *x u, alors on continue le procédé. Sinon, si le calcul de xAw est plus coûteux que le calcul de xA (w- u) *xAu, alors on remplace le paquet w de bits de d par le nombre w-u. L'étape de consolidation (ici, une multiplication par xAu, qui ce traduit par l'opération RO <- ROxRl mod N) sera réalisée lorsque tous les bits de d modifiés auront été utilisés .
Par rapport aux deux précédents modes de réalisation décrits, ce troisième mode de réalisation présente l'avantage d'être plus rapide, puisque, pour effectuer une randomisation, on choisit chaque fois le chemin le plus rapide (le moins coûteux) . Ainsi, on montre expérimentalement que la complexité de ce procédé est d'environ 1.4. La complexité est le nombre moyen de multiplications de contenus de registres réalisées pour chaque bit de l'exposant d. La complexité d'un algorithme SAM non protégé est de 1.5 ; la complexité des procédés selon le premier ou le deuxième modes de réalisation de l'invention est quant à elle légèrement supérieure à 1.5.
Par ailleurs, dans ce troisième mode de réalisation, la source d'aléatoirité (le nombre u) est extérieure au procédé. Enfin, les ressources (notamment le nombre de registres) utilisées sont les mêmes.
troisième mode de réalisation peut être concrétisé par ' algorithme IV suivant :
Entrée : x, d = (dm, ... , d0)2 Paramètres : v, k Sortie : y = xAd mod N RO <- 1 ; R2 <- x ; i <- m ; L = { } tant que i > 0, faire RO <- ROxRO mod N si di = 1 alors R0 <- R0xR2 mod N fin si si i = m mod( (m+1) /k) ) alors σ <- 1 fin si si σ = 1 et I = { } alors (modification du nombre u en cours de procédé) σ <- 0; u <- R{0, ..., 2V-1} ; RI = xAu mod N fin si
h <- H( ) si w > u alors Δ <- w-u ; h.Δ <- 1 + H(Δ) sinon hΛ <- v+2 fin si p <- R{0, 1}
[ (h>hΔ) OU ( (p≈l ) ET (h≈hΔ) ) ] alors (on choisit de réaliser xΛ (w-u) ) di->i-v+l <- Δ ; L <- L u { i-v+1 } fin si si (i e L) alors R0 <- ROxRl mod N L <- L \ { i } fin si i <- i-1 fin tant que retourner R0
Dans cet exemple, l'ensemble L contient la liste des indices pour lesquels une étape de consolidation doit être réalisée. L'instruction "si di = 1 alors RO <- R0χR2 mod N fin si" est l'instruction classique d'un algorithme SAM, réalisée pour chaque valeur de i .
L'exposant d est ici découpé en k blocs, de taille identique si m+1 est divisible par k ou de taille identique à une unité près sinon.
A chaque début de bloc (c'est à dire pour i ≈ m mod( (1+1) /k) ) , on met la variable σ à 1. Ensuite, quand σ vaut 1, il faut attendre que l'ensemble L soit vide avant d'effectuer une nouvelle étape de randomisation. A chaque étape de consolidation, on enlève un indice i(j) correspondant de l'ensemble L (instruction L <- L \{i}). Lorsque l'ensemble I» est vidé, une nouvelle valeur de u peut être choisie et xAu est calculé par un algorithme SAM classique utilisant les registres Ri et R2.
Au milieu de chaque bloc (σ = 0) , on réalise une ou plusieurs étapes de randomisation, lorsque h>hΔ ou (p=l et h = hΔ) , et on mémorise à chaque fois (instruction L <- L u {i-v+1}) l'indice i(j)-v+l auquel on devra effectuer une étape de consolidation. Il faut donc que i- v+1 soit un indice de consolidation valable, c'est-à-dire que i-v+1 >0 (condition de consistance) . A chaque étape de randomisation, si h > hΔ, on choisit de réaliser l'opération x (w-u) *xAu, moins coûteuse, et on modifie les bits de d en conséquence (di_>i-v+ι <- Δ) . Si h < hΔ, on choisit de réaliser xAw, moins coûteuse, et on ne modifie pas d. Si h = hΔ, on choisit aléatoirement (p = 0 ou 1 aléatoire) de réaliser xA (w-u) *xAu ou xAw.
A titre indicatif, on donne le nombre moyen de multiplications modulaires nécessaires pour réaliser une exponentiation de longueur 1024 avec l'algorithme SAM, protégé ou non : • SAM sans protection : 1536 multiplication
• SAM protégé en ajoutant un multiple de Φ(n) (r.Φ(n) avec r de 64 bits) ajouté à l'exposant d (art antérieur) : 1536 + 96 multiplications
• SAM protégé selon l'algorithme II ou III : 1536 + 10 multiplications
• SAM protégé selon l'algorithme I' : 1536+512 multiplications, p, p étant la valeur moyenne de p
• SAM protégé selon l'algorithme IV : 1443 multiplications
On constate par ces exemples qu'un algorithme protégé selon l'invention est très efficace, en terme de multiplications réalisées (et donc de temps de calcul) .