diff --git a/base58-bytestring.cabal b/base58-bytestring.cabal
--- a/base58-bytestring.cabal
+++ b/base58-bytestring.cabal
@@ -1,5 +1,5 @@
 name:                base58-bytestring
-version:             0.0.3
+version:             0.1.0
 synopsis:            Implementation of BASE58 transcoding for ByteStrings
 
 description: Implementation of BASE58 transcoding copy-pasted from
@@ -20,6 +20,7 @@
 
 library
   exposed-modules: Data.ByteString.Base58
+                 , Data.ByteString.Base58.Internal
 
   default-extensions: OverloadedStrings
                     , DeriveDataTypeable
@@ -40,6 +41,7 @@
 
   hs-source-dirs:  test
   ghc-options:     -Wall -rtsopts -threaded
+  default-language:    Haskell2010
 
   build-depends:       base >=4.6 && < 5
                      , base58-bytestring
@@ -48,3 +50,19 @@
                      , quickcheck-instances
                      , tasty
                      , tasty-quickcheck
+
+
+benchmark bench
+  type:    exitcode-stdio-1.0
+  main-is: Main.hs
+
+  default-extensions: OverloadedStrings
+
+  hs-source-dirs:  bench
+  ghc-options:     -Wall -rtsopts -threaded
+  default-language:    Haskell2010
+
+  build-depends:       base >=4.6 && < 5
+                     , base58-bytestring
+                     , bytestring
+                     , criterion
diff --git a/bench/Main.hs b/bench/Main.hs
new file mode 100644
--- /dev/null
+++ b/bench/Main.hs
@@ -0,0 +1,41 @@
+module Main where
+
+import Data.Word
+import Criterion.Main
+import Data.ByteString ( ByteString )
+import Data.ByteString.Base58
+
+import qualified Data.ByteString as BS
+
+symChars :: [Word8]
+symChars = cycle
+           $ BS.unpack
+           $ unAlphabet bitcoinAlphabet
+
+symN :: Int -> ByteString
+symN n = BS.pack
+         $ take n
+         $ symChars
+
+nameVal :: [(String, Int)]
+nameVal = [ ("10 bytes", 10)
+          , ("42 bytes", 100)
+          , ("100 bytes", 1000) ]
+
+main :: IO ()
+main = defaultMain
+       [ bgroup "encodeBase58I"
+         [ bench "approx 10 bytes (1e24)" $  nf (encodeBase58I bitcoinAlphabet) 1000000000000000000000000
+         , bench "approx 42 bytes (1e100)" $ nf (encodeBase58I bitcoinAlphabet) 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+         , bench "approx 100 bytes (1e240)" $ nf (encodeBase58I bitcoinAlphabet) 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+         ]
+
+       , bgroup "decodeBase58I"
+         $ map (\(name, val) -> bench name $ nf (decodeBase58I bitcoinAlphabet) $ symN val) nameVal
+
+       , bgroup "encodeBase58"
+         $ map (\(name, val) -> bench name $ nf (encodeBase58 bitcoinAlphabet) $ symN val) nameVal
+
+       , bgroup "decodeBase58"
+         $ map (\(name, val) -> bench name $ nf (decodeBase58 bitcoinAlphabet) $ symN val) nameVal
+       ]
diff --git a/src/Data/ByteString/Base58.hs b/src/Data/ByteString/Base58.hs
--- a/src/Data/ByteString/Base58.hs
+++ b/src/Data/ByteString/Base58.hs
@@ -13,45 +13,16 @@
        ) where
 
 import Control.Applicative
-import Data.Bits
 import Data.ByteString ( ByteString )
+import Data.ByteString.Base58.Internal
 import Data.Char (chr, ord)
 import Data.Maybe
-import Data.String
-import Data.Typeable ( Typeable )
-import Data.Word
-import GHC.Generics ( Generic )
 import Numeric
 
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Char8 as BC
-import qualified Data.List as L
 
-newtype Alphabet =
-    Alphabet
-    { unAlphabet  :: ByteString
-    } deriving (Ord, Eq, Show, Typeable, Generic, IsString)
 
-bitcoinAlphabet :: Alphabet
-bitcoinAlphabet =
-    "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
-
-rippleAlphabet :: Alphabet
-rippleAlphabet =
-    "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"
-
-flickrAlphabet :: Alphabet
-flickrAlphabet =
-    "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
-
--- | Take 'i' byte from alphabet
-b58 :: Alphabet -> Int -> Word8
-b58 a i = BS.index (unAlphabet a) i
-
--- | Lookup position of byte 'w' in alphabet
-b58' :: Alphabet -> Word8 -> Maybe Int
-b58' a w = BS.elemIndex w (unAlphabet a)
-
 encodeBase58I :: Alphabet -> Integer -> ByteString
 encodeBase58I alpha i =
     BC.pack $ showIntAtBase 58 f i ""
@@ -60,14 +31,13 @@
     f = chr . fromIntegral . b58 alpha . fromIntegral
 
 decodeBase58I :: Alphabet -> ByteString -> Maybe Integer
-decodeBase58I alpha s = case go of
-    Just (r,[]) -> Just r
-    _           -> Nothing
-  where
-    c = b58' alpha . fromIntegral . ord
-    p = isJust . c
-    f = fromIntegral . fromJust . c
-    go = listToMaybe $ readInt 58 p f (BC.unpack s)
+decodeBase58I alpha s =
+    let c = b58' alpha . fromIntegral . ord
+        p = isJust . c
+        f = fromIntegral . fromJust . c
+    in case readInt 58 p f (BC.unpack s) of
+        [(r,[])] -> Just r
+        _        -> Nothing
 
 -- | Encode a bytestring to a base 58 representation.
 encodeBase58 :: Alphabet -> ByteString -> ByteString
@@ -91,19 +61,3 @@
         r | BS.null b = Just BS.empty
           | otherwise = integerToBS <$> decodeBase58I alpha b
     in BS.append prefix <$> r
-
--- | Decode a big endian Integer from a bytestring
-bsToInteger :: ByteString -> Integer
-bsToInteger = (L.foldl' f 0) . BS.unpack
-  where
-    f n w = (toInteger w) .|. shiftL n 8
-
--- | Encode an Integer to a bytestring as big endian
-integerToBS :: Integer -> ByteString
-integerToBS 0 = BS.pack [0]
-integerToBS i
-    | i > 0     = BS.pack $ reverse $ L.unfoldr f i
-    | otherwise = error "integerToBS not defined for negative values"
-  where
-    f 0 = Nothing
-    f x = Just $ (fromInteger x :: Word8, x `shiftR` 8)
diff --git a/src/Data/ByteString/Base58/Internal.hs b/src/Data/ByteString/Base58/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/ByteString/Base58/Internal.hs
@@ -0,0 +1,55 @@
+module Data.ByteString.Base58.Internal where
+
+import Data.Bits
+import Data.ByteString ( ByteString )
+import Data.String
+import Data.Typeable ( Typeable )
+import Data.Word
+import GHC.Generics ( Generic )
+
+import qualified Data.ByteString as BS
+import qualified Data.List as L
+
+
+newtype Alphabet =
+    Alphabet
+    { unAlphabet  :: ByteString
+    } deriving (Ord, Eq, Show, Typeable, Generic, IsString)
+
+
+bitcoinAlphabet :: Alphabet
+bitcoinAlphabet =
+    "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
+
+rippleAlphabet :: Alphabet
+rippleAlphabet =
+    "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"
+
+flickrAlphabet :: Alphabet
+flickrAlphabet =
+    "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
+
+-- | Take 'i' byte from alphabet
+b58 :: Alphabet -> Int -> Word8
+b58 a i = BS.index (unAlphabet a) i
+
+-- | Lookup position of byte 'w' in alphabet
+b58' :: Alphabet -> Word8 -> Maybe Int
+b58' a w = BS.elemIndex w (unAlphabet a)
+
+
+-- | Decode a big endian Integer from a bytestring
+bsToInteger :: ByteString -> Integer
+bsToInteger = (L.foldl' f 0) . BS.unpack
+  where
+    f n w = (toInteger w) .|. shiftL n 8
+
+-- | Encode an Integer to a bytestring as big endian
+integerToBS :: Integer -> ByteString
+integerToBS 0 = BS.pack [0]
+integerToBS i
+    | i > 0     = BS.pack $ reverse $ L.unfoldr f i
+    | otherwise = error "integerToBS not defined for negative values"
+  where
+    f 0 = Nothing
+    f x = Just $ (fromInteger x :: Word8, x `shiftR` 8)
