diff --git a/Network/CommSec/KeyExchange.hs b/Network/CommSec/KeyExchange.hs
--- a/Network/CommSec/KeyExchange.hs
+++ b/Network/CommSec/KeyExchange.hs
@@ -1,7 +1,29 @@
 {-# LANGUAGE RecordWildCards, BangPatterns #-}
+-- |This module provides an authenticated key exchange using the station to
+-- station protocol and RSA signatures for authentication.
+--
+-- For example, after presharing ssh keys generated using ssh-keygen:
+--
+-- @
+--  import Crypto.PubKey.OpenSsh
+--  import qualified Data.ByteString as B
+--  import Network.CommSec.KeyExchange
+--
+--  main = do
+--      -- Step 1: (not shown) get file paths, host, and port somehow.
+--      -- Step 2: Read in the keys
+--      OpenSshPrivateKeyRsa priv <- (either error id . (\x -> decodePrivate x)) `fmap` B.readFile myPrivateKeyFile
+--      OpenSshPublicKeyRsa them _ <- (either error id . decodePublic) `fmap` B.readFile theirPublicKeyFile
+--
+--      -- Step 3: Listen for and accept a connection (or connect to the listener)
+--      if listener
+--          then accept host port them priv
+--          else connect host port them priv
+-- @
 module Network.CommSec.KeyExchange
     ( connect
     , accept
+    , keyExchangeInit, keyExchangeResp
     , CS.send, CS.recv, CS.Connection, Net.HostName, Net.PortNumber
     ) where
 
@@ -33,7 +55,7 @@
 import Network.CommSec hiding (accept, connect)
 import Network.CommSec.Package (InContext(..), OutContext(..))
 
--- RFC 5114 section 2.3
+-- |This prime is from RFC 5114 section 2.3
 thePrime :: Integer
 thePrime = 0x87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597
 
@@ -41,17 +63,20 @@
 theGenerator :: Integer
 theGenerator = 5
 
--- Sign exponents and atest to our ID:  Sign(q_y, Sha256(a | b | pk_x))
+-- |Sign exponents:  Sign(q_y, Sha256(a | b))
 signExps :: Integer -> Integer -> PrivateKey -> ByteString
 signExps a b k = L.toStrict . RSA.sign k $ encodeExps a b
 
--- Verify exponents and other party was signed as:  Sign(q_y, Sha256(a | b | pk_x))
+-- |Verify exponents and other party was signed as:  Sign(q_y, Sha256(a | b))
 verifyExps :: Integer -> Integer -> ByteString -> PublicKey -> Bool
 verifyExps a b sig k = RSA.verify k (encodeExps a b) (fromStrict sig)
 
+-- |Serialize exponents in an agreed upon format
 encodeExps :: Integer -> Integer -> L.ByteString
 encodeExps a b = fromStrict . runPut $ put a >> put b
 
+-- |Get the secret value @x@ and a publicly sharable value @theGenerator
+-- ^ x@
 getXaX :: IO (Integer, Integer)
 getXaX = do
     g <- newGenIO :: IO HmacDRBG
@@ -59,11 +84,16 @@
         ax    = modexp theGenerator x thePrime
     return (x,ax)
 
+-- |@keyExchangeResp sock them me@
+--
+-- Act as the responder in an authenticated key exchange using the socket
+-- @sock@ as the communications channel, the public key @them@ to verify
+-- the end point and the private key @me@ to prove ourself.
 keyExchangeResp :: Net.Socket -> PublicKey -> PrivateKey -> IO (OutContext, InContext)
 keyExchangeResp sock publicThem privateMe = do
     (y,ay) <- getXaX
     ax     <- (either error id . decode) `fmap` recvMsg sock
-    let axy = ax * ay `mod` thePrime
+    let axy = modexp ax y thePrime
         sharedSecret = encode . sha256 $ i2bs (2048 `div` 8) axy
         shared512    = expandSecret sharedSecret (16 + 16 + 4 + 4)
         -- Split the 512 bit secret into [ Key 1 (128b) | Key 2 (128b) | salt 1 (32b) | salt 2 (32 b) ]
@@ -86,6 +116,11 @@
            (error "RESP: Verification failed when exchanging key.  Man in the middle?")
     return (outCtx, inCtx)
 
+-- |@keyExchangeInit sock them me@
+--
+-- Act as the initiator in an authenticated key exchange using the socket
+-- @sock@ as the communications channel, the public key @them@ to verify
+-- the end point and the private key @me@ to prove ourself.
 keyExchangeInit :: Net.Socket -> PublicKey -> PrivateKey -> IO (OutContext, InContext)
 keyExchangeInit sock publicThem privateMe = do
     -- our secret big number, x, and a^x for exchange.
@@ -96,7 +131,7 @@
         decodePkg = runGet (do i <- get -- Integer
                                e <- get -- Encrypted signature
                                return (i,e))
-        axy = ax * ay `mod` thePrime :: Integer
+        axy = modexp ay x thePrime :: Integer
         sharedSecret = encode . sha256 $ i2bs (2048 `div` 8) axy
         shared512    = expandSecret sharedSecret 64
         -- Split the 512 bit secret into [ Key 1 (128b) | Key 2 (128b) | salt 1 (32b) | salt 2 (32 b) ]
@@ -118,10 +153,12 @@
     sendMsg sock enc
     return (outCtx, inCtx)
 
+-- |Connect to the specified host and port, establishing a secure,
+-- authenticated connection with a party holding the public key.
 connect :: Net.HostName -> Net.PortNumber -> PublicKey -> PrivateKey -> IO Connection
 connect host port them us = do
     sockaddr <- resolve host port
-    socket <- Net.socket Net.AF_INET Net.Stream Net.defaultProtocol
+    socket   <- Net.socket Net.AF_INET Net.Stream Net.defaultProtocol
     Net.connect socket sockaddr
     Net.setSocketOption socket Net.NoDelay 1
     Net.setSocketOption socket Net.ReuseAddr 1
@@ -136,6 +173,9 @@
                                     Net.addrFamily = Net.AF_INET, Net.addrSocketType = Net.Stream } ) (Just h) (Just (show port))
         return (maybe (error $ "Could not resolve host " ++ h) Net.addrAddress (listToMaybe ai))
 
+-- |Listen for and accept a connection on the host and port, establishing
+-- a secure, authenticated connection with a party holding the specified
+-- public key.
 accept :: Net.PortNumber -> PublicKey -> PrivateKey -> IO Connection
 accept port them us = do
     let sockaddr = Net.SockAddrInet port Net.iNADDR_ANY
diff --git a/Test/test.hs b/Test/test.hs
--- a/Test/test.hs
+++ b/Test/test.hs
@@ -6,6 +6,7 @@
 import qualified Data.ByteString as B
 import Data.ByteString.Char8 ()
 import Crypto.PubKey.OpenSsh
+import Crypto.Types.PubKey.RSA
 import Control.Concurrent
 import System.FilePath
 
@@ -14,10 +15,10 @@
 port = 1874
 host = "127.0.0.1"
 
-readSSHKeys :: FilePath -> IO (OpenSshPublicKey, OpenSshPrivateKey)
+readSSHKeys :: FilePath -> IO (PublicKey, PrivateKey)
 readSSHKeys fp = do
-    pub  <- (either error id . decodePublic) `fmap` B.readFile (fp <.> "pub")
-    priv <- (either error id . (\x -> decodePrivate x Nothing)) `fmap` B.readFile fp
+    OpenSshPublicKeyRsa pub _ <- (either error id . decodePublic) `fmap` B.readFile (fp <.> "pub")
+    OpenSshPrivateKeyRsa priv <- (either error id . (\x -> decodePrivate x Nothing)) `fmap` B.readFile fp
     return (pub,priv)
 
 main = do
diff --git a/commsec-keyexchange.cabal b/commsec-keyexchange.cabal
--- a/commsec-keyexchange.cabal
+++ b/commsec-keyexchange.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                commsec-keyexchange
-version:             0.1
+version:             0.1.1
 synopsis:            Key agreement for commsec.
 description:         Use RSA keys to authenticate a key exchange to
                      establish a commsec 'Connection'.  This package comes with
