diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # Revision history for z-botan
 
+## 0.2.0.0  -- 2020-05-14
+
+* Change `EMEPadding` to `EncParam`, add `SM2EncParam`.
+* Change `EMSA` to `SignParam`, add `Ed25519Pure`, `Ed25519ph`, `Ed25519Hash`, `SM2SignParam`.
+* Change PubKey decrypt, verify type to `IO`. 
+
 ## 0.2.0.0  -- 2020-05-12
 
 * Simplify `KeyType` in `Z.Crypto.PubKey`.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
 * MAC.
 * Key derivation functions.
 * Password hash.
-* Constant time multiple precision integers.
+* Multiple precision integers.
 * Public key creation, import and export.
 * Public key encryption/decryption
 * Diffie-Hellman key exchange.
diff --git a/Z-Botan.cabal b/Z-Botan.cabal
--- a/Z-Botan.cabal
+++ b/Z-Botan.cabal
@@ -1,15 +1,13 @@
 cabal-version:      2.4
 name:               Z-Botan
-version:            0.2.0.0
+version:            0.3.0.0
 synopsis:           Crypto for Haskell
 description:        Crypto for Haskell, based on <http://botan.randombit.net/ Botan>
 license:            BSD-3-Clause
 license-file:       LICENSE
-author:             Dong Han, Tao He
+author:             Z.Haskell Contributors
 maintainer:         winterland1989@gmail.com
-copyright:
-  (c) Z.Haskell Contributors, 2017-2020
-
+copyright:          (c) Z.Haskell Contributors, 2017-2020
 category:           Data
 build-type:         Custom
 homepage:           https://github.com/ZHaskell/z-botan
diff --git a/Z/Crypto/Cipher.hs b/Z/Crypto/Cipher.hs
--- a/Z/Crypto/Cipher.hs
+++ b/Z/Crypto/Cipher.hs
@@ -233,7 +233,7 @@
     deriving anyclass T.Print
 
 -- | Pass 'BlockCipher' to FFI as 'botan_block_cipher_t'.
-withBlockCipher :: HasCallStack => BlockCipher -> (BotanStructT -> IO r) -> IO r
+withBlockCipher :: BlockCipher -> (BotanStructT -> IO r) -> IO r
 {-# INLINABLE withBlockCipher #-}
 withBlockCipher (BlockCipher bc _ _ _) = withBotanStruct bc
 
@@ -544,7 +544,7 @@
     deriving anyclass T.Print
 
 -- | Pass 'Cipher' to FFI as 'botan_cipher_t'.
-withCipher :: HasCallStack => Cipher -> (BotanStructT -> IO r) -> IO r
+withCipher :: Cipher -> (BotanStructT -> IO r) -> IO r
 {-# INLINABLE withCipher #-}
 withCipher (Cipher c _ _ _ _ _) = withBotanStruct c
 
diff --git a/Z/Crypto/Hash.hs b/Z/Crypto/Hash.hs
--- a/Z/Crypto/Hash.hs
+++ b/Z/Crypto/Hash.hs
@@ -178,7 +178,7 @@
     deriving anyclass T.Print
 
 -- | Pass Hash to FFI as @botan_hash_t@
-withHash :: HasCallStack => Hash -> (BotanStructT -> IO r) -> IO r
+withHash :: Hash -> (BotanStructT -> IO r) -> IO r
 {-# INLINABLE withHash #-}
 withHash (Hash h _ _) = withBotanStruct h
 
diff --git a/Z/Crypto/KDF.hs b/Z/Crypto/KDF.hs
--- a/Z/Crypto/KDF.hs
+++ b/Z/Crypto/KDF.hs
@@ -27,12 +27,15 @@
   , pbkdfTypeToParam
   ) where
 
+import           GHC.Generics
 import           Z.Botan.Exception
 import           Z.Botan.FFI
 import           Z.Crypto.Hash     (HashType (..), hashTypeToCBytes)
 import           Z.Crypto.MAC      (MACType (..), macTypeToCBytes)
 import           Z.Data.CBytes     (CBytes, withCBytes, withCBytesUnsafe)
 import qualified Z.Data.CBytes     as CB
+import           Z.Data.JSON       (JSON)
+import qualified Z.Data.Text       as T
 import qualified Z.Data.Vector     as V
 import           Z.Foreign
 
@@ -70,6 +73,8 @@
     -- ^ NIST SP 800-56A KDF using HMAC
     | SP800_56C MACType
     -- ^ NIST SP 800-56C KDF using HMAC
+  deriving (Show, Read, Eq, Ord, Generic)
+  deriving anyclass (T.Print, JSON)
 
 kdfTypeToCBytes :: KDFType -> CBytes
 kdfTypeToCBytes (HKDF mt        ) = CB.concat [ "HKDF(" , macTypeToCBytes mt, ")"]
diff --git a/Z/Crypto/MAC.hs b/Z/Crypto/MAC.hs
--- a/Z/Crypto/MAC.hs
+++ b/Z/Crypto/MAC.hs
@@ -37,6 +37,7 @@
 import           Z.Crypto.Cipher   (BlockCipherType, blockCipherTypeToCBytes)
 import           Z.Crypto.Hash     (HashType, hashTypeToCBytes)
 import           Z.Data.CBytes     as CB
+import           Z.Data.JSON       (JSON)
 import qualified Z.Data.Text       as T
 import qualified Z.Data.Vector     as V
 import           Z.Foreign
@@ -69,6 +70,8 @@
              -- ^ A CBC-MAC variant sometimes used in finance. Always uses DES.
              -- Sometimes called the “DES retail MAC”, also standardized in ISO 9797-1.
              -- It is slow and has known attacks. Avoid unless required.
+  deriving (Show, Read, Eq, Ord, Generic)
+  deriving anyclass (T.Print, JSON)
 
 macTypeToCBytes :: MACType -> CBytes
 macTypeToCBytes (CMAC bc   ) = CB.concat ["CMAC(", blockCipherTypeToCBytes bc, ")"]
@@ -90,7 +93,7 @@
     deriving anyclass T.Print
 
 -- | Pass MAC to FFI as 'botan_mac_t'.
-withMAC :: HasCallStack => MAC -> (BotanStructT -> IO r) -> IO r
+withMAC :: MAC -> (BotanStructT -> IO r) -> IO r
 {-# INLINABLE withMAC #-}
 withMAC (MAC m _ _) = withBotanStruct m
 
diff --git a/Z/Crypto/PubKey.hs b/Z/Crypto/PubKey.hs
--- a/Z/Crypto/PubKey.hs
+++ b/Z/Crypto/PubKey.hs
@@ -15,7 +15,7 @@
   -- * Asymmetric cryptography algorithms
     KeyType(..)
   -- * Key generation and manipulation
-  , PrivKey(..), PubKey(..)
+  , PrivKey, PubKey
   , newPrivKey, newKeyPair, privKeyToPubKey
   , loadPrivKey
   , privKeyAlgoName
@@ -32,15 +32,13 @@
   -- * Encrypt & Decrypt
   , pkEncrypt
   , pkDecrypt
-  , sm2Encrypt
-  , sm2Decrypt
-  , EMEPadding(..)
+  , EncParam(..)
   -- * Sign & verify
-  , EMSA(..), SignFmt(..)
+  , SignParam(..), SignFmt(..), Signer, signerSize, Verifier
   , newSigner, updateSigner, finalSigner, sinkToSigner, sign, signChunks
   , newVerifier, updateVerifier, finalVerifier, sinkToVerifier, verify, verifyChunks
   -- * Key agreement
-  , KeyAgreement(..)
+  , KeyAgreement, keyAgreementSize
   , newKeyAgreement
   , exportKeyAgreementPublic
   , keyAgree
@@ -132,9 +130,11 @@
   -- * re-exports
   , HashType(..)
   , KDFType(..)
+  , RNG, getRNG
   -- * internal
   , withPrivKey
   , withPubKey
+  , botanStructToPubKey
   ) where
 
 import           Data.Word
@@ -148,8 +148,8 @@
 import           Z.Crypto.RNG        (RNG, getRNG, withRNG)
 import qualified Z.Data.Builder      as B
 import           Z.Data.CBytes       (CBytes)
-
 import qualified Z.Data.CBytes       as CB
+import           Z.Data.JSON       (JSON)
 import qualified Z.Data.Text         as T
 import qualified Z.Data.Vector       as V
 import           Z.Foreign
@@ -523,6 +523,11 @@
     deriving (Show, Eq, Ord, Generic)
     deriving anyclass T.Print
 
+-- | Unsafe construct a 'PubKey' from a botan struct.
+botanStructToPubKey :: BotanStruct -> PubKey
+{-# INLINABLE botanStructToPubKey  #-}
+botanStructToPubKey = PubKey
+
 -- | Pass 'PubKey' to FFI.
 withPubKey :: PubKey -> (BotanStructT -> IO r) -> IO r
 {-# INLINABLE withPubKey  #-}
@@ -803,55 +808,47 @@
 -- Public Key Encryption / Decryption --
 ----------------------------------------
 
--- | Sets of allowed padding schemes for public key types.
+-- | Sets of allowed params for public key types.
 --
 -- The recommended values for eme is 'EME1_SHA1' or 'EME1_SHA256'.
 -- If you need compatibility with protocols using the PKCS #1 v1.5 standard, you can also use 'EME_PKCS1_v1'5'.
-data EMEPadding
+--
+-- To use SM2 encryption, use 'SM2EncParam'.
+data EncParam
     = EME_RAW
     | EME_PKCS1_v1'5
     | EME_OAEP HashType CBytes              -- ^ hash, label
     | EME_OAEP' HashType HashType CBytes    -- ^ hash, mask gen hash, labal
+    | SM2EncParam HashType
 
-emeToCBytes :: EMEPadding -> CBytes
-{-# INLINABLE emeToCBytes  #-}
-emeToCBytes EME_RAW              = "Raw"
-emeToCBytes EME_PKCS1_v1'5       = "PKCS1v15"
-emeToCBytes (EME_OAEP  ht label)
+encParamToCBytes :: EncParam -> CBytes
+{-# INLINABLE encParamToCBytes  #-}
+encParamToCBytes EME_RAW              = "Raw"
+encParamToCBytes EME_PKCS1_v1'5       = "PKCS1v15"
+encParamToCBytes (EME_OAEP  ht label)
     | CB.null label = CB.concat ["OAEP(", hashTypeToCBytes ht, ",MGF1)" ]
     | otherwise = CB.concat ["OAEP(", hashTypeToCBytes ht, ",MGF1,", label, ")"]
 
-emeToCBytes (EME_OAEP' ht ht' label)
+encParamToCBytes (EME_OAEP' ht ht' label)
     | CB.null label =
         CB.concat ["OAEP(", hashTypeToCBytes ht, ",MGF1(", hashTypeToCBytes ht', "))"]
     | otherwise =
         CB.concat ["OAEP(", hashTypeToCBytes ht, ",MGF1(", hashTypeToCBytes ht', "),", label, ")"]
+encParamToCBytes (SM2EncParam ht) = hashTypeToCBytes ht
 
 -- |  Encrypt a message, returning the ciphertext.
 --
 -- Though botan support DLIES and ECIES but only EME are exported via FFI, please use an algorithm that directly support eme encryption such as RSA and ElGamal.
 --
 pkEncrypt :: HasCallStack
-          => PubKey -> EMEPadding -> RNG
+          => PubKey -> EncParam -> RNG
           -> V.Bytes        -- ^ plaintext
           -> IO V.Bytes     -- ^ ciphertext
 {-# INLINABLE pkEncrypt  #-}
-pkEncrypt pubKey padding = encrypt_ pubKey (emeToCBytes padding)
-
--- |  Encrypt a message using SM2, returning the ciphertext.
-sm2Encrypt :: HasCallStack
-           => PubKey -> HashType -> RNG
-           -> V.Bytes        -- ^ plaintext
-           -> IO V.Bytes     -- ^ ciphertext
-{-# INLINABLE sm2Encrypt  #-}
-sm2Encrypt pubKey ht = encrypt_ pubKey (hashTypeToCBytes ht)
-
-encrypt_ :: HasCallStack => PubKey -> CBytes -> RNG -> V.Bytes -> IO V.Bytes
-{-# INLINABLE encrypt_  #-}
-encrypt_ pubKey param rng ptext = do
+pkEncrypt pubKey padding rng ptext = do
     encryptor <-
         withPubKey pubKey $ \ pubKey' ->
-        CB.withCBytesUnsafe param $ \ param' ->
+        CB.withCBytesUnsafe (encParamToCBytes padding) $ \ param' ->
             newBotanStruct
                 (\ op -> botan_pk_op_encrypt_create op pubKey' param' 0) -- Flags should be 0 in this version.
                 botan_pk_op_encrypt_destroy
@@ -869,25 +866,14 @@
 --
 -- Though botan support DLIES and ECIES but only EME are exported via FFI, please use an algorithm that directly support decryption such as 'RSA' and 'ElGamal'.
 --
-pkDecrypt :: HasCallStack => PrivKey -> EMEPadding
-          -> V.Bytes        -- ^ ciphertext
-          -> V.Bytes        -- ^ plaintext
+pkDecrypt :: HasCallStack => PrivKey -> EncParam
+          -> V.Bytes            -- ^ ciphertext
+          -> IO V.Bytes         -- ^ plaintext
 {-# INLINABLE pkDecrypt  #-}
-pkDecrypt pubKey padding = decrypt_ pubKey (emeToCBytes padding)
-
--- |  Decrypt a message using SM2, returning the plaintext.
-sm2Decrypt :: HasCallStack => PrivKey -> HashType
-           -> V.Bytes        -- ^ plaintext
-           -> V.Bytes     -- ^ ciphertext
-{-# INLINABLE sm2Decrypt  #-}
-sm2Decrypt privKey ht = decrypt_ privKey (hashTypeToCBytes ht)
-
-decrypt_ :: HasCallStack => PrivKey -> CBytes -> V.Bytes -> V.Bytes
-{-# INLINABLE decrypt_  #-}
-decrypt_ key param ctext = unsafePerformIO $ do
+pkDecrypt key padding ctext = do
     decryptor <-
         withPrivKey key $ \ key' ->
-        CB.withCBytesUnsafe param $ \ param' ->
+        CB.withCBytesUnsafe (encParamToCBytes padding) $ \ param' ->
             newBotanStruct
                 (\ op -> botan_pk_op_decrypt_create op key' param' 0) -- Flags should be 0 in this version.
                 botan_pk_op_decrypt_destroy
@@ -904,12 +890,12 @@
 -- Signature Generation --
 --------------------------
 
--- |  Currently available values for 'EMSA', examples are “EMSA1(SHA-1)” and “EMSA4(SHA-256)”.
+-- | Signature params.
 --
 -- Currently available values for 'EMSA' include EMSA1, EMSA2, EMSA3, EMSA4, and Raw. All of them, except Raw, take a parameter naming a message digest function to hash the message with. The Raw encoding signs the input directly; if the message is too big, the signing operation will fail. Raw is not useful except in very specialized applications.
 -- For RSA, use EMSA4 (also called PSS) unless you need compatibility with software that uses the older PKCS #1 v1.5 standard, in which case use EMSA3 (also called “EMSA-PKCS1-v1_5”). For DSA, ECDSA, ECKCDSA, ECGDSA and GOST 34.10-2001 you should use EMSA1.
 --
-data EMSA
+data SignParam
     = EMSA1 HashType
     | EMSA2 HashType
     | EMSA3_RAW (Maybe HashType)
@@ -919,8 +905,16 @@
     | ISO_9796_DS2 HashType Bool (Maybe Int)    -- ^ hash, implicit, salt size
     | ISO_9796_DS3 HashType Bool                -- ^ hash, implicit
     | EMSA_Raw
+    | Ed25519Pure                               -- ^ pure Ed25519
+    | Ed25519ph                                 -- ^ rfc8032 HashEdDSA variant
+    | Ed25519Hash HashType                      -- ^ HashEdDSA
+    | SM2SignParam CBytes HashType                  -- ^ userid, hash(GM/T 0009-2012 specifies
+                                                -- @"1234567812345678"@ as the default userid)
+    | XMSSEmptyParam                            -- ^ XMSS do not need param
+  deriving (Show, Read, Eq, Ord, Generic)
+  deriving anyclass (T.Print, JSON)
 
-emsaToCBytes :: EMSA -> CBytes
+emsaToCBytes :: SignParam -> CBytes
 {-# INLINABLE emsaToCBytes  #-}
 emsaToCBytes (EMSA1 ht) = CB.concat ["EMSA1(", hashTypeToCBytes ht, ")"]
 emsaToCBytes (EMSA3_RAW (Just ht)) =
@@ -949,10 +943,15 @@
               ]
 emsaToCBytes (EMSA2 ht) = CB.concat ["EMSA2(", hashTypeToCBytes ht, ")"]
 emsaToCBytes EMSA_Raw = "Raw"
+emsaToCBytes Ed25519Pure = "Pure"
+emsaToCBytes Ed25519ph = "Ed25519ph"
+emsaToCBytes (Ed25519Hash ht) = hashTypeToCBytes ht
+emsaToCBytes (SM2SignParam uid ht) = CB.concat [uid, ",", hashTypeToCBytes ht]
+emsaToCBytes _ = ""
 
 -- The format defaults to IEEE_1363 which is the only available format for RSA. For DSA, ECDSA, ECGDSA and ECKCDSA you can also use DER_SEQUENCE, which will format the signature as an ASN.1 SEQUENCE value.
 data SignFmt = DER_SEQUENCE | IEEE_1363
-    deriving (Eq, Ord, Show, Generic)
+    deriving (Eq, Ord, Show, Enum, Generic)
     deriving anyclass T.Print
 
 signFmtToFlag :: SignFmt -> Word32
@@ -962,14 +961,12 @@
 
 data Signer = Signer
     { signerStruct :: {-# UNPACK #-} !BotanStruct
-    , signerName   :: {-# UNPACK #-} !CBytes
-    , signerFmt    :: !SignFmt
-    , signerSiz    :: {-# UNPACK #-} !Int           -- ^ output length
+    , signerSize   :: {-# UNPACK #-} !Int           -- ^ output signature length
     }
     deriving (Show, Generic)
     deriving anyclass T.Print
 
-newSigner :: HasCallStack => PrivKey -> EMSA -> SignFmt -> IO Signer
+newSigner :: HasCallStack => PrivKey -> SignParam -> SignFmt -> IO Signer
 {-# INLINABLE newSigner  #-}
 newSigner key emsa fmt = do
     let name = emsaToCBytes emsa
@@ -981,11 +978,11 @@
             siz <- withBotanStruct op $ \ op' ->
                 fst <$> allocPrimUnsafe @CSize (\ siz' ->
                     throwBotanIfMinus_ $ botan_pk_op_sign_output_length op' siz')
-            return (Signer op name fmt (fromIntegral siz))
+            return (Signer op (fromIntegral siz))
 
 updateSigner :: HasCallStack => Signer -> V.Bytes -> IO ()
 {-# INLINABLE updateSigner  #-}
-updateSigner (Signer op _ _ _) msg =
+updateSigner (Signer op _) msg =
     withBotanStruct op $ \ op' ->
     withPrimVectorUnsafe msg $ \ m moff mlen ->
         throwBotanIfMinus_ (hs_botan_pk_op_sign_update op' m moff mlen)
@@ -994,7 +991,7 @@
 -- Afterwards, the sign operator is reset and may be used to sign a new message.
 finalSigner :: HasCallStack => Signer -> RNG -> IO V.Bytes
 {-# INLINABLE finalSigner  #-}
-finalSigner (Signer op _ _ siz) rng =
+finalSigner (Signer op siz) rng =
     withBotanStruct op $ \ op' ->
     withRNG rng $ \ rng' ->
     allocBotanBufferUnsafe siz $ botan_pk_op_sign_finish op' rng'
@@ -1009,7 +1006,7 @@
 
 -- | Directly sign a message, with system RNG.
 sign :: HasCallStack
-     => PrivKey -> EMSA -> SignFmt
+     => PrivKey -> SignParam -> SignFmt
      -> V.Bytes         -- ^ input
      -> IO V.Bytes      -- ^ signature
 {-# INLINABLE sign #-}
@@ -1020,7 +1017,7 @@
 
 -- | Directly compute a chunked message's mac with system RNG.
 signChunks :: HasCallStack
-           => PrivKey -> EMSA -> SignFmt
+           => PrivKey -> SignParam -> SignFmt
            -> [V.Bytes]
            -> IO V.Bytes
 {-# INLINABLE signChunks #-}
@@ -1033,39 +1030,34 @@
 -- Signature Verification --
 ----------------------------
 
-data Verifier = Verifier
-    { verifierStruct :: {-# UNPACK #-} !BotanStruct
-    , verifierName   :: {-# UNPACK #-} !CBytes
-    , verifierFmt    :: !SignFmt
-    }
+newtype Verifier = Verifier BotanStruct
     deriving (Show, Generic)
     deriving anyclass T.Print
 
-newVerifier :: HasCallStack => PubKey -> EMSA -> SignFmt -> IO Verifier
+newVerifier :: HasCallStack => PubKey -> SignParam -> SignFmt -> IO Verifier
 {-# INLINABLE newVerifier  #-}
 newVerifier pubKey emsa fmt = do
-    let name = emsaToCBytes emsa
+    let param = emsaToCBytes emsa
     withPubKey pubKey $ \ pubKey' ->
-        CB.withCBytesUnsafe name $ \ arg -> do
+        CB.withCBytesUnsafe param $ \ arg -> do
             op <- newBotanStruct
                 (\ ret -> botan_pk_op_verify_create ret pubKey' arg (signFmtToFlag fmt))
                 botan_pk_op_verify_destroy
-            return (Verifier op name fmt)
+            return (Verifier op)
 
 updateVerifier :: HasCallStack => Verifier -> V.Bytes -> IO ()
 {-# INLINABLE updateVerifier  #-}
-updateVerifier (Verifier op _ _) msg = do
+updateVerifier (Verifier op) msg = do
     withBotanStruct op $ \ op' ->
         withPrimVectorUnsafe msg $ \ msg' off len ->
             throwBotanIfMinus_ $ hs_botan_pk_op_verify_update op' msg' off len
 
 finalVerifier :: HasCallStack => Verifier -> V.Bytes -> IO Bool
 {-# INLINABLE finalVerifier  #-}
-finalVerifier (Verifier op _ _) msg =
+finalVerifier (Verifier op) msg =
     withBotanStruct op $ \ op' ->
     withPrimVectorUnsafe msg $ \ msg' off len -> do
         r <- throwBotanIfMinus $ hs_botan_pk_op_verify_finish op' msg' off len
-        print r
         return $ r == BOTAN_FFI_SUCCESS
 --    BOTAN_FFI_SUCCESS = 0,
 --    BOTAN_FFI_INVALID_VERIFIER = 1
@@ -1080,24 +1072,24 @@
 
 -- | Directly sign a message.
 verify :: HasCallStack
-       => PubKey -> EMSA -> SignFmt
+       => PubKey -> SignParam -> SignFmt
        -> V.Bytes  -- ^ input
        -> V.Bytes  -- ^ signature
-       -> Bool
+       -> IO Bool
 {-# INLINABLE verify #-}
-verify key emsa fmt inp sig = unsafePerformIO $ do
+verify key emsa fmt inp sig = do
     m <- newVerifier key emsa fmt
     updateVerifier m inp
     finalVerifier m sig
 
 -- | Directly compute a chunked message's mac.
 verifyChunks :: HasCallStack
-           => PubKey -> EMSA -> SignFmt
+           => PubKey -> SignParam -> SignFmt
            -> [V.Bytes]
            -> V.Bytes           -- ^ signature
-           -> Bool
+           -> IO Bool
 {-# INLINABLE verifyChunks  #-}
-verifyChunks key emsa fmt inps sig = unsafePerformIO $ do
+verifyChunks key emsa fmt inps sig = do
     m <- newVerifier key emsa fmt
     mapM_ (updateVerifier m) inps
     finalVerifier m sig
@@ -1109,7 +1101,7 @@
 -- | Key agreement object.
 data KeyAgreement = KeyAgreement
     { keyAgreementStruct :: {-# UNPACK #-} !BotanStruct
-    , keyAgreementSize   :: {-# UNPACK #-} !Int
+    , keyAgreementSize   :: {-# UNPACK #-} !Int     -- ^ size of the agreed key
     }
     deriving (Show, Generic)
     deriving anyclass T.Print
diff --git a/Z/Crypto/RNG.hs b/Z/Crypto/RNG.hs
--- a/Z/Crypto/RNG.hs
+++ b/Z/Crypto/RNG.hs
@@ -56,7 +56,7 @@
     rngTypeCBytes ProcessorRNG  = "hwrng"
 
 -- | Use RNG as a `botan_rng_t` object.
-withRNG :: HasCallStack => RNG -> (BotanStructT -> IO a) -> IO a
+withRNG :: RNG -> (BotanStructT -> IO a) -> IO a
 {-# INLINABLE withRNG #-}
 withRNG (RNG rng) f = withBotanStruct rng f
 
diff --git a/Z/Crypto/X509.hs b/Z/Crypto/X509.hs
--- a/Z/Crypto/X509.hs
+++ b/Z/Crypto/X509.hs
@@ -12,8 +12,7 @@
 -}
 module Z.Crypto.X509 (
   -- * X509 Certificates
-    Cert, withCert
-  , loadCert, loadCertFile, dupCert
+    Cert, withCert, loadCert, loadCertFile, dupCert
   -- * read X509 field
   , certStart, certExpire
   , certStart', certExpire'
@@ -36,9 +35,7 @@
   , CRL
   , withCRL, loadCRL, loadCRLFile, isRevokedX509
   -- * CertStore
-  , CertStore
-  , withCertStore
-  , loadCertStoreFile
+  , CertStore, withCertStore, loadCertStoreFile
   , mozillaCertStore
   , systemCertStore
   -- * constants
@@ -61,7 +58,7 @@
 import           Z.Botan.Exception
 import           Z.Botan.FFI
 import           Z.Crypto.Hash          (HashType, hashTypeToCBytes)
-import           Z.Crypto.PubKey        (PubKey (..))
+import           Z.Crypto.PubKey        (PubKey, botanStructToPubKey)
 import qualified Z.Data.Text            as T
 import qualified Z.Data.Text.Base       as T
 import qualified Z.Data.Vector          as V
@@ -87,7 +84,8 @@
     deriving (Show, Generic)
     deriving anyclass T.Print
 
-withCert :: HasCallStack => Cert -> (BotanStructT -> IO r) -> IO r
+-- | Use 'Cert' as a `botan_cert_t`.
+withCert :: Cert -> (BotanStructT -> IO r) -> IO r
 {-# INLINABLE withCert #-}
 withCert (Cert cert) = withBotanStruct cert
 
@@ -230,7 +228,7 @@
 {-# INLINABLE certPubKey #-}
 certPubKey cert = do
     withCert cert $ \ cert' ->
-        PubKey <$> newBotanStruct
+        botanStructToPubKey <$> newBotanStruct
             (cert' `botan_x509_cert_get_public_key`)
             botan_pubkey_destroy
 
@@ -411,7 +409,8 @@
     deriving (Show, Generic)
     deriving anyclass T.Print
 
-withCRL :: HasCallStack => CRL -> (BotanStructT -> IO r) -> IO r
+-- | Use 'CRL' as a `botan_crl_t`.
+withCRL :: CRL -> (BotanStructT -> IO r) -> IO r
 {-# INLINABLE withCRL #-}
 withCRL (CRL crl) = withBotanStruct crl
 
@@ -456,7 +455,7 @@
     deriving anyclass T.Print
 
 -- | Use 'CertStore' as a 'botan_x509_certstore_t'.
-withCertStore :: HasCallStack => CertStore -> (BotanStructT -> IO r) -> IO r
+withCertStore :: CertStore -> (BotanStructT -> IO r) -> IO r
 {-# INLINABLE withCertStore #-}
 withCertStore (CertStore c) = withBotanStruct c
 
