# RSA Demonstration package # Copyright: Erich Kaltofen, 8/9/1989 (Mathematica) and 8/10/1992 (Maple) # Permission to use provided the copyright notice is not removed. `convert/toASCII`:=proc(string) # hack for conversion of characters to their ascii codes # (courtesy G. Fee, Waterloo Maple Software, 8/9/92) local addr, lst, op3, code, i; # addr := addressof(string); # lst := disassemble(addr); # op3 := lst[3]; # code := convert(op3, base, 256); # code[4] # generally usable code (EK) if string = `.` then RETURN(46) fi; for i to 128 do if substring(ctrlstring, i..i) = string then RETURN(i-1) fi od; print(`Try to convert unprintable character to ASCII`); RETURN(0); end; # printable characters for conversion form ascii values ctrlstring := `.......... ..................... !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ(\\)^_``abcdefghijklmnopqrstuvwxyz{|}~.`; `convert/fromASCII`:=proc(ascii_val) # converts ascii value back to printable character substring(ctrlstring, (ascii_val+1)..(ascii_val+1)) end; encode := proc(ClearText, PublicKey) local b, i, ints, codedints; b := blocking_factor(PublicKey); ints := pack(ClearText, b); codedints := []; for i from 1 to nops(ints) do codedints := [op(codedints), scramble(ints[i], PublicKey)] od; RETURN(codedints) end; decode := proc(CodedInts, PrivateKeys) local b, i, ints, P, Q, magicexp; P := PrivateKeys[1]; Q := PrivateKeys[2]; magicexp := iquo(2*(P-1)*(Q-1) + 1, 3); publickey := P*Q; ints:=[]; for i to nops(CodedInts) do ints := [op(ints), unscramble(CodedInts[i], magicexp, publickey) ] od; b := blocking_factor(publickey); RETURN(unpack(ints, b)) end; find_key := proc(Start) # Find a probabilistic prime P>=Start with irem(P, 3)=2 local int; int := Start; if irem(int, 2) = 0 then int := int + 1 fi; if irem( int, 3 ) = 0 then int := int + 2 fi; if irem( int, 3 ) = 1 then int := int + 4 fi; while not(isprime(int)) do int := int + 6 od; # should check if save against p-1 or elliptic factoring algorithm RETURN(int) end; # internal functions blocking_factor := proc(Key) iquo(trunc( evalf(log(Key)/log(2)) ), 8) end; pack := proc(text, b) local chars, len, i, j, k, ints, code, c, nb, blanks; nb := length(text)/b; if type(nb, integer) then len := nb; else len := trunc(nb + 1); fi; # append some blanks so that blocking doesn't run out of characters blanks := ``; for i to len*b - length(text) do blanks := `` . blanks . ` `; od; # this hack fails for very long keys chars := text . blanks; j := 0; ints := []; for i to len do code := 0; for k to b do j := j+1; code := 2**8 * code + convert(substring(chars, j..j), toASCII); od; ints := [op(ints), code]; od; RETURN(ints) end; unpack:= proc(intlist, b) local len, i, j, block, text; len := nops(intlist); text := ``; for i to len do block := ``; j := intlist[i]; for k to b do block := cat(convert(irem(j, 2**8), fromASCII), block); j := iquo(j, 2**8) od; text := cat(text, block); od; RETURN(text) end; scramble:=proc(Int, PublicKey) irem( irem( Int*Int, PublicKey) * Int, PublicKey) end; unscramble:=proc(CodedInt, MagicExp, PublicKey) power_mod( CodedInt, MagicExp, PublicKey) end; power_mod:=proc(a, e, m) # compute a^e mod m local half; if e = 0 then RETURN(1) fi; if e = 1 then RETURN(irem(a, m)) fi; half := power_mod(a, iquo(e, 2), m); if type(e,even) then RETURN(Expand(half*half) mod m) else RETURN(Expand(half*half*a) mod m) fi end;