• Aucun résultat trouvé

3.4 Contre-exemples

3.4.2 Conditionnelles

Une extension naturelle consiste à considérer des processus avec des branches else. Cepen-dant, lorsque les messages émis sur ces branches peuvent dépendre, directement ou indirectement, de certaines constantes, il devient nécessaire que l’attaquant dispose d’un nombre arbitraire de constantes. Ce résultat négatif est déjà valable pour les propriétés d’accessibilité.

Étant donné un entier n arbitraire, nous notons Σn un ensemble de cardinal n de constantes de type τ?. Formellement, nous montrons que nous pouvons associer, pour chaque instance de PCP, deux protocoles P et Q (qui utilisent exclusivement le chiffrement symétrique et la paire) tels que P 6vatQ avec n constantes, si, et seulement si, l’instance de PCP a une solution de longueur plus petite que n. Il s’agit donc de modifier les protocoles de la section précédente pour que l’attaquant ne puisse vérifier sa solution que s’il dispose d’autant de constantes que la longueur (en nombre de tuiles) de la solution de PCP.

L’étape la plus nouvelle consiste à établir un moyen de vérifier que l’attaquant dispose d’une liste de constantes toutes différentes. Le nom D (avec δ(D) = τk) représente une clé inconnue de

l’attaquant, la variable x0

c représente une clé ajoutée par l’attaquant, de type δ(x0

c) = τc ∈ T , et les nonces nc, n0c, ainsi que la constante ⊥ncet les variables xnc, x0nc, sont de type τnc. ⊥ncpermet de représenter la liste vide.

V0(c) = in(c, x0c).new nc.out(c, senc(hnc, x0c, ⊥nci, D))

V1(c) = in(c, senc(hxnc, x1c, x0nci, D)). in(c, senc(hync, y1c, x0nci, D)). if x1c 6= y1

cthen

new n0c.out(c, senc(hn0c, x1c, ynci, D))

Le processus V0 permet d’obtenir des jetons hnc, x0c, ⊥nci. Ensuite, le principe de V1 est que les éléments de la liste a :: b :: ` sont deux à deux distincts si, et seulement si :

— les éléments des listes a :: ` et b :: ` sont deux à deux distincts ; — et a 6= b.

À ce titre, la construction if x1 c 6= y1

cthen a la sémantique attendue : elle continue de s’exécuter seulement si x1

c et y1

c sont instanciées par des valeurs différentes. Cette instruction peut se coder comme if x1

c = y1

cthen 0 else . . . . Si nous conservions chaque fois le même pointeur de tête, il se-rait facile d’obtenir hn1, a, n2i puis hn2, b, n1i, et ainsi de disposer d’une liste chaînée infinie avec seulement deux constantes. Le changement de pointeur, grâce au nonce n0c, résout ce problème. Exemple 3.3. Si l’attaquant dispose de trois constantes a, b, c, il peut obtenir les termes suivants après trois utilisations de V0 :

ta= senc(hn1, a, ⊥nci, D) tb= senc(hn2, b, ⊥nci, D) tc= senc(hn3, c, ⊥nci, D)

Il peut donc en déduire par exemple t0b = senc(hn02, b, n1i, D) et t0c = senc(hn03, c, n1i, D) en appli-quant V1 à tb, ta puis à tc, ta. Enfin, il peut obtenir t00c = senc(hn003, c, n02i, D) en appliquant V1 à t0c, t0b. Il pourra alors certifier qu’il possède trois constantes distinctes en fournissant t00c, t0b et ta, dont les nonces se suivent. Si il tente de tricher et d’utiliser deux fois la même constante, et récupère par exemple senc(hn4, c, ⊥nci, D), il peut arriver à obtenir senc(hn00

4, c, n02i, D), senc(hn00

2, b, n04i, D) ou senc(hn01, a, n4i, D), mais à chaque fois ces termes représentent la tête d’une liste de trois constantes seulement. Il ne peut pas obtenir de liste plus longue sans utiliser une constante supplémentaire.

Plus formellement, démontrons le lemme suivant :

Lemme 3.3. Soit E = {senc(hn1, a0, n0i, D), senc(hn2, a1, n1i, D) . . . , senc(hnk+1, ak, nki, D)} un ensemble de termes. Posons P = {( ! new c00.out(c0, c00).V0(c00) | ! new c01.out(c1, c01).V1(c01))} et sup-posons (tr, φ) ∈ traceΣ+

0(P), tels que E ⊆ img(φ). Alors pour tout i 6= j, ai6= aj.

Démonstration informelle. Nous procédons par récurrence sur k. Si k = 1, le résultat est évident. Supposons que le résultat soit vrai pour un k quelconque, et démontrons-le pour k + 1. Posons ti= senc(hni+1, ai, nii, D) pour tout i. Si l’attaquant a réussi à connaître l’ensemble {t1, . . . , tk+1} alors il a réussi à connaître {t1, . . . , tk} et {t1, . . . , tk−1, tk+1}. L’hypothèse de récurrence s’applique, et nous avons ai 6= aj pour tout i 6= j tels que i, j6 k. Or, comme le nom D n’est pas déductible (puisqu’il n’apparaît qu’en position de clé), l’attaquant a nécessairement appris tk+1 après avoir

exécuté V1. Donc, il connaissait nécessairement senc(hn0k+2, ak+1, n0ki, D) et senc(hnk+1, a, n0ki, D) avec n0k+2, n0k des noms et a 6= ak+1. Pour un nonce n donné, il n’existe qu’un seul terme de la forme senc(hn, _, _i, D), donc a = ak et n0k = nk et ak+1 6= ak. En appliquant l’hypothèse de récurrence à {t1, . . . , tk−1, senc(hn0k+2, ak+1, nki, D)}, nous obtenons de plus que ak+1 6= ai pour chaque i < k, ce qui démontre le résultat.

À partir de ce point, il suffit d’adapter les processus de la section précédente pour vérifier l’existence d’une liste chaînée de constantes toutes différentes au moins aussi longue que la solution. Nous modifions B pour que l’attaquant doive fournir un jeton senc(hp1, c, p2i, D) : charge à lui de pouvoir fournir les jetons suivants au moment de construire la solution. Les variables xp et x0p vérifient δ(xp) = δ(xp) = τnc, et la variable x0 satisfait δ(x0) = τc :

B = in(c0, senc(hxp, x0, x0pi, D)).out(c0, senc(h⊥U, ⊥V, xpi, K))

Nous modifions Pi(ci) en demandant à l’attaquant de fournir un jeton qui pointe vers la bonne adresse. À la fin, nous mettons à jour l’adresse cible pour la prochaine étape (le nonce n1du terme senc(hn1, m1, yp0i, K)). Les données yp, y0, yp0 sont des variables, et δ(yp) = δ(y0p) = τnc tandis que δ(y0) = τc. De plus, les jetons chiffrés par K contiennent maintenant une troisième information : en plus des pointeurs x et y vers les solutions en construction, ils contiennnent également un pointeur yp vers le dernier élément de la liste de constantes construite : de cette manière, l’attaquant doit fournir une constante différente pour chaque nouvelle tuile.

Pi(ci) = in(ci, senc(hyp0, y0, ypi, D)).in(ci, senc(hx, y, ypi, K). new n2.out(ci, senc(hx, u1i, n2i, U )).

. . .

new nki.out(ci, senc(hnki−1, uki

i , nkii, U )). new m2.out(ci, senc(hy, vi1, m2i, V )).

. . .

new mji.out(ci, senc(hmji−1, vji

i , mjii, V )). out(ci, senc(hnki, mji, yp0i, K)

Ces changements suffisent à garantir que l’attaquant ne peut obtenir la solution que s’il dispose d’autant de constantes que la taille de la solution, en nombre de tuiles. Les autres modifications (avec z0, z00 des variables de type τnc) sont triviales :

C(cj) =in(cj, senc(hx0, y0, z0i, K). in(cj, senc(hx0, z1, zpi, U ). in(cj, senc(hy0, z1, z0pi, V ). out(cj, senc(hzp, z0p, z0i, K) FP =in(cf, senc(hx00, y00, z00i, K). in(cf, senc(hx00, z2, ⊥Ui, U ). in(cf, senc(hy00, z2, ⊥Vi, V ). out(cf, a)

FQ=in(cf, senc(hx00, y00, z00i, K). in(cf, senc(hx00, z2, ⊥Ui, U ). in(cf, senc(hy00, z2, ⊥Vi, V ). out(cf, b)

Nous considérons les protocoles P et Q suivants :

P ={B, FP, ! new c01.out(c1, c01).P1(c10), . . . , ! new c0n.out(cn, c0n).Pn(c0n), ! new c0n+1.out(cn+1, c0n+1).C(c0n+1), ! new c0n+2.out(cn+2, c0n+2).V0(c0n+2), ! new c0n+3.out(cn+3, c0n+3).V1(c0n+3)}

Q ={B, FQ, ! new c01.out(c1, c01).P1(c10), . . . , ! new c0n.out(cn, c0n).Pn(c0n), ! new c0n+1.out(cn+1, c0n+1).C(c0n+1), ! new c0n+2.out(cn+2, c0n+2).V0(c0n+2), ! new c0n+3.out(cn+3, c0n+3).V1(c0n+3)}

Il est clair que P et Q sont conformes au système de type (T , δ). Concernant les ensembles de constantes, nous avons ΣP = ΣQ= {⊥V, ⊥U, ⊥nc}.

Proposition 3.2. Il existe un témoin quasiment typé de non-inclusion P 6vat Q par rapport à Σn] (ΣP∪ ΣQ) si, et seulement si, l’instance de PCP considérée admet une solution de longueur au plus n.

Démonstration informelle. Si l’instance de PCP admet une solution de longueur au plus n, il est facile de construire un témoin quasiment typé, en utilisant les constantes différentes pour obtenir une liste chaînée (par les nonces) de constantes.

Réciproquement, supposons qu’il existe un témoin quasiment typé de P 6vat Q par rapport à Σn] {⊥V, ⊥U, ⊥nc}. Nous admettons, comme pour la proposition 3.1, qu’il existe une solution de l’instance de PCP. Il reste à montrer que cette solution est de longueur au plus n.

La solution a été construite à travers les processus Pi et donc pour chaque tuile, l’attaquant a dû fournir senc(hyp, y0, yp0i, D) avec yp0 un pointeur vers une constante précédente. De plus, comme le témoin est quasiment typé, la variable y0 a dû être instanciée par un terme t tel que δ(t) 4 δ(y0) = τc : nécessairement t est une donnée. Comme l’attaquant ne connaît aucune autre donnée que les constantes de Σn] {⊥V, ⊥U, ⊥nc}, il a utilisé chaque fois l’une de ces constantes. D’après le lemme 3.3, les constantes utilisées sont deux à deux distinctes. Nécessairement, l’attaquant dispose de plus de constantes de type τ? qu’il n’y a de tuiles dans la solution, donc n > ` où ` est la longueur de la solution.