我有一個函式可以使用 HsOpenSsl 的readPrivateKey函式讀取 Rsa 密鑰,不幸的是,我的函式的簽名是 this String -> IO (Maybe (IO Maybe RsaKey))。我需要 PEM 格式和一個 Cryptonite.RSA 密鑰,我撰寫了一個函式mkRsaKey來從 PEM 格式的字串中生成它。
代碼如下:
import qualified Crypto.PubKey.RSA as Rsa --from cryptonite
import OpenSSL.EVP.PKey -- from HsOpenSSL
import OpenSSL.PEM -- from HsOpenSSL
import OpenSSL.RSA -- from HsOpenSSL
import Prelude
data RsaKey = RsaKey
{ rsaKeyCryptoniteKey :: Rsa.PrivateKey,
rsaKeyStringRepr :: String
}
deriving (Show)
openSslKeyToCryptoniteKey :: RSAKeyPair -> Maybe Rsa.PrivateKey
openSslKeyToCryptoniteKey key = do
let d = rsaD key
let p = rsaP key
let q = rsaQ key
let mdP = rsaDMP1 key
let mdQ = rsaDMQ1 key
let mqinv = rsaIQMP key
let size = rsaSize key
let n = rsaN key
let e = rsaE key
dP <- mdP
dQ <- mdQ
qinv <- mqinv
let pub = Rsa.PublicKey size n e
return $ Rsa.PrivateKey pub d p q dP dQ qinv
openSslKeyToRsaKey :: RSAKeyPair -> IO (Maybe RsaKey)
openSslKeyToRsaKey key = do
stringRepr <- writePublicKey key
let maybeCryptoKey = openSslKeyToCryptoniteKey key
return $ do
cryptoKey <- maybeCryptoKey
return $ RsaKey cryptoKey stringRepr
mkRsaKey :: String -> IO (Maybe (IO (Maybe RsaKey)))
mkRsaKey privateKey = do
someOpenSslKey <- readPrivateKey privateKey PwNone
let openSslKey = toKeyPair someOpenSslKey
return $ openSslKeyToRsaKey <$> openSslKey
現在,正如您所看到的,型別簽名在我看來并不是我想要的最佳狀態IO (Maybe RsaKey)。我怎樣才能做到這一點?
編輯:
我實際上設法做到了,但我正在使用unsafePerformIO:
mkRsaKey :: String -> IO (Maybe RsaKey)
mkRsaKey privateKey = do
someOpenSslKey <- readPrivateKey privateKey PwNone
return $ do
openSslKey <- toKeyPair someOpenSslKey
unsafePerformIO (openSslKeyToRsaKey $ openSslKey)
據我所知你永遠不應該使用unsafePerformIO沒有它有什么方法可以做到這一點嗎?
uj5u.com熱心網友回復:
很好的發現case。這絕對不是您應該使用的地方unsafePerformIO。這是一種更緊湊的方式,為了好玩。
flattenMaybe :: (Monad m) => m (Maybe (m (Maybe a))) -> m (Maybe a)
flattenMaybe m = m >>= fromMaybe (return Nothing)
為了更有趣,像這樣壓平層的能力是 monad 的特征能力;我們只是在 上使用該能力m (Maybe ...),也稱為MaybeT。所以我們也可以這樣寫:
flattenMaybe = runMaybeT . join . fmap MaybeT . MaybeT
進行必要的包裝/展開以使用joinat MaybeT m (MaybeT m a) -> MaybeT m a。
uj5u.com熱心網友回復:
找到一種沒有unsafePerformIO技巧的方法是使用 case 陳述句,該陳述句僅在Nothingcase 中使用 return 函式。這是實作:
mkRsaKey :: String -> IO (Maybe RsaKey)
mkRsaKey privateKey = do
someOpenSslKey <- readPrivateKey privateKey PwNone
let maybeOpenSslKey = toKeyPair someOpenSslKey
case maybeOpenSslKey of
Just key -> openSslKeyToRsaKey key
Nothing -> return Nothing
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/393118.html
上一篇:產品型別轉換為元組
