TP11-sol.cas
4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
restart;maple_mode(1);cas_setup(0,0,0,1,0,1e-10,10,[1,50,0,25],0,0,0); #radians,pas de cmplx, pas de Sqrt
/* ------------------------------------------------Exercice---------------------------------------------*/
time(p:=nextprime(10^50)):
time(isprime(p)):
time(is_pseudoprime(p)):
/* le temps de isprime est trop long pour avoir ete utilise pour£ trouver le nombre premier avec nextprime. La doc confirme bien que£ nextprime donne un pseudopremier.*/
i:=20;n:=nextprime(10^i)*nextprime(20^i);
ifactor(n);
/* a partir de i=30 ca ne repond plus?*/
p:=nextprime(nextprime(10^30)*nextprime(20^30));
ifactor(p-1); #ca marche souvent
pari():;
pari_isprime(p,1);
/* Les grands nombres premiers apparaissant dans le certificat sont eux£m\^eme certifi\'es, ce qui explique les crochets emboit\'es.*/
/* On a cree n avec de petits facteurs, on arrive a le factoriser*/
i:=0;l:=[];
while i<1 do
n:=1;for j from 1 to 10 do n:=n*(1+rand(10000)) od;
if is_pseudoprime(n+1)>0 then p:=n+1;i++; fi;
od;
Divn:=transpose(ifactors(p-1)[2]);
divn:=Divn[1];
expn:=Divn[2];
/* On cherche maintenant le certificat. Pour chaque premier divisant p-1 on trouve£un element d'ordre la puissance maximale de ce diviseur qui divise p-1. On£utilisera factors et powmod*/
certifs:=[];
for i in divn do
a:=2;
while powermod(a,(p-1)/i,p)=1 do a:=1+rand(p-1) od;
certifs:=[op(certifs),a];
od;
g:=1;
for i from 1 to dim(divn) do g:=mods(g*powmod(certifs[i],(p-1)/(divn[i]^expn[i]),p),p) od;
/* seq(powmod(g,i,p),i=divisors(p-1));# NON! ne pas le faire trop de diviseurs!*/
maple_mode(0); // on bascule en mode xcas et l'on cree le 1 de Z/pZ
unp:= 1 % p;
maple_mode(1); #on retourne en mode maple.
unp:=makemod(1,p); #la meme chose directement, mais c'est mal documente.
pari():; #on charge pari une fois pour toute.
unp:=Mod(1,p); #via pari, mais apres avoir charge pari avec: pari();
/* On peut maitenant multiplier un entier par ce nombre modulaire pour passer£automatiquement dans Z/pZ*/
gzp:=g*unp;
znorder(gzp);# ou bien on pouvait faire directement:
if znorder(Mod(g,p))==p-1 then print("ca fait bien p-1") fi;
p:=nextprime(10^13);i:=0;l:=[];
while i<10 do
if is_pseudoprime(4*p+1)>0 then l:=[op(l),4*p+1];i++; fi;
p:=nextprime(p);
od:l;
p:=nextprime(10^13+100);
g:=pari_znprimroot(p);
pari_znlog(3,Mod(g,p)); #il reussit
ifactor(p-1);
/* p-1 a de petits facteurs premiers, on peut donc resoudre le probleme£du log discret. Dans le cas suivant ca ne marche plus.*/
pdifficile:=l[3];
p:=pdifficile;
g:=pari_znprimroot(p);
#pari_znlog(3,Mod(g,p)); #depasse la memoire max de pari
/* Le nombre de genereurs de (Z/pZ)^x est le nombre d'inversibles dans Z/(p-1)Z,£c'est donc phi(p-1). la Proba de trouver un generateur en piochant au hasard£est donc de s=phi(p-1)/p. On a au moins 95 pour cent de chance d'avoir un£generateur en n tirages ssi (1-s)^n<0.05 ssi n>ln(0.05)/ln(1-s).£ Autre maniere de commencer avec une liste vide, on utilise le symbole: NULL*/
l:=NULL;for i from 1 to 30 do p:=nextprime(rand(10^20)); l:=l,evalf(euler(p-1)/p) od;
seq(log(0.05)/log(1-s),s=[l]);
/* Lorsque pari_znprimroot ne retourne pas 2, son ordre est bien different de£p-1. On peut donc conjecturer que pari essaye successivement des petits£entiers. Cependant il faut remarquer que le temps de znprimroot est directement£relie au temps de factorisation de p-1. Donc pari semble avoir factorise p-1*/
l:=NULL;for i from 1 to 30 do p:=nextprime(rand(10^20)); l:=l,[pari_znprimroot(p),p-znorder(Mod(2,p))] od;
p1:=100000000003677906312417649500520066316186689905131;
time(ifactor(p1-1)):
time(znprimroot(p1)):
time(znorder(Mod(2,p1))):
p2:=nextprime(p1);
time(ifactor(p2-1)):
time(znprimroot(p2)):
time(znorder(Mod(2,p2))):
/* -------------------------------------EXERCICE---------------------------------------------*/
p:=pdifficile;
/* b,e pas trop petits par rapport a p, pour que le modulo p melange£ vraiment.*/
message:="ABCDA, Remarquez que des lettres identiques ne sont pas codees de la meme maniere!";asc(message);
asc(messsage)-[seq(65,i=1..length(message))];
b:=12345;e:=54321; igcd(e,p-1); B:=powmod(b,e,p);
l:=asc(message);k:=[seq(rand(50),i=1..length(message))];
C:=[seq([(b^k[i]) mod p,(l[i]*B^k[i]) mod p],i=1..length(message))];#le message crypte
ee:=p-1-e;#c'est -e [p-1] qui nous interesse
/* L'astuce est que (B^k)=((b^e)^k) qui vaut par commutativit\'e des la£ composition des application B:x->x^k et A:x->x^e ((b^k)^e). £Le principe a retenir, est qu'en crypto on a juste besoin£d'operations A,B qui commutent, et que la donnee de A de donne pas£A^(-1) */
decrypt:=[seq(irem(powmod(C[i][1],ee,p)*C[i][2],p),i=1..length(message))];
char(decrypt);