module RSAMaker 
   where
import Data.Char ( chr )

encode :: String -> [Integer]
encode s = map (toInteger . fromEnum ) s

rsa_encode :: Integer -> Integer -> [Integer] -> [Integer]
rsa_encode n e numbers = map (\num -> mod ( num ^ e ) n ) numbers

rsa_decode :: Integer -> Integer -> [Integer] -> [Integer]
rsa_decode d n ciphers = map (\c -> mod ( c ^ d ) n ) ciphers

decode :: [Integer] -> String
decode encoded = map ( chr . fromInteger ) encoded 

divisors :: Integer -> [Integer]
divisors n = [m | m <- [1..n] , mod n m == 0 ]

isPrime :: Integer -> Bool
isPrime n = divisors n == [1,n]

totient :: Integer -> Integer -> Integer
totient prime1 prime2 = (prime1 - 1 ) * ( prime2 - 1 ) 

myE :: Integer -> Integer
myE tot = head [n | n <- [2..tot - 1] , gcd n tot == 1]

myD :: Integer -> Integer -> Integer  -> Integer
myD e n phi = head [d | d <- [1..n] , mod ( d * e ) phi == 1]

main = do 
   putStrLn "Enter a test text!"
   text <- getLine
   let primes = take 90 $ filter isPrime [1..]
       p1     = last primes
       p2     = last $ init primes
       tot    = totient p1 p2
       e      =  myE tot
       n   = p1  * p2 
       rsa_encoded  =  rsa_encode n e $ encode text
       d  =  myD e n tot
       encrypted = concatMap show rsa_encoded
       decrypted = decode $ rsa_decode d n rsa_encoded 
   putStrLn ("Encrypted: " ++ encrypted ) 
   putStrLn ("And now decrypted: " ++ decrypted )