{-# LANGUAGE OverloadedStrings #-}
module Network.DomainAuth.Pubkey.RSAPub (
lookupPublicKey
) where
import Crypto.PubKey.RSA (PublicKey)
import Data.ASN1.BinaryEncoding (DER)
import Data.ASN1.Encoding (decodeASN1')
import Data.ASN1.Types (fromASN1)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as BS ()
import Data.X509 (PubKey(PubKeyRSA))
import Network.DNS (Domain)
import qualified Network.DNS as DNS
import Network.DomainAuth.Mail
import qualified Network.DomainAuth.Pubkey.Base64 as B
lookupPublicKey :: DNS.Resolver -> Domain -> IO (Maybe PublicKey)
lookupPublicKey :: Resolver -> ByteString -> IO (Maybe PublicKey)
lookupPublicKey Resolver
resolver ByteString
domain = do
Maybe ByteString
mpub <- Resolver -> ByteString -> IO (Maybe ByteString)
lookupPublicKey' Resolver
resolver ByteString
domain
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ case Maybe ByteString
mpub of
Maybe ByteString
Nothing -> forall a. Maybe a
Nothing
Just ByteString
pub -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ ByteString -> PublicKey
decodeRSAPublicyKey ByteString
pub
lookupPublicKey' :: DNS.Resolver -> Domain -> IO (Maybe ByteString)
lookupPublicKey' :: Resolver -> ByteString -> IO (Maybe ByteString)
lookupPublicKey' Resolver
resolver ByteString
domain = do
Either DNSError [ByteString]
ex <- Resolver -> ByteString -> IO (Either DNSError [ByteString])
DNS.lookupTXT Resolver
resolver ByteString
domain
case Either DNSError [ByteString]
ex of
Left DNSError
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
Right [ByteString]
x -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ [ByteString] -> Maybe ByteString
extractPub [ByteString]
x
extractPub :: [ByteString] -> Maybe ByteString
= forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup ByteString
"p" forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [(ByteString, ByteString)]
parseTaggedValue forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> a
head
decodeRSAPublicyKey :: ByteString -> PublicKey
decodeRSAPublicyKey :: ByteString -> PublicKey
decodeRSAPublicyKey ByteString
b64 = PublicKey
pub
where
der :: ByteString
der = ByteString -> ByteString
B.decode ByteString
b64
pub :: PublicKey
pub = case forall a.
ASN1Decoding a =>
a -> ByteString -> Either ASN1Error [ASN1]
decodeASN1' (forall a. HasCallStack => a
undefined :: DER) ByteString
der of
Left ASN1Error
_ -> forall a. HasCallStack => [Char] -> a
error [Char]
"decodeRSAPublicyKey (1)"
Right [ASN1]
ans1 -> case forall a. ASN1Object a => [ASN1] -> Either [Char] (a, [ASN1])
fromASN1 [ASN1]
ans1 of
Right (PubKeyRSA PublicKey
p,[]) -> PublicKey
p
Either [Char] (PubKey, [ASN1])
_ -> forall a. HasCallStack => [Char] -> a
error [Char]
"decodeRSAPublicyKey (2)"