diff --git a/src/U2F.hs b/src/U2F.hs
--- a/src/U2F.hs
+++ b/src/U2F.hs
@@ -1,30 +1,62 @@
 {-# LANGUAGE DeriveGeneric #-}
 
-module U2F where
+{- |
+  __HOW TO USE__
 
-import GHC.Generics
-import Data.Bits
+  To Register
 
-import Data.Either.Unwrap
+    - Generate yourself a Request, consisting of your site/service uri, u2f version number, etc, send it to the client.
 
+    - Assuming the client returned a registration response (Registration), parse it with parseRegistration.
+
+    - Use verifyRegistration Request Registration to verify that the Registration is valid. (Challenge bytes match, were signed by key described in cert)
+
+    - Stash the publicKey and keyHandle somewhere, so you can use them for signin. verifyRegistration returns a Request, with added keyHandle, for convenience.
+
+  To Signin
+
+    - Make a Request.
+
+    - Parse whatever signin json you have with parseSignin.
+
+    - Dig out the publicKey for the relevant keyHandle.
+
+    - Verify signin with verifySignin publicKey Request Signin
+
+-}
+module U2F
+  (
+    parseRequest,
+    parseRegistration,
+    parseRegistrationData,
+    verifyRegistration,
+    parseSignin,
+    parseClientData,
+    verifySignin,
+    formatOutputBase64
+  )where
+import U2F.Types
+
+import Data.Bits
+
+import Data.ASN1.BitArray
+import Data.ASN1.Encoding
 import Data.ASN1.BinaryEncoding
 import Data.ASN1.Types
+
 import qualified Data.ByteString.Lazy.Char8 as LBS
 import qualified Data.ByteString.Char8 as BS
 
-import Data.Text.Encoding (encodeUtf8)
-import Data.Aeson ((.:), (.:?), decode, FromJSON(..),
-  ToJSON(..), Value(..), genericParseJSON, defaultOptions)
+import Data.Aeson (decode)
 import Data.Binary.Get
-import Data.Aeson.Types
-import Control.Applicative ((<$>), (<*>))
-import Data.ASN1.BitArray
-import Data.ASN1.Encoding
+
 import Data.ByteString (pack)
 import Data.ByteString.Base64.URL (encode, decodeLenient)
+
+import Data.List
+
 import qualified Data.Text as T
 import Data.Text.Encoding (encodeUtf8, decodeUtf8)
-import Data.List
 
 import qualified Crypto.Hash.SHA256 as SHA256
 
@@ -35,83 +67,23 @@
 import qualified Crypto.PubKey.ECC.ECDSA as ECDSA
 import Crypto.Hash.Algorithms
 
-{-
-  HOW TO USE
-  ==========
-  To Register
-    - Generate yourself a Request, consisting of your site/service uri, u2f version number, etc, send it to the client.
-    - Assuming the client returned a registration response (Registration), parse it with parseRegistration.
-    - Use verifyRegistration Request Registration to verify that the Registration is valid. (Challenge bytes match, were signed by key described in cert)
-    - Stash the publicKey and keyHandle somewhere, so you can use them for signin. verifyRegistration returns a Request, with added keyHandle, for convenience.
-  To Signin
-    - Make a Request.
-    - Parse whatever signin json you have with parseSignin.
-    - Dig out the publicKey for the relevant keyHandle.
-    - Verify signin with verifySignin publicKey Request Signin
--}
-
--- Curve
+-- | The U2F Spec (currently) exclusively supports use of the SEC p256r Curve
+ourCurve :: Curve
 ourCurve = getCurveByName SEC_p256r1
 
--- Errors
-data U2FError =
-  RegistrationParseError |
-  RegistrationDataParseError |
-  RegistrationCertificateParseError |
-  PubKeyParsingError |
-  SignatureParseError |
-  ChallengeMismatchError |
-  FailedVerificationError |
-  SigninParseError |
-  ClientDataParseError |
-  RequestParseError
-  deriving (Show, Eq)
-
-data Request = Request {
-  appId :: T.Text,
-  version :: T.Text,
-  challenge :: T.Text,
-  keyHandle :: Maybe T.Text
-} deriving (Show, Generic, Eq)
-instance FromJSON Request
-instance ToJSON Request
-
--- Registration Flow --
-data Registration = Registration {
-  registration_registrationData :: T.Text,
-  registration_challenge :: T.Text,
-  registration_version :: Maybe T.Text,
-  registration_appId :: T.Text,
-  registration_clientData :: T.Text,
-  registration_sessionID :: Maybe T.Text
-} deriving (Show, Generic)
-instance ToJSON Registration where
-  toJSON = genericToJSON defaultOptions {
-                fieldLabelModifier = Prelude.drop 13 }
-
-instance FromJSON Registration where
-  parseJSON = genericParseJSON defaultOptions {
-                fieldLabelModifier = Prelude.drop 13 }
-
-
-data RegistrationData = RegistrationData {
-  registrationData_reserved :: BS.ByteString,
-  registrationData_publicKey :: BS.ByteString,
-  registrationData_keyHandle :: BS.ByteString,
-  registrationData_certificate :: BS.ByteString,
-  registrationData_signature :: BS.ByteString
-} deriving (Show, Generic)
-
+-- | Parses Registration or Signin Request JSON
 parseRequest :: String -> Either U2FError Request
 parseRequest x = case (Data.Aeson.decode (LBS.pack x) :: Maybe Request) of
   Just request -> Right request
   Nothing -> Left RequestParseError
 
+-- | Parses Registration response JSON
 parseRegistration :: String -> Either U2FError Registration
 parseRegistration x = case (Data.Aeson.decode (LBS.pack x) :: Maybe Registration) of
   Just registration -> Right registration
   Nothing -> Left RegistrationParseError
 
+-- | Parses base64-encoded bytestring in Registration response
 parseRegistrationData :: BS.ByteString -> Either U2FError RegistrationData
 parseRegistrationData r = Right $ runGet unpackRegistrationData ( LBS.fromStrict $ decodeLenient r)
 
@@ -124,7 +96,8 @@
 
 findPubKey :: Foldable t => t ASN1 -> Maybe ECDSA.PublicKey
 findPubKey parsedCert = case (find pubKeyShape parsedCert) of
-  Just (BitString (BitArray len x)) -> parsePublicKey $ BS.tail x
+  -- Eventually check to make sure this is not compressed, in right format
+  Just (BitString (BitArray _ x)) -> parsePublicKey $ BS.tail x
   _ -> Nothing
 
 pubKeyShape :: ASN1 -> Bool
@@ -143,9 +116,10 @@
   publicKey <- pure $ registrationData_publicKey registrationData
   pure $ getSignatureBase appId clientData keyHandle publicKey
 
+-- | Verifies that Registration is a valid response to the Request
 verifyRegistration :: Request -> Registration -> Either U2FError Request
 verifyRegistration request registration = do
-  challengesEqual <- u2fComparator (challenge request) (registration_challenge registration) ChallengeMismatchError
+  _ <- u2fComparator (challenge request) (registration_challenge registration) ChallengeMismatchError
   registrationData <- parseRegistrationData $ encodeUtf8 $ registration_registrationData registration
   pkey <- getPubKeyFromCertificate $ registrationData_certificate registrationData
   signature <- parseSignature $ registrationData_signature registrationData
@@ -154,48 +128,23 @@
     True -> Right (request {keyHandle = Just $ formatOutputBase64 $ registrationData_keyHandle registrationData})
     False -> Left FailedVerificationError
 
--- Signin Flow --
-data Signin = Signin {
-  signin_keyHandle :: T.Text,
-  signin_clientData :: T.Text,
-  signin_signatureData :: T.Text
-} deriving (Show, Generic, Eq)
-
-instance FromJSON Signin where
-  parseJSON = genericParseJSON defaultOptions {
-                fieldLabelModifier = Prelude.drop 7 }
-
-data ClientData = ClientData {
-  clientData_typ :: T.Text,
-  clientData_challenge :: T.Text,
-  clientData_origin :: T.Text,
-  clientData_cid_pubkey :: T.Text
-  } deriving (Show, Generic, Eq)
-
-instance FromJSON ClientData where
-  parseJSON = genericParseJSON defaultOptions {
-                fieldLabelModifier = Prelude.drop 11 }
-
-data SignatureData = SignatureData {
-  signatureData_userPresenceFlag :: BS.ByteString,
-  signatureData_counter :: BS.ByteString,
-  signatureData_signature :: BS.ByteString
-} deriving (Show, Generic)
-
+-- | Parses Signin response JSON
 parseSignin :: String -> Either U2FError Signin
 parseSignin x = case (Data.Aeson.decode (LBS.pack x) :: Maybe Signin) of
   Just signin -> Right signin
   Nothing -> Left SigninParseError
 
+-- | Parses base64-encoded client data bytestring inside Signin response
 parseClientData :: BS.ByteString -> Either U2FError ClientData
 parseClientData x = case (Data.Aeson.decode (LBS.fromStrict $ decodeLenient x) :: Maybe ClientData) of
   Just clientData -> Right clientData
   Nothing -> Left ClientDataParseError
 
+-- | Verifies that Signin response is valid given saved pubkey bytestring, request
 verifySignin :: BS.ByteString -> Request -> Signin -> Either U2FError Bool
 verifySignin savedPubkey request signin = do
   clientData <- parseClientData $ encodeUtf8 $ signin_clientData signin
-  challengesEqual <- u2fComparator (challenge request) (clientData_challenge clientData) ChallengeMismatchError
+  _ <- u2fComparator (challenge request) (clientData_challenge clientData) ChallengeMismatchError
   signatureData <- parseSignatureData $ encodeUtf8 $ signin_signatureData signin
   signature <- parseSignature $ signatureData_signature signatureData
   signatureBase <- getSigninSignatureBase request signin signatureData
@@ -207,8 +156,6 @@
     True -> Right True
     False -> Left FailedVerificationError
 
--- Other stuff
-
 parseSignatureData :: BS.ByteString -> Either U2FError SignatureData
 parseSignatureData s = Right $ runGet unpackSignatureData ( LBS.fromStrict $ decodeLenient s)
 
@@ -228,10 +175,10 @@
 parsePublicKey :: BS.ByteString -> Maybe ECDSA.PublicKey
 parsePublicKey keyByteString = case P256.pointFromBinary keyByteString of
   CryptoPassed key -> Just $ ECDSA.PublicKey ourCurve $ Point (fst $ P256.pointToIntegers key) (snd $ P256.pointToIntegers key)
-  CryptoFailed err -> Nothing
+  CryptoFailed _ -> Nothing
 
--- URL-friendly base64 encoding may or may not contain padding. Delete it here
--- https://tools.ietf.org/html/rfc4648#section-3.2
+-- | URL-friendly base64 encoding may or may not contain padding. (https://tools.ietf.org/html/rfc4648#section-3.2).
+--   We remove it here.
 formatOutputBase64 :: BS.ByteString -> T.Text
 formatOutputBase64 byteString = T.replace (T.pack "=") (T.pack "") (decodeUtf8 $ encode byteString)
 
diff --git a/src/U2F/Types.hs b/src/U2F/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/U2F/Types.hs
@@ -0,0 +1,113 @@
+{-# LANGUAGE DeriveGeneric #-}
+
+module U2F.Types where
+
+import GHC.Generics
+import qualified Data.Text as T
+import qualified Data.ByteString.Char8 as BS
+import Data.Aeson ((.:), (.:?), decode, FromJSON(..),
+  ToJSON(..), Value(..), genericParseJSON, genericToJSON,  defaultOptions)
+import Data.Aeson.Types (fieldLabelModifier)
+
+data U2FError =
+  RegistrationParseError            |
+  RegistrationDataParseError        |
+  RegistrationCertificateParseError |
+  PubKeyParsingError                |
+  SignatureParseError               |
+  ChallengeMismatchError            |
+  FailedVerificationError           |
+  SigninParseError                  |
+  ClientDataParseError              |
+  RequestParseError                 |
+  RegisterRequestParseError
+  deriving (Show, Eq)
+
+data Transport =  BT  | -- ^ Bluetooth Classic (Bluetooth BR/EDR)
+                  BLE | -- ^ Bluetooth Low Energy (Bluetooth Smart)
+                  NFC | -- ^ Near-Field Communications
+                  USB   -- ^ USB HID (Human Interface Device)
+  deriving (Show, Eq)
+
+-- | Generic request for old version of protocol. Probably want to remove
+data Request = Request {
+  appId :: T.Text,
+  version :: T.Text,
+  challenge :: T.Text,
+  keyHandle :: Maybe T.Text
+} deriving (Show, Generic, Eq)
+instance FromJSON Request
+instance ToJSON Request
+
+data RegisterRequest = RegisterRequest {
+  registerRequest_version :: T.Text, -- Will probably be 'U2F_V2'
+  registerRequest_challenge :: T.Text
+} deriving (Show, Generic)
+instance ToJSON RegisterRequest where
+  toJSON = genericToJSON defaultOptions {
+                fieldLabelModifier = Prelude.drop 16 }
+instance FromJSON RegisterRequest where
+  parseJSON = genericParseJSON defaultOptions {
+                fieldLabelModifier = Prelude.drop 16 }
+
+data RegisteredKey = RegisteredKey {
+  registeredKey_version :: T.Text,
+  registeredKey_keyHandle :: T.Text,
+  registeredKey_transports :: Maybe [Transport],
+  registeredKey_appId :: Maybe T.Text
+} deriving (Show, Generic, Eq)
+
+-- Register Flow --
+
+data Registration = Registration {
+  registration_registrationData :: T.Text,
+  registration_challenge :: T.Text,
+  registration_version :: Maybe T.Text,
+  registration_appId :: T.Text,
+  registration_clientData :: T.Text,
+  registration_sessionID :: Maybe T.Text
+} deriving (Show, Generic)
+instance ToJSON Registration where
+  toJSON = genericToJSON defaultOptions {
+                fieldLabelModifier = Prelude.drop 13 }
+
+instance FromJSON Registration where
+  parseJSON = genericParseJSON defaultOptions {
+                fieldLabelModifier = Prelude.drop 13 }
+
+
+data RegistrationData = RegistrationData {
+  registrationData_reserved :: BS.ByteString,
+  registrationData_publicKey :: BS.ByteString,
+  registrationData_keyHandle :: BS.ByteString,
+  registrationData_certificate :: BS.ByteString,
+  registrationData_signature :: BS.ByteString
+} deriving (Show, Generic)
+
+-- Signin Flow --
+data Signin = Signin {
+  signin_keyHandle :: T.Text,
+  signin_clientData :: T.Text,
+  signin_signatureData :: T.Text
+} deriving (Show, Generic, Eq)
+
+instance FromJSON Signin where
+  parseJSON = genericParseJSON defaultOptions {
+                fieldLabelModifier = Prelude.drop 7 }
+
+data ClientData = ClientData {
+  clientData_typ :: T.Text,
+  clientData_challenge :: T.Text,
+  clientData_origin :: T.Text,
+  clientData_cid_pubkey :: T.Text
+  } deriving (Show, Generic, Eq)
+
+instance FromJSON ClientData where
+  parseJSON = genericParseJSON defaultOptions {
+                fieldLabelModifier = Prelude.drop 11 }
+
+data SignatureData = SignatureData {
+  signatureData_userPresenceFlag :: BS.ByteString,
+  signatureData_counter :: BS.ByteString,
+  signatureData_signature :: BS.ByteString
+} deriving (Show, Generic)
diff --git a/tests/test.hs b/tests/test.hs
--- a/tests/test.hs
+++ b/tests/test.hs
@@ -1,26 +1,29 @@
 import Test.Hspec
-import Control.Exception (evaluate)
 import U2F
-import Data.Maybe
+import U2F.Types
+import Data.Either.Unwrap (fromRight)
 import qualified Data.ByteString.Char8 as BS
 import qualified Data.Text as T
 
+rawRegRequest :: String
 rawRegRequest = "{\"appId\":\"https://localhost:4000\",\"version\":\"U2F_V2\",\"challenge\":\"7uy5uxqHXeCGg7K1cWmO3bVlr_KY1U5dQkPP_wOvlWg\",\"keyHandle\":\"9Hgjem2ZlnKKuKVnHepmuSzMHnoyCX0idccYCwztgtpXllNSr-xv_oSuQnyVCN8HYa5JgIsawOxhtp0CIIcBGQ\"}"
+registrationRequest :: Request
 registrationRequest = Request (T.pack "https://localhost:4000") (T.pack "U2F_V2") (T.pack "7uy5uxqHXeCGg7K1cWmO3bVlr_KY1U5dQkPP_wOvlWg") Nothing
-registrationResponse = justRight $ parseRegistration "{\"registrationData\":\"BQQ65jfw5zT6MqdV81UYQ6btGV-dK8wRyxAGuYcFAKvFp1HubXnyI9wG5Vw8zdmE8sjBNK58GNrJ3woQ-e_nnV9kQPR4I3ptmZZyirilZx3qZrkszB56Mgl9InXHGAsM7YLaV5ZTUq_sb_6ErkJ8lQjfB2GuSYCLGsDsYbadAiCHARkwggJEMIIBLqADAgECAgR4wN8OMAsGCSqGSIb3DQEBCzAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowKjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMjAyNTkwNTkzNDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLW4cVyD_f4OoVxFd6yFjfSMF2_eh53K9Lg9QNMg8m-t5iX89_XIr9g1GPjbniHsCDsYRYDHF-xKRwuWim-6P2-jOzA5MCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS4xMBMGCysGAQQBguUcAgEBBAQDAgUgMAsGCSqGSIb3DQEBCwOCAQEAPvar9kqRawv5lJON3JU04FRAAmhWeKcsQ6er5l2QZf9h9FHOijru2GaJ0ZC5UK8AelTRMe7wb-JrTqe7PjK3kgWl36dgBDRT40r4RMN81KhfjFwthw4KKLK37UQCQf2zeSsgdrDhivqbQy7u_CZYugkFxBskqTxuyLum1W8z6NZT189r1QFUVaJll0D33MUcwDFgnNA-ps3pOZ7KCHYykHY_tMjQD1aQaaElSQBq67BqIaIU5JmYN7Qp6B1-VtM6VJLdOhYcgpOVQIGqfu90nDpWPb3X26OVzEc-RGltQZGFwkN6yDrAZMHL5HIn_3obd8fV6gw2fUX2ML2ZjVmybjBEAiBGwwt4P70-8E1KmmKQBtVQkvi-w16gSYLECB68b8nDNgIgCiRB1ATDXuWQ7m2DfNnsEq3bs3haITTa4ssHWB8PG-0\",\"challenge\":\"7uy5uxqHXeCGg7K1cWmO3bVlr_KY1U5dQkPP_wOvlWg\",\"version\":\"U2F_V2\",\"appId\":\"https://localhost:4000\",\"sessionId\":\"444\",\"clientData\":\"eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6Ijd1eTV1eHFIWGVDR2c3SzFjV21PM2JWbHJfS1kxVTVkUWtQUF93T3ZsV2ciLCJvcmlnaW4iOiJodHRwczovL2xvY2FsaG9zdDo0MDAwIiwiY2lkX3B1YmtleSI6InVudXNlZCJ9\"}"
-registrationGoodSig = BS.pack "0D\STX F\195\vx?\189>\240MJ\154b\144\ACK\213P\146\248\190\195^\160I\130\196\b\RS\188o\201\195\&6\STX \n$A\212\EOT\195^\229\144\238m\131|\217\236\DC2\173\219\179xZ!4\218\226\203\aX\US\SI\ESC\237"
-registrationGoodSigBase = BS.pack "\NUL\219\214S\135\176*\251\174\&8J\132g\177\209\ETX\192y\136s/L\136si\RSA\255\140\184/%\129Q\208\243\CAN!\204\&1\202\144j\153\246\&4\171\SOH\251@\165\244%\202=\ETB>\217\160\a\STX!\158\246W\244x#zm\153\150r\138\184\165g\GS\234f\185,\204\RSz2\t}\"u\199\CAN\v\f\237\130\218W\150SR\175\236o\254\132\174B|\149\b\223\aa\174I\128\139\SUB\192\236a\182\157\STX \135\SOH\EM\EOT:\230\&7\240\231\&4\250\&2\167U\243U\CANC\166\237\EM_\157+\204\DC1\203\DLE\ACK\185\135\ENQ\NUL\171\197\167Q\238my\242#\220\ACK\229\\<\205\217\132\242\200\193\&4\174|\CAN\218\201\223\n\DLE\249\239\231\157_d"
+registrationResponse :: Registration
+registrationResponse = fromRight $ parseRegistration "{\"registrationData\":\"BQQ65jfw5zT6MqdV81UYQ6btGV-dK8wRyxAGuYcFAKvFp1HubXnyI9wG5Vw8zdmE8sjBNK58GNrJ3woQ-e_nnV9kQPR4I3ptmZZyirilZx3qZrkszB56Mgl9InXHGAsM7YLaV5ZTUq_sb_6ErkJ8lQjfB2GuSYCLGsDsYbadAiCHARkwggJEMIIBLqADAgECAgR4wN8OMAsGCSqGSIb3DQEBCzAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowKjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMjAyNTkwNTkzNDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLW4cVyD_f4OoVxFd6yFjfSMF2_eh53K9Lg9QNMg8m-t5iX89_XIr9g1GPjbniHsCDsYRYDHF-xKRwuWim-6P2-jOzA5MCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS4xMBMGCysGAQQBguUcAgEBBAQDAgUgMAsGCSqGSIb3DQEBCwOCAQEAPvar9kqRawv5lJON3JU04FRAAmhWeKcsQ6er5l2QZf9h9FHOijru2GaJ0ZC5UK8AelTRMe7wb-JrTqe7PjK3kgWl36dgBDRT40r4RMN81KhfjFwthw4KKLK37UQCQf2zeSsgdrDhivqbQy7u_CZYugkFxBskqTxuyLum1W8z6NZT189r1QFUVaJll0D33MUcwDFgnNA-ps3pOZ7KCHYykHY_tMjQD1aQaaElSQBq67BqIaIU5JmYN7Qp6B1-VtM6VJLdOhYcgpOVQIGqfu90nDpWPb3X26OVzEc-RGltQZGFwkN6yDrAZMHL5HIn_3obd8fV6gw2fUX2ML2ZjVmybjBEAiBGwwt4P70-8E1KmmKQBtVQkvi-w16gSYLECB68b8nDNgIgCiRB1ATDXuWQ7m2DfNnsEq3bs3haITTa4ssHWB8PG-0\",\"challenge\":\"7uy5uxqHXeCGg7K1cWmO3bVlr_KY1U5dQkPP_wOvlWg\",\"version\":\"U2F_V2\",\"appId\":\"https://localhost:4000\",\"sessionId\":\"444\",\"clientData\":\"eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6Ijd1eTV1eHFIWGVDR2c3SzFjV21PM2JWbHJfS1kxVTVkUWtQUF93T3ZsV2ciLCJvcmlnaW4iOiJodHRwczovL2xvY2FsaG9zdDo0MDAwIiwiY2lkX3B1YmtleSI6InVudXNlZCJ9\"}"
 
+signinRequest :: Request
 signinRequest = Request (T.pack "https://localhost:4000") (T.pack "U2F_V2") (T.pack "7uy5uxqHXeCGg7K1cWmO3bVlr_KY1U5dQkPP_wOvlWg") (Just $ T.pack "9Hgjem2ZlnKKuKVnHepmuSzMHnoyCX0idccYCwztgtpXllNSr-xv_oSuQnyVCN8HYa5JgIsawOxhtp0CIIcBGQ")
-signinResponse = justRight $ parseSignin "{\"keyHandle\":\"9Hgjem2ZlnKKuKVnHepmuSzMHnoyCX0idccYCwztgtpXllNSr-xv_oSuQnyVCN8HYa5JgIsawOxhtp0CIIcBGQ\",\"clientData\":\"eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwiY2hhbGxlbmdlIjoiN3V5NXV4cUhYZUNHZzdLMWNXbU8zYlZscl9LWTFVNWRRa1BQX3dPdmxXZyIsIm9yaWdpbiI6Imh0dHBzOi8vbG9jYWxob3N0OjQwMDAiLCJjaWRfcHVia2V5IjoidW51c2VkIn0\",\"signatureData\":\"AQAAAAAwRgIhAI4jLgLewiaFzuyyuaxlToF1OHmkItaOeASUtIStic5HAiEA8X16pOe_Sugk8O8AAh2iQdlx_98cR9UwwCwDmr_bbXo\"}"
+signinResponse :: Signin
+signinResponse = fromRight $ parseSignin "{\"keyHandle\":\"9Hgjem2ZlnKKuKVnHepmuSzMHnoyCX0idccYCwztgtpXllNSr-xv_oSuQnyVCN8HYa5JgIsawOxhtp0CIIcBGQ\",\"clientData\":\"eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwiY2hhbGxlbmdlIjoiN3V5NXV4cUhYZUNHZzdLMWNXbU8zYlZscl9LWTFVNWRRa1BQX3dPdmxXZyIsIm9yaWdpbiI6Imh0dHBzOi8vbG9jYWxob3N0OjQwMDAiLCJjaWRfcHVia2V5IjoidW51c2VkIn0\",\"signatureData\":\"AQAAAAAwRgIhAI4jLgLewiaFzuyyuaxlToF1OHmkItaOeASUtIStic5HAiEA8X16pOe_Sugk8O8AAh2iQdlx_98cR9UwwCwDmr_bbXo\"}"
+signinSavedPubkey :: BS.ByteString
 signinSavedPubkey = BS.pack "\EOT:\230\&7\240\231\&4\250\&2\167U\243U\CANC\166\237\EM_\157+\204\DC1\203\DLE\ACK\185\135\ENQ\NUL\171\197\167Q\238my\242#\220\ACK\229\\<\205\217\132\242\200\193\&4\174|\CAN\218\201\223\n\DLE\249\239\231\157_d"
-justRight (Right x) = x
 
 main :: IO ()
 main = hspec $ do
   describe "Request/Response Parsing" $ do
     it "should work for registration requests" $ do
-      regRequest <- pure $ justRight $ parseRequest rawRegRequest
+      regRequest <- pure $ fromRight $ parseRequest rawRegRequest
       (appId regRequest) `shouldBe` (T.pack "https://localhost:4000")
 
   describe "Registration Flow" $ do
@@ -34,7 +37,7 @@
       registrationVerificationSuccess <- return $ do
             verifyRegistration registrationRequest registrationResponse
       --TODO: Find a better way to test for this
-      (registrationVerificationSuccess) `shouldBe` (Right $ justRight registrationVerificationSuccess)
+      (registrationVerificationSuccess) `shouldBe` (Right $ fromRight registrationVerificationSuccess)
 
   describe "Signin Flow" $ do
     it "should check that request and response challenges are equivalent" $ do
@@ -44,7 +47,6 @@
       signinVerificationFail `shouldBe` (Left ChallengeMismatchError)
 
     it "should validate properly formed request and response" $ do
-      signinVerificationSuccess <- return $ do
-            verifySignin signinSavedPubkey signinRequest signinResponse
+      signinVerificationSuccess <- return $ verifySignin signinSavedPubkey signinRequest signinResponse
       --TODO: Find a better way to test for this
-      (signinVerificationSuccess) `shouldBe` (Right $ justRight signinVerificationSuccess)
+      (signinVerificationSuccess) `shouldBe` (Right $ fromRight signinVerificationSuccess)
diff --git a/u2f.cabal b/u2f.cabal
--- a/u2f.cabal
+++ b/u2f.cabal
@@ -2,7 +2,7 @@
 -- see http://haskell.org/cabal/users-guide/
 
 name:                u2f
-version:             0.1.0.0
+version:             0.1.0.1
 synopsis:            Haskell Universal Two Factor helper toolbox library thing
 description:         Library useful for server-side U2F Registration and Signin flows.
 homepage:            https://github.com/EButlerIV/u2f
@@ -15,30 +15,36 @@
 build-type:          Simple
 extra-source-files:  ChangeLog.md, README.md
 cabal-version:       >=1.10
+tested-with: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.1, GHC == 8.0.2
 
 library
   exposed-modules:     U2F
+                     , U2F.Types
+  ghc-options: -Wall
   -- other-modules:
   -- other-extensions:
-  build-depends:       base >=4.8 && <4.9
-                       , cryptonite >= 0.17
-                       , binary >= 0.8.4.0
-                       , text
-                       , asn1-encoding
-                       , asn1-types
-                       , base64-bytestring
-                       , cryptohash
-                       , aeson
-                       , bytestring
-                       , either-unwrap
+  build-depends:       base >= 4.8 && < 4.11
+                       , cryptonite >= 0.17 && < 0.21
+                       , binary >= 0.8.4.0 && < 0.9
+                       , text >= 1.2 && < 1.3
+                       , asn1-encoding >= 0.9 && < 0.10
+                       , asn1-types >= 0.3.2 && < 0.4
+                       , base64-bytestring >= 1.0.0.1 && < 1.0.1.0
+                       , cryptohash >= 0.11 && < 0.12
+                       , aeson >= 1.0 && < 1.1
+                       , bytestring >= 0.10 && < 0.11
   hs-source-dirs:      src
   default-language:    Haskell2010
 
-test-suite test
+test-suite hspec-suite
   type:       exitcode-stdio-1.0
-  main-is:    tests/test.hs
+  main-is:    test.hs
+  ghc-options: -Wall
+  hs-source-dirs: tests
+  default-language:    Haskell2010
   build-depends:  base
-                , hspec
+                , hspec >= 2.2 && < 2.3
                 , u2f
                 , text
+                , either-unwrap
                 , bytestring
