keystore 0.4.0.0 → 0.5.0.1
raw patch · 8 files changed
+302/−110 lines, 8 filesdep −attoparsec
Dependencies removed: attoparsec
Files
- changelog +10/−0
- examples/deploy/deploy.hs +1/−1
- keystore.cabal +1/−2
- src/Data/KeyStore/CLI.hs +1/−1
- src/Data/KeyStore/IO.hs +16/−12
- src/Data/KeyStore/KS/Opt.hs +18/−3
- src/Data/KeyStore/Sections.hs +252/−22
- src/Data/KeyStore/Types.hs +3/−69
changelog view
@@ -28,3 +28,13 @@ * Write Haddock annotations for Sections module. * Tidy cabal file * Revise readme and cabal documentation++0.5.0.0 Chris Dornan <chrisd@irisconnect.co.uk> 2014-07-27+ * expose getKeystore, getState, getCtxState, putCtxState in Data.KeyStore.IO+ * add proxy arguments to verifyKeystore & locateKeys in Data.KeyStore.Sections+ * opened up the export of Data.KeyStore.Types+ * added getSettingsOpt' to Data.KeyStore.KS.Opt+ * Fix #1, (section, key and host prefixes)++0.5.0.1 Chris Dornan <chrisd@irisconnect.co.uk> 2014-07-28+ * fix default sectionPWEnvVar in Sections class
examples/deploy/deploy.hs view
@@ -57,7 +57,7 @@ sign_ks ic = signKeystore ic sections >>= B.writeFile ks_mac_fp verify_ks :: Bool -> IC -> IO ()-verify_ks fatal ic = chk =<< catch (B.readFile ks_mac_fp >>= verifyKeystore ic) hdl+verify_ks fatal ic = chk =<< catch (B.readFile ks_mac_fp >>= verifyKeystore ic sections) hdl where chk True = return () chk False | fatal = error msg
keystore.cabal view
@@ -1,5 +1,5 @@ Name: keystore-Version: 0.4.0.0+Version: 0.5.0.1 Synopsis: Managing stores of secret things Homepage: http://github.com/cdornan/keystore Author: Chris Dornan@@ -160,7 +160,6 @@ crypto-random >= 0.0.7 , aeson >= 0.6.2 , aeson-pretty >= 0.7 ,- attoparsec >= 0.10.4.0 , base >= 4 , base64-bytestring >= 1.0 , byteable >= 0.1 ,
src/Data/KeyStore/CLI.hs view
@@ -18,7 +18,7 @@ version :: String-version = "0.4.0.0"+version = "0.5.0.1" cli :: IO () cli = parseCLI >>= command Nothing
src/Data/KeyStore/IO.hs view
@@ -62,6 +62,10 @@ , verify , verify_ , run+ , getKeystore+ , getState+ , getCtxState+ , putCtxState ) where import Data.KeyStore.IO.IC@@ -105,7 +109,7 @@ -- context to be cached between calls to these access functions. instanceCtx :: CtxParams -> IO IC instanceCtx cp =- do ctx_st <- get $ instanceCtx_ cp+ do ctx_st <- getCtxState $ instanceCtx_ cp IC cp . Just <$> newIORef ctx_st -- | This functional method will generate an IC that will not cache any@@ -268,7 +272,7 @@ -- | Return all of the keys in the keystore. keys :: IC -> IO [Key]-keys ic = Map.elems . _ks_keymap <$> get_keystore ic+keys ic = Map.elems . _ks_keymap <$> getKeystore ic -- | Delete a list of keys from the keystore. deleteKeys :: IC -> [Name] -> IO ()@@ -345,14 +349,14 @@ -- debug logging and errors. run :: IC -> KS a -> IO a run ic p =- do (ctx,st0) <- get ic+ do (ctx,st0) <- getCtxState ic st1 <- scan_env ctx st0 let msg = "[Keystore: " ++ ctx_store ctx ++"]\n" (e,st2,les) = run_ ctx st1 $ debugLog msg >> p r <- e2io e mapM_ (logit ctx) les st' <- backup_env ctx st2- put ic ctx st'+ putCtxState ic ctx st' return r scan_env :: Ctx -> State -> IO State@@ -371,20 +375,20 @@ where (e,st',les') = run_ ctx st0 backupKeysKS -get_keystore :: IC -> IO KeyStore-get_keystore ic = st_keystore <$> get_state ic+getKeystore :: IC -> IO KeyStore+getKeystore ic = st_keystore <$> getState ic -get_state :: IC -> IO State-get_state ic = snd <$> get ic+getState :: IC -> IO State+getState ic = snd <$> getCtxState ic -get :: IC -> IO (Ctx,State)-get IC{..} =+getCtxState :: IC -> IO (Ctx,State)+getCtxState IC{..} = case ic_cache of Nothing -> determineCtx ic_ctx_params Just rf -> readIORef rf -put :: IC -> Ctx -> State -> IO ()-put IC{..} ctx st =+putCtxState :: IC -> Ctx -> State -> IO ()+putCtxState IC{..} ctx st = do maybe (return ()) (flip writeIORef (ctx,st)) ic_cache when (not $ maybe False id $ cp_readonly ic_ctx_params) $ LBS.writeFile (ctx_store ctx) $ keyStoreBytes $ st_keystore st
src/Data/KeyStore/KS/Opt.hs view
@@ -7,9 +7,11 @@ , OptEnum(..) , opt_enum , getSettingsOpt+ , getSettingsOpt' , setSettingsOpt , opt__debug_enabled , opt__verify_enabled+ , opt__sections_fix , opt__backup_keys , opt__hash_comment , opt__hash_prf@@ -39,6 +41,7 @@ import Data.Maybe import Data.Char import Text.Printf+import Control.Applicative data Opt a@@ -58,9 +61,11 @@ deriving Show getSettingsOpt :: Opt a -> Settings -> a-getSettingsOpt Opt{..} (Settings hm) =- maybe opt_default opt_from $ HM.lookup (optName opt_enum) hm+getSettingsOpt opt = maybe (opt_default opt) id . getSettingsOpt' opt +getSettingsOpt' :: Opt a -> Settings -> Maybe a+getSettingsOpt' Opt{..} (Settings hm) = opt_from <$> HM.lookup (optName opt_enum) hm+ setSettingsOpt :: Opt a -> a -> Settings -> Settings setSettingsOpt Opt{..} x (Settings hm) = Settings $ HM.insert (optName opt_enum) (opt_to x) hm@@ -72,6 +77,9 @@ opt__verify_enabled :: Opt Bool opt__verify_enabled = bool_opt vfy_help False Verify__enabled +opt__sections_fix :: Opt Bool+opt__sections_fix = bool_opt sfx_help False Sections__fix+ opt__backup_keys :: Opt [Name] opt__backup_keys = backup_opt bku_help Backup__keys @@ -106,6 +114,7 @@ data OptEnum = Debug__enabled | Verify__enabled+ | Sections__fix | Backup__keys | Hash__comment | Hash__prf@@ -125,6 +134,7 @@ case enm of Debug__enabled -> Opt_ opt__debug_enabled Verify__enabled -> Opt_ opt__verify_enabled+ Sections__fix -> Opt_ opt__sections_fix Backup__keys -> Opt_ opt__backup_keys Hash__comment -> Opt_ opt__hash_comment Hash__prf -> Opt_ opt__hash_prf@@ -258,7 +268,7 @@ typ = T.intercalate "|" $ map shw [minBound..maxBound] -dbg_help, vfy_help, bku_help, hcm_help, hpr_help, hit_help, hwd_help,+dbg_help, vfy_help, sfx_help, bku_help, hcm_help, hpr_help, hit_help, hwd_help, hna_help, ccy_help, cpr_help, cit_help, cna_help :: [T.Text] dbg_help =@@ -269,6 +279,11 @@ , "in which the secret text loaded from environment" , "variables is checked against the stored MACs." , "These checks can consume a lot of compute time."+ ]+sfx_help =+ [ "Set when a 'Sections' keystore has been fixed so that"+ , "section, key and host names no longer contrained to avoid"+ , "prefixes." ] bku_help = [ "Controls the default keys that will be used to make secret copies"
src/Data/KeyStore/Sections.hs view
@@ -31,17 +31,23 @@ where import Data.KeyStore.IO+import Data.KeyStore.KS import qualified Data.Text as T import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy.Char8 as LBS import qualified Data.Aeson as A import qualified Data.HashMap.Strict as HM import qualified Data.Vector as V+import qualified Data.Map as Map import Data.Maybe import Data.List+import Data.Char import Data.Ord+import Data.String import Data.Monoid+import Control.Lens import Control.Applicative+import Control.Monad import Text.Printf import System.FilePath import Safe@@ -106,7 +112,7 @@ describeSection s = "The '" ++ encode s ++ "' Section." - sectionPWEnvVar = EnvVar . T.pack . ("KEY_" ++) . _name . passwordName+ sectionPWEnvVar = EnvVar . T.pack . ("KEY_pw_" ++) . encode -- | Sections are used to hold the top (master) key for the keystore,@@ -150,7 +156,7 @@ -- procedure. initialise :: Sections h s k => CtxParams -> KeyPredicate h s k -> IO () initialise cp kp = do- stgs <- scs kp Nothing+ stgs <- setSettingsOpt opt__sections_fix True <$> scs kp Nothing newKeyStore (the_keystore cp) stgs ic <- instanceCtx cp mapM_ (mks kp ic) [minBound..maxBound]@@ -165,26 +171,34 @@ -- | Rotate in a set of keys spwecified by the predicate. rotate :: Sections h s k => IC -> KeyPredicate h s k -> IO ()-rotate ic kp = sequence_ [ rotate' ic mb_h s k | (mb_h,s,k)<-host_keys++non_host_keys, kp mb_h s k ]+rotate ic kp = reformat ic' $ sequence_ [ rotate' ic mb_h s k | (mb_h,s,k)<-host_keys++non_host_keys, kp mb_h s k ] where host_keys = [ (Just h ,s,k) | k<-[minBound..maxBound], Just isp<-[keyIsHostIndexed k], h<-[minBound..maxBound], isp h, let s = key_section h k ] non_host_keys = [ (Nothing,s,k) | k<-[minBound..maxBound], Nothing <-[keyIsHostIndexed k], s<-[minBound..maxBound], keyIsInSection k s ] + ic' = kp_RFT kp ic+ -- | Retrieve the keys for a given host from the store. Note that the whole history for the given key is returned. -- Note also that the secret text may not be present if it si not accessible (depnding upon hwich section passwords -- are correctly bound in the process environment). Note also that the 'Retrieve' diagnostic should not fail if a -- coherent model has been ddefined for 'Sections'. retrieve :: Sections h s k => IC -> h -> k -> IO (Retrieve [Key])-retrieve ic h k = either (return . Left) (\nm->Right <$> locateKeys ic nm) $ keyName h k+retrieve ic h k = reformat ic' $ either (return . Left) (\nm->Right <$> locate_keys ic' nm) $ keyName h k+ where+ ic' = h_RFT h ic -- | Sign the keystore. (Requites the password for the signing section to be correctly -- bound in the environment) signKeystore :: Sections h s k => IC -> SECTIONS h s k -> IO B.ByteString-signKeystore ic scn = B.readFile (the_keystore $ ic_ctx_params ic) >>= sign_ ic (sgn_nme $ signing_key scn)+signKeystore ic scn = reformat ic' $ B.readFile (the_keystore $ ic_ctx_params ic) >>= sign_ ic (sgn_nme $ signing_key scn)+ where+ ic' = scn_RFT scn ic -- Verify that the signature for a keystore matches the keystore.-verifyKeystore :: IC -> B.ByteString -> IO Bool-verifyKeystore ic sig = B.readFile (the_keystore $ ic_ctx_params ic) >>= flip (verify_ ic) sig+verifyKeystore :: Sections h s k => IC -> SECTIONS h s k -> B.ByteString -> IO Bool+verifyKeystore ic scn sig = reformat ic' $ B.readFile (the_keystore $ ic_ctx_params ic) >>= flip (verify_ ic) sig+ where+ ic' = scn_RFT scn ic -- | A predicate specifying all of the keys in the store. noKeys :: KeyPredicate h s k@@ -254,28 +268,37 @@ -- to work the password for the top section (or the passwords for all of the sections -- must be bound if the store does not maintain a top key). secretKeySummary :: Sections h s k => IC -> SECTIONS h s k -> IO T.Text-secretKeySummary ic scn = T.unlines <$> mapM f (sections scn)+secretKeySummary ic scn = reformat ic' $ T.unlines <$> mapM f (sections scn) where f s = do sec <- T.pack . B.unpack <$> (showSecret ic False $ passwordName s) return $ T.concat ["export ",_EnvVar $ sectionPWEnvVar s,"=",sec] + ic' = scn_RFT scn ic+ -- | List a shell script for storing the public signing key for the store. publicKeySummary :: Sections h s k => IC -> SECTIONS h s k -> FilePath -> IO T.Text-publicKeySummary ic scn fp = f <$> showPublic ic True (sgn_nme $ signing_key scn)+publicKeySummary ic scn fp = reformat ic' $ f <$> showPublic ic True (sgn_nme $ signing_key scn) where f b = T.pack $ "echo '" ++ B.unpack b ++ "' >" ++ fp ++ "\n" + ic' = scn_RFT scn ic+ -- | List all of the keys that have the given name as their prefix. If the -- generic name of a key is given then it will list the complete history for -- the key, the current (or most recent) entry first.-locateKeys :: IC -> Name -> IO [Key]-locateKeys ic nm = sortBy (flip $ comparing _key_name) . filter yup <$> keys ic+locateKeys :: Sections h s k => IC -> SECTIONS h s k -> Name -> IO [Key]+locateKeys ic scn nm = locate_keys ic' nm where+ ic' = scn_RFT scn ic++locate_keys :: Sections h s k => REFORMAT h s k -> Name -> IO [Key]+locate_keys ic' nm = reformat ic' $ sortBy (flip $ comparing _key_name) . filter yup <$> keys ic+ where yup = isp . _key_name isp nm' = nm_s `isPrefixOf` _name nm'- nm_s = _name nm+ ic = _REFORMAT ic' -- | Return the genertic name for a given key thst is used by the specified -- host, returning a failure diagnostic if the host does not have such a key@@ -304,7 +327,7 @@ -- | The name of the key that stores the password for a given sections. passwordName :: Sections h s k => s -> Name-passwordName s = name' $ "pw_" ++ encode s+passwordName s = name' $ "/pw/" ++ encode s fmt :: Code a => (a->Bool) -> String fmt p = unwords [ encode h | h<-[minBound..maxBound], p h ]@@ -385,18 +408,18 @@ backup_password ic s sv_s = secureKey ic (passwordName s) $ safeguard [sve_nme sv_s] key_nme :: Sections h s k => Maybe h -> s -> k -> Name-key_nme mb_h s k = name' $ encode s ++ "_" ++ encode k ++ hst_sfx+key_nme mb_h s k = name' $ encode s ++ "/" ++ encode k ++ hst_sfx where- hst_sfx = maybe "" (\h -> "_" ++ encode h) mb_h+ hst_sfx = maybe "" (\h -> "/" ++ encode h) mb_h sgn_nme :: Sections h s k => s -> Name-sgn_nme s = name' $ encode s ++ "_keystore_signing_key"+sgn_nme s = name' $ encode s ++ "/keystore_signing_key" sve_nme :: Sections h s k => s -> Name-sve_nme s = name' $ "save_" ++ encode s+sve_nme s = name' $ "/save/" ++ encode s scn_pattern :: Sections h s k => s -> Pattern-scn_pattern s = pattern $ "^" ++ encode s ++ "_.*"+scn_pattern s = pattern $ "^" ++ encode s ++ "/.*" unique_nme :: IC -> Name -> IO Name unique_nme ic nm =@@ -411,10 +434,7 @@ c_nms = [ nm | i<-[length nms+1..], let nm=nname i nm0, nm `notElem` nms ] nname :: Int -> Name -> Name- nname i nm_ = name' $ _name nm_ ++ printf "_%03d" i--name' :: String -> Name-name' = either (error.show) id . name+ nname i nm_ = name' $ _name nm_ ++ printf "/%03d" i the_keystore :: CtxParams -> FilePath the_keystore = maybe "keystore.json" id . cp_store@@ -432,3 +452,213 @@ } where fp sfx = sd </> encode k ++ sfx+++--------------------------------------------------------------------------------+--+-- Regormating the KeyStore Names to Allow Prefixes (#3)+--+--------------------------------------------------------------------------------+++reformat :: Sections h s k => REFORMAT h s k -> IO a -> IO a+reformat rft@(REFORMAT ic) p = reformat_ic (encoding rft) ic >> p++-- Proxy city!++data REFORMAT h s k = REFORMAT { _REFORMAT :: IC }++data CODE a = CODE++scn_RFT :: SECTIONS h s k -> IC -> REFORMAT h s k+kp_RFT :: KeyPredicate h s k -> IC -> REFORMAT h s k+h_RFT :: h -> IC -> REFORMAT h s k++scn_RFT _ ic = REFORMAT ic+kp_RFT _ ic = REFORMAT ic+h_RFT _ ic = REFORMAT ic++reformat_ic :: Encoding -> IC -> IO ()+reformat_ic enc ic = do+ (ctx,st) <- getCtxState ic+ putCtxState ic ctx $+ st { st_keystore = reformat_keystore enc $ st_keystore st }++reformat_keystore :: Encoding -> KeyStore -> KeyStore+reformat_keystore enc ks =+ case getSettingsOpt opt__sections_fix $ _cfg_settings $ _ks_config ks of+ True -> ks+ False -> over ks_config (reformat_config enc) $+ over ks_keymap (reformat_key_map enc) ks++reformat_config :: Encoding -> Configuration -> Configuration+reformat_config enc =+ over cfg_settings (setSettingsOpt opt__sections_fix True) .+ over cfg_settings (reformat_settings enc) .+ over cfg_triggers (reformat_triggers enc)++reformat_triggers :: Encoding -> TriggerMap -> TriggerMap+reformat_triggers enc = Map.map $+ over trg_pattern (reformat_pattern enc) .+ over trg_settings (reformat_settings enc)++reformat_settings :: Encoding -> Settings -> Settings+reformat_settings enc stgs =+ case getSettingsOpt' opt__backup_keys stgs of+ Nothing -> stgs+ Just nms -> setSettingsOpt opt__backup_keys (map (reformat_name enc) nms) stgs++reformat_pattern :: Encoding -> Pattern -> Pattern+reformat_pattern enc pat = maybe oops id $ run_munch (m_pattern enc) $ _pat_string pat+ where+ oops = error $ "reformat_pattern: bad pattern format: " ++ _pat_string pat++reformat_key_map :: Encoding -> KeyMap -> KeyMap+reformat_key_map enc km = Map.fromList [ (reformat_name enc nm,r_ky ky) | (nm,ky)<-Map.toList km ]+ where+ r_ky =+ over key_name (reformat_name enc) .+ over key_secret_copies (reformat_ecm enc)++reformat_ecm :: Encoding -> EncrypedCopyMap -> EncrypedCopyMap+reformat_ecm enc ecm = Map.fromList [ (reformat_sg enc sg,r_ec ec) | (sg,ec)<-Map.toList ecm ]+ where+ r_ec = over ec_safeguard (reformat_sg enc)++reformat_sg :: Encoding -> Safeguard -> Safeguard+reformat_sg enc = safeguard . map (reformat_name enc) . safeguardKeys++reformat_name :: Encoding -> Name -> Name+reformat_name enc nm = maybe oops id $ run_munch (m_name enc) $ _name nm+ where+ oops = error $ "reformat_name: bad name format: " ++ _name nm++m_pattern :: Encoding -> Munch Pattern+m_pattern enc = do+ munch_ "^"+ s <- enc_s enc+ munch_ "_.*"+ return $ fromString $ "^" ++ s ++ "/.*"++m_name, m_save, m_pw, m_section :: Encoding -> Munch Name++m_name enc = m_save enc <|> m_pw enc <|> m_section enc++m_save enc = do+ munch_ "save_"+ s <- enc_s enc+ return $ name' $ "/save/" ++ s++m_pw enc = do+ munch_ "pw_"+ s <- enc_s enc+ return $ name' $ "/pw/" ++ s++m_section enc = do+ s <- enc_s enc+ m_section_signing enc s <|> m_section_key enc s++m_section_key, m_section_signing :: Encoding -> String -> Munch Name++m_section_signing _ s = do+ munch_ "_keystore_signing_key"+ return $ name' $ s ++ "/keystore_signing_key"++m_section_key enc s = do+ munch_ "_"+ k <- enc_k enc+ m_section_key_host enc s k <|> m_section_key_vrn enc s k++m_section_key_vrn, m_section_key_host :: Encoding -> String -> String -> Munch Name++m_section_key_vrn _ s k = do+ munch_ "_"+ v <- munch_vrn+ return $ name' $ s ++"/" ++ k ++ "/" ++ v++m_section_key_host enc s k = do+ munch_ "_"+ h <- enc_h enc+ munch_ "_"+ v <- munch_vrn+ return $ name' $ s ++"/" ++ k ++ "/" ++ h ++ "/" ++ v++munch_vrn :: Munch String+munch_vrn = do+ c1 <- munch1 isDigit+ c2 <- munch1 isDigit+ c3 <- munch1 isDigit+ return [c1,c2,c3]++-- Capturing the host, section and key encodings in a nice convenient+-- monotype that we can pass around.++data Encoding =+ Encoding+ { enc_h, enc_s, enc_k :: Munch String+ }++encoding :: Sections h s k => REFORMAT h s k -> Encoding+encoding rft =+ Encoding+ { enc_h = code_m $ host_c rft+ , enc_s = code_m $ section_c rft+ , enc_k = code_m $ key_c rft+ }+ where+ host_c :: Sections h s k => REFORMAT h s k -> CODE h+ host_c _ = CODE++ section_c :: Sections h s k => REFORMAT h s k -> CODE s+ section_c _ = CODE++ key_c :: Sections h s k => REFORMAT h s k -> CODE k+ key_c _ = CODE++code_m :: Code a => CODE a -> Munch String+code_m c = foldr (<|>) empty $ [ munch $ encode x | x<-bds c ]+ where+ bds :: Code a => CODE a -> [a]+ bds _ = [minBound..maxBound]++-- our Munch Monad++newtype Munch a = Munch { _Munch :: String -> Maybe (a,String) }++instance Functor Munch where+ fmap f m = m >>= \x -> return $ f x++instance Applicative Munch where+ pure = return+ (<*>) = ap++instance Alternative Munch where+ empty = Munch $ const Nothing+ (<|>) x y = Munch $ \s -> _Munch x s <|> _Munch y s++instance Monad Munch where+ return x = Munch $ \s -> Just (x,s)+ (>>=) m f = Munch $ \s -> _Munch m s >>= \(x,s') -> _Munch (f x) s'++run_munch :: Munch a -> String -> Maybe a+run_munch (Munch f) str = case f str of+ Just (x,"") -> Just x+ _ -> Nothing++munch1 :: (Char->Bool) -> Munch Char+munch1 p = Munch $ \str -> case str of+ c:t | p c -> Just (c,t)+ _ -> Nothing++munch_ :: String -> Munch ()+munch_ s = const () <$> munch s++munch :: String -> Munch String+munch str_p = Munch $ \str -> case str_p `isPrefixOf` str of+ True -> Just (str_p,drop (length str_p) str)+ False -> Nothing++--------------------------------------------------------------------------------++name' :: String -> Name+name' = either (error.show) id . name
src/Data/KeyStore/Types.hs view
@@ -27,77 +27,11 @@ -- marked down in <https://github.com/cdornan/keystore/blob/master/schema.md>. module Data.KeyStore.Types- ( KeyStore(..)- , ks_keymap- , ks_config- , Configuration(..)- , TriggerMap- , Trigger(..)- , Settings(..)- , cfg_settings- , cfg_triggers- , TextJsonAssoc(..)- , KeyMap- , NameKeyAssoc(..)- , Key(..)- , key_name- , key_comment- , key_identity- , key_is_binary- , key_env_var- , key_hash- , key_public- , key_secret_copies- , key_clear_text- , key_clear_private- , key_created_at- , Hash(..)- , HashDescription(..)- , EncrypedCopyMap- , EncrypedCopy(..)- , EncrypedCopyData(..)- , RSASecretData(..)- , AESSecretData(..)- , PublicKey(..)- , PrivateKey(..)- , Cipher(..)- , _text_Cipher- , HashPRF(..)- , _text_HashPRF- , EncryptionKey(..)- , FragmentID(..)- , Pattern(..)- , Iterations(..)- , Octets(..)- , Identity(..)- , SettingID(..)- , TriggerID(..)- , Comment(..)- , EnvVar(..)- , ClearText(..)- , Salt(..)- , IV(..)- , HashData(..)- , AESKey(..)- , SecretData(..)- , RSAEncryptedKey(..)- , RSASecretBytes(..)- , RSASignature(..)- , EncryptionPacket(..)- , SignaturePacket(..)- , Void(..)- , Dirctn(..)- , void_- , pattern- , defaultSettings- , checkSettingsCollisions- , emptyKeyStore- , emptyKeyMap- , defaultConfiguration- , pbkdf- , keyWidth+ ( module Data.KeyStore.Types , module Data.KeyStore.Types.NameAndSafeguard , module Data.KeyStore.Types.E+ , PublicKey(..)+ , PrivateKey(..) ) where import Data.KeyStore.Types.Schema