\section{User Interface} \ignore{ \begin{code} module RSAMain (main) where import IO import System (getArgs,getProgName,exitFailure) import Random (getStdRandom) import RSA import Brianweb.Misc import Brianweb.Math.NumberTheory import Brianweb.List (splitOn) \end{code} } \begin{code} commands :: [(String,[String] -> IO())] commands = [ ("encrypt", encryptCommand False), ("decrypt", encryptCommand True), ("genkey",genKeyCommand), ("decryptwithoutd",decryptWithoutD) ] \end{code} \begin{code} encryptCommand :: Bool -> [String] -> IO() encryptCommand _ [pq',e',m'] = do pq <- readIntegral pq' e <- readIntegral e' m <- readIntegral m' putStrLn $ show $ rsaEncrypt pq e m encryptCommand False _ = fail "encrypt requires pq, e, and m values" encryptCommand True _ = fail "decrypt requires pq, d, and m values" \end{code} \begin{code} genKeyCommand :: [String] -> IO() genKeyCommand [bits'] = do bits <- readIntegral bits' (p,q,e,d) <- getStdRandom(rsaGenKey bits) putStrLn $ "p: " ++ show p putStrLn $ "q: " ++ show q putStrLn $ "pq: " ++ show (p*q) putStrLn $ "e: " ++ show e putStrLn $ "d: " ++ show d genKeyCommand _ = fail "genkey requires a bits argument" \end{code} % FEATURE: Probably should make this pure and stick it in RSA.lhs \begin{code} decryptWithoutD :: [String] -> IO() decryptWithoutD [pq',e',c'] = do e <- readIntegral e' c <- readIntegral c' (p,q) <- case splitOn (==',') pq' of (_,[]) -> do pq <- readIntegral pq' putStrLn $ "Need to factor " ++ show pq ++ ". This could take a while..." let factors = factor pq putStrLn $ "factorization: " ++ show factors case factors of [(p',1),(q',1)] -> return (p',q') _ -> fail $ show pq ++ " doesn't factor to two primes" pair -> tupleMapM readIntegral pair let phi = (p-1)*(q-1) d = multInvMod phi e putStrLn $ "d: " ++ show d putStrLn $ "m: " ++ (show $ rsaEncrypt (p*q) d c) decryptWithoutD _ = fail "decryptwithoutd requires pq (or p,q if known) e and m" \end{code} \begin{code} main :: IO() main = do args <- getArgs case args of (command:args') -> do action <- partialLookup command commands "command" action args' `catch` \e -> if isUserError e then do hPutStrLn stderr $ ioeGetErrorString e exitFailure else ioError e _ -> usage where usage = do me <- getProgName hPutStrLn stderr $ unlines [ "Usage: " ++ me ++ " cmd args", " cmd is " ++ (englishJoin "or" $ map fst commands)] exitFailure \end{code}