? p=nextprime(random(10^30)) %3 = 738873402423833494183027176953 ? q=nextprime(random(10^25)) %4 = 3787776806865662882378273 ? n=p*q %5 = 2798687536910915970127263606347911460948554197853542169 ? e=random(n) %6 = 1483959194866204179348536010284716655442139024915720699 ? phin=(p-1)*(q-1) %7 = 2798687536910915970127262867470721260308194351943986944 ? while(gcd(e,phin)!=1,e=e+1) ? e %8 = 1483959194866204179348536010284716655442139024915720699 ? d = lift(Mod(e,phin)^(-1)); %9 = 2113367928496305469541348387088632973457802358781610803 ? (e*d)%phin %10 = 1 ? log(n)/log(27) %11 = 38.03851667699197952338510248We can encode single blocks of up to 38 letters. Let's encode ``HARVARD'':
? m=8+27*1+27^2*18+27^3*22+27^4*1+27^5*18+27^6*4 %12 = 1808939906 ? E(x)=lift(Mod(x,n)^e) ? D(x)=lift(Mod(x,n)^d) ? secret_message = E(m) %14 = 625425724974078486559370130768554070421628674916144724 ? D(secret_message) %15 = 1808939906
The following complete PARI program automates the whole process, though it is a little clumsy. Call this file rsa.gp. It uses { and } so that functions can be extended over more than one line.
/* rsa.gp ------------------------------------------------ */
{alphabet=[" ","A","B","C","D","E","F","G","H","I","J","K","L","M",
"N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
}
{letter_to_number(l,
n)=
for(n=1,27,if(alphabet[n]==l,return(n-1)));
error("invalid input.")
}
{number_to_message(n,
s="")=
while(n>0, s = concat(s,alphabet[n%27+1]); n = n \ 27);
return(s)
}
{message_to_number(w,
i,n=0)=
for(i=1,length(w), n = n + 27^(i-1)*letter_to_number(w[i]));
return(n);
}
{make_rsa_key(len,
p,q,n,e,d)=
p = nextprime(random(10^(len/2)));
q = nextprime(random(10^(len/2+3)));
n = p*q; phin = (p-1)*(q-1);
e = random(phin);
while(gcd(e,phin)!=1,e=e+1);
d = lift(Mod(e,phin)^(-1));
return([n,e,d]);
}
encrypt(message, n, e) = lift(Mod(message_to_number(message),n)^e);
decrypt(secret, n, d) = number_to_message(lift(Mod(secret,n)^d));
/* rsa.gp ------------------------------------------------ */
Here is an example that uses the above little program.
? \r rsa
? setrand(1) \\ default random number seed is 1!
? rsa=make_rsa_key(20) \\ returns [n, e, d]
%2 = [89050154117716728145939, 33735260657253161660951,
49244741969289756040079]
? n = rsa[1]; e = rsa[2]; d = rsa[3];
? public_key = [n,e]
%3 = [89050154117716728145939, 33735260657253161660951]
? msg = ["H", "A", "R", "V", "A", "R", "D"]; \\ clumsy!!!
? secret = encrypt(msg,n,e)
%36 = 75524965161901413275866
? decrypt(secret, n, d)
%37 = "HARVARD"