diff --git a/hexstring.cabal b/hexstring.cabal
--- a/hexstring.cabal
+++ b/hexstring.cabal
@@ -1,6 +1,6 @@
 name: hexstring
 category: Data
-version: 0.9.0
+version: 0.10.0
 license: MIT
 license-file: LICENSE
 copyright: (c) 2015 Leon Mergen
@@ -11,9 +11,8 @@
 stability: experimental
 synopsis: Fast and safe representation of a hex string
 description:
-            Provides an interface for representing a HexString. It uses fast conversion
-            functions to convert to-and-from String or Text formats. Internally, the
-            HexString is represented by a ByteString.
+            Provides an interface for converting any object that has a 'Binary' instance
+            to and from a hexadecimal Text representation.
                       
 build-type: Simple
 data-files: LICENSE, README.md
@@ -28,6 +27,7 @@
   exposed-modules:     Data.HexString
   
   build-depends:       base                     >= 4.3          && < 5
+                     , binary 
                      , text
                      , bytestring
                      , base16-bytestring
@@ -48,6 +48,8 @@
                      , text
 
                      , bytestring
+                     , binary
+                     
                      , hexstring
 
 source-repository head
diff --git a/src/Data/HexString.hs b/src/Data/HexString.hs
--- a/src/Data/HexString.hs
+++ b/src/Data/HexString.hs
@@ -1,45 +1,48 @@
-module Data.HexString where
-
-import qualified Data.ByteString        as BS
-import qualified Data.ByteString.Char8  as BS8
-import qualified Data.ByteString.Base16 as BS16
+module Data.HexString ( HexString
+                      , hexString
+                      , toHex
+                      , fromHex
+                      , asText ) where
 
-import qualified Data.Text as T
-import qualified Data.Text.Encoding as TE
+import           Data.Word                   (Word8)
 
--- | Data type representing a HexString.
-data HexString
-  = HexString !BS.ByteString
-  deriving ( Show, Eq, Ord )
+import qualified Data.ByteString.Base16 as BS16 (decode, encode)
+import qualified Data.ByteString        as BS
+import qualified Data.ByteString.Lazy   as BSL
 
--- | Access to the raw binary data this HexString represents
-getBinary :: HexString -> BS.ByteString
-getBinary (HexString bs) = bs
+import qualified Data.Text              as T
+import qualified Data.Text.Encoding     as TE
 
--- | Create new HexString based on raw binary data
-setBinary :: BS.ByteString -> HexString
-setBinary = HexString
+import qualified Data.Binary            as B (Binary, decode, encode)
 
--- | Converts `BS.ByteString` to a `HexString`
-decodeByteString :: BS.ByteString -> HexString
-decodeByteString = HexString . fst . BS16.decode
+-- | Represents a Hex string. Guarantees that all characters it contains
+--   are valid hex characters.
+data HexString =
+  HexString BS.ByteString
+  deriving ( Show, Eq, Ord )
 
--- | Converts a `T.Text` representation to a `HexString`
-decodeText :: T.Text -> HexString
-decodeText = decodeByteString . TE.encodeUtf8
+-- | Smart constructor which validates that all the text are actually
+--   hexadecimal characters.
+hexString :: BS.ByteString -> HexString
+hexString bs =
+  let isValidHex :: Word8 -> Bool
+      isValidHex c
+        | (48 <= c) && (c < 58)  = True
+        | (97 <= c) && (c < 103) = True
+        | otherwise              = False
 
--- | Converts a `String` representation to a `HexString`
-decodeString :: String -> HexString
-decodeString = decodeByteString . BS8.pack
+  in if   BS.all isValidHex bs
+     then HexString bs
+     else error ("Not a valid hex string: " ++ show bs)
 
--- | Converts a `HexString` to a `BS.ByteString`
-encodeByteString :: HexString -> BS.ByteString
-encodeByteString = BS16.encode . getBinary
+-- | Converts a 'B.Binary' to a 'HexString' value
+toHex :: B.Binary a  => a -> HexString
+toHex = hexString . BS16.encode . BSL.toStrict . B.encode
 
--- | Converts a `HexString` to a `T.Text` representation
-encodeText :: HexString -> T.Text
-encodeText = TE.decodeUtf8 . encodeByteString
+-- | Converts a 'HexString' to a 'B.Binary' value
+fromHex :: B.Binary a => HexString -> a
+fromHex (HexString bs) = B.decode . BSL.fromStrict . fst . BS16.decode $ bs
 
--- | Converts a `HexString` to a `String` representation
-encodeString :: HexString -> String
-encodeString = BS8.unpack . encodeByteString
+-- | Access to a 'T.Text' representation of the 'HexString'
+asText :: HexString -> T.Text
+asText (HexString bs) = TE.decodeUtf8 bs
diff --git a/test/Data/HexStringSpec.hs b/test/Data/HexStringSpec.hs
--- a/test/Data/HexStringSpec.hs
+++ b/test/Data/HexStringSpec.hs
@@ -1,23 +1,26 @@
 module Data.HexStringSpec where
 
-import           Data.HexString
+import           Data.HexString ( hexString
+                                , toHex
+                                , fromHex
+                                , asText )
 
+import qualified Data.ByteString       as BS
 import qualified Data.ByteString.Char8 as BS8
 import qualified Data.Text             as T
 
+import qualified Data.Binary as B ( encode )
+
 import           Test.Hspec
 
 spec :: Spec
 spec = do
-  describe "when decoding hex data" $ do
-    it "should be able to parse basic hex data" $ do
-      (getBinary . decodeByteString) (BS8.pack "ffff") `shouldBe` BS8.pack "\255\255"
-      (getBinary . decodeString) "ffff"                `shouldBe` BS8.pack "\255\255"
-      (getBinary . decodeText) (T.pack "ffff")         `shouldBe` BS8.pack "\255\255"
+  describe "when constructing a hex string" $ do
+    it "should accept strings that fall within a valid range" $
+      hexString (BS8.pack "0123456789abcdef") `shouldBe` hexString (BS8.pack "0123456789abcdef")
 
-    it "should be able to recode basic hex data to different formats" $
-      let hex = BS8.pack "ffff"
-      in do
-        (encodeText . decodeByteString) hex       `shouldBe` T.pack "ffff"
-        (encodeString . decodeByteString) hex     `shouldBe` "ffff"
-        (encodeByteString . decodeByteString) hex `shouldBe` BS8.pack "ffff"
+    it "should reject strings outside the range" $ do
+      putStrLn (show (hexString (BS8.pack "/"))) `shouldThrow` anyErrorCall
+      putStrLn (show (hexString (BS8.pack ":"))) `shouldThrow` anyErrorCall
+      putStrLn (show (hexString (BS8.pack "`"))) `shouldThrow` anyErrorCall
+      putStrLn (show (hexString (BS8.pack "g"))) `shouldThrow` anyErrorCall
