(* RSA Demo,  Uebung Grundlegende Algorithmen,  
      WS2000/01,  
von Thomas Bayer,  
      bayert@in . tum . 
        de *) 


 (* 
      n1,  n2  =  Index der Primzahlen,  n1  =  130 bedeutet,  
      dass die 130.  Primzahl verwendet wird *) 
 (* 
      Ergebnis :  {{e, n}, {d, n}} *) 
Keys[n1_Integer,  
        n2_Integer]  :=  
      Module[{n, p, q, phi, e, d}, 
p  =  
          Prime[n1]; 
q  =  
          Prime[n2]; 
n  =  
          p q; 
phi  =  (p - 1) (q - 
                1); 
e  =  
          Mod[2^16  +  1, n]; 
If[e  ==  0,  
          e  =  3]; 
While[
          GCD[e, phi]  ≠  1,  
          e  =  e  +  2]; 
d  =  ExtendedGCD[e,  
              phi][[2, 1]]; 
If[d < 0, 
          d  =  d  +  phi]; 
Return[{{e, n}, {d, 
              n}}];
]

 (* Nachricht message wird mit oeffentlichen Schluessel verschluesselt, 
size  =  
        Laenge der Textbloecke, 
Ergebnis ist Liste ganzer Zahlen,  
      die uebertragen werden kann *) 

\(PublicEncryption[message_String, \ publicKey_List, \ 
        size_Integer:  3]\  := \ 
      Module[{intList, \ code}, 
intList\  = \ 
          TextToIntegers[message, size]; 
Return[
          Map[\((PowerMod[#, publicKey[\([\)\(1\)\(]\)], \ 
                  publicKey[\([\)\(2\)\(]\)]])\) &, 
            intList]];
]\ 

 (*\ 
      Entschluesselung\ von\ empfangener\ Nachricht\ mit\ Privaschluessel\ *) 
\)
PrivateDecryption[code_List,  privateKey_List]  :=  
      Module[{message,  coeffs}, 
coeffs  =  
          Map[(PowerMod[#, privateKey[[1]], 
                  privateKey[[2]]]) &, 
            code]; 
Return[
          IntegersToText[
            coeffs]];
]

 (* 
      Umwandlung eines Textes in Liste ganzer Zahlen,  
      size  =  Blockgroesse *) 

\(TextToIntegers[messageText_String, \ size_Integer]\  := \ 
      Module[{message, \ messagePart}, 
message\  = \ 
          messageText; 
Table[
If[
            StringLength[message]\  < \ size, \ \ message\  = \ 
              message\  <> \ 
                Block[{str\  = \ ""}, 
                  Do[str\  = \ str\  <> \ " ", {i, 1, 
                      size\  - \ StringLength[message]}]; 
                  str]; ]; 
messagePart\  = \ 
            StringTake[message, size]; 
message\  = \ 
            StringDrop[message, size]; 
StringToInteger[
            messagePart], 
{i, 1, 
            Ceiling[StringLength[messageText]/
                size]}]
]

 (*\ 
      Umkehrung\ zu\ TextToIntegers\ *) 
\)
\(IntegersToText[intList_List]\  := \ 
      Module[{message\  = \ "", \ str, \ 
          i}, 
Do[
str\  = \ 
            IntegerToString[
              intList[\([i]\)]]; 
message\  = \ 
            message\  <> \ str, 
{i, 1, 
            Length[intList]}]; 
Return[
          message];
]\ 

 (*\ 
      Wandle\ ein\ String\ in\ eine\ Zahl\ zur\ Basis\ 256\ um*) \ \)
StringToInteger[str_String]  :=  
      Module[{coeffs,  sum,  n,  
          base  =  256}, 
n  =  
          StringLength[str]; 
coeffs  =  
          Flatten[ToCharacterCode[
              Characters[str]]];  
sum  =  
          Sum[coeffs[[i]]* base^(n - i), {i, 1, 
              n}]; 
Return[
          sum]; 
]
  
IntegerToString[sum_Integer]  :=  
      Module[{coeffs,  temp,  str,  n,  
          p}, 
coeffs  =  
          IntegerDigits[sum, 256];  
Return[
          FromCharacterCode[coeffs]];
]