? 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"