you're telling me a puppy coded this??
module Puppy.Crypto.RSA where

import Data.List (singleton)
import Effectful
import Effectful.Fail
import qualified Crypto.PubKey.RSA  as RSA
import qualified Crypto.Store.PKCS8 as PKCS8
import qualified Crypto.Store.X509  as X509
import qualified Data.ByteString    as BS
import qualified Data.X509          as X509

encodePrivateKey :: RSA.PrivateKey -> BS.ByteString
encodePrivateKey
  = PKCS8.writeKeyFileToMemory PKCS8.PKCS8Format
  . singleton
  . X509.PrivKeyRSA

decodePrivateKey :: BS.ByteString -> Maybe RSA.PrivateKey
decodePrivateKey
  = extract
  . PKCS8.readKeyFileFromMemory
  where
    extract ((PKCS8.Unprotected (X509.PrivKeyRSA x)):_) = Just x
    extract (_ : rest) = extract rest
    extract _ = Nothing

encodePublicKey :: RSA.PublicKey -> BS.ByteString
encodePublicKey
  = X509.writePubKeyFileToMemory
  . singleton
  . X509.PubKeyRSA

decodePublicKey :: BS.ByteString -> Maybe RSA.PublicKey
decodePublicKey
  = extract
  . X509.readPubKeyFileFromMemory
  where
    extract ((X509.PubKeyRSA x):_) = Just x
    extract (_ : rest) = extract rest
    extract _ = Nothing

readKeyFile :: (IOE :> es, Fail :> es) => FilePath -> Eff es RSA.PrivateKey
readKeyFile path = liftIO (decodePrivateKey <$> BS.readFile path) >>= \case
  Just x  -> return x
  Nothing -> fail "Bad key file"