diff --git a/.travis.yml b/.travis.yml
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,5 @@
 # NB: don't set `language: haskell` here
+language: c
 
 # See also https://github.com/hvr/multi-ghc-travis for more information
 
@@ -7,27 +8,33 @@
 # release of a major GHC version. Setting HPVER implictly sets
 # GHCVER. Omit lines with versions you don't need/want testing for.
 env:
- - GHCVER=6.12.3
- - GHCVER=7.0.1
- - GHCVER=7.0.2
- - GHCVER=7.0.3
- - GHCVER=7.0.4
- - GHCVER=7.2.1
- - GHCVER=7.2.2
- - GHCVER=7.4.1
- - GHCVER=7.4.2
- - GHCVER=7.6.1
- - GHCVER=7.6.2
- - GHCVER=7.6.3
- - GHCVER=head
+#- CABALVER=1.16 GHCVER=6.12.3
+ - CABALVER=1.16 GHCVER=7.0.1
+ - CABALVER=1.16 GHCVER=7.0.2
+ - CABALVER=1.16 GHCVER=7.0.3
+ - CABALVER=1.16 GHCVER=7.0.4
+ - CABALVER=1.16 GHCVER=7.2.1
+ - CABALVER=1.16 GHCVER=7.2.2
+ - CABALVER=1.16 GHCVER=7.4.1
+ - CABALVER=1.16 GHCVER=7.4.2
+ - CABALVER=1.16 GHCVER=7.6.1
+ - CABALVER=1.16 GHCVER=7.6.2
+ - CABALVER=1.18 GHCVER=7.6.3
+ - CABALVER=1.18 GHCVER=7.8.1
+ - CABALVER=1.18 GHCVER=7.8.2
+ - CABALVER=1.18 GHCVER=7.8.3
+ - CABALVER=1.18 GHCVER=7.8.4
+ - CABALVER=1.22 GHCVER=7.10.1
+ - CABALVER=1.22 GHCVER=7.10.2
+ - CABALVER=head GHCVER=head
  - HPVER=2013.2.0.0
  - HPVER=2012.4.0.0
  - HPVER=2012.2.0.0
-#- HPVER=2011.4.0.0
+ - HPVER=2011.4.0.0
 
 matrix:
   allow_failures:
-   - env: GHCVER=head
+   - env: CABALVER=head GHCVER=head
 
 # Note: the distinction between `before_install` and `install` is not
 #       important.
@@ -35,19 +42,28 @@
  - case "$HPVER" in
     "") ;;
 
+    "2014.2.0.0")
+      export CABALVER=1.18 ;
+      export GHCVER=7.8.3 ;
+      echo "constraints:async==2.0.1.5,attoparsec==0.10.4.0,case-insensitive==1.1.0.3,fgl==5.5.0.1,GLUT==2.5.1.1,GLURaw==1.4.0.1,haskell-src==1.0.1.6,hashable==1.2.2.0,html==1.0.1.2,HTTP==4000.2.10,HUnit==1.2.5.2,mtl==2.1.3.1,network==2.4.2.3,OpenGL==2.9.2.0,OpenGLRaw==1.5.0.0,parallel==3.2.0.4,parsec==3.1.5,primitive==0.5.2.1,QuickCheck==2.6,random==1.0.1.1,regex-base==0.93.2,regex-compat==0.95.1,regex-posix==0.95.2,split==0.2.2,stm==2.4.2,syb==0.4.1,text==1.1.0.0,transformers==0.3.0.0,unordered-containers==0.2.4.0,vector==0.10.9.1,xhtml==3000.2.1,zlib==0.5.4.1" > cabal.config ;;
+
     "2013.2.0.0")
+      export CABALVER=1.16 ;
       export GHCVER=7.6.3 ;
       echo "constraints:async==2.0.1.4,attoparsec==0.10.4.0,case-insensitive==1.0.0.1,cgi==3001.1.7.5,fgl==5.4.2.4,GLUT==2.4.0.0,GLURaw==1.3.0.0,haskell-src==1.0.1.5,hashable==1.1.2.5,html==1.0.1.2,HTTP==4000.2.8,HUnit==1.2.5.2,mtl==2.1.2,network==2.4.1.2,OpenGL==2.8.0.0,OpenGLRaw==1.3.0.0,parallel==3.2.0.3,parsec==3.1.3,QuickCheck==2.6,random==1.0.1.1,regex-base==0.93.2,regex-compat==0.95.1,regex-posix==0.95.2,split==0.2.2,stm==2.4.2,syb==0.4.0,text==0.11.3.1,transformers==0.3.0.0,unordered-containers==0.2.3.0,vector==0.10.0.1,xhtml==3000.2.1,zlib==0.5.4.1" > cabal.config ;;
 
     "2012.4.0.0")
+      export CABALVER=1.16 ;
       export GHCVER=7.6.2 ;
       echo "constraints:async==2.0.1.3,cgi==3001.1.7.4,fgl==5.4.2.4,GLUT==2.1.2.1,haskell-src==1.0.1.5,html==1.0.1.2,HTTP==4000.2.5,HUnit==1.2.5.1,mtl==2.1.2,network==2.3.1.0,OpenGL==2.2.3.1,parallel==3.2.0.3,parsec==3.1.3,QuickCheck==2.5.1.1,random==1.0.1.1,regex-base==0.93.2,regex-compat==0.95.1,regex-posix==0.95.2,split==0.2.1.1,stm==2.4,syb==0.3.7,text==0.11.2.3,transformers==0.3.0.0,vector==0.10.0.1,xhtml==3000.2.1,zlib==0.5.4.0" > cabal.config ;;
 
     "2012.2.0.0")
+      export CABALVER=1.16 ;
       export GHCVER=7.4.1 ;
       echo "constraints:cgi==3001.1.7.4,fgl==5.4.2.4,GLUT==2.1.2.1,haskell-src==1.0.1.5,html==1.0.1.2,HTTP==4000.2.3,HUnit==1.2.4.2,mtl==2.1.1,network==2.3.0.13,OpenGL==2.2.3.1,parallel==3.2.0.2,parsec==3.1.2,QuickCheck==2.4.2,random==1.0.1.1,regex-base==0.93.2,regex-compat==0.95.1,regex-posix==0.95.1,stm==2.3,syb==0.3.6.1,text==0.11.2.0,transformers==0.3.0.0,xhtml==3000.2.1,zlib==0.5.3.3" > cabal.config ;;
 
     "2011.4.0.0")
+      export CABALVER=1.16 ;
       export GHCVER=7.0.4 ;
       echo "constraints:cgi==3001.1.7.4,fgl==5.4.2.4,GLUT==2.1.2.1,haskell-src==1.0.1.4,html==1.0.1.2,HUnit==1.2.4.2,network==2.3.0.5,OpenGL==2.2.3.0,parallel==3.1.0.1,parsec==3.1.1,QuickCheck==2.4.1.1,regex-base==0.93.2,regex-compat==0.95.1,regex-posix==0.95.1,stm==2.2.0.1,syb==0.3.3,xhtml==3000.2.0.4,zlib==0.5.3.1,HTTP==4000.1.2,deepseq==1.1.0.2" > cabal.config ;;
 
@@ -58,41 +74,37 @@
 
    esac
 
- - sudo add-apt-repository -y ppa:hvr/ghc
- - sudo apt-get update
- - sudo apt-get install cabal-install-1.18 ghc-$GHCVER
- - export PATH=/opt/ghc/$GHCVER/bin:$PATH
+ - travis_retry sudo add-apt-repository -y ppa:hvr/ghc
+ - travis_retry sudo apt-get update
+ - travis_retry sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER
+ - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
 
 install:
- - cabal-1.18 update
- - cabal-1.18 install Cabal-1.18.1.2
- - cabal-1.18 install --only-dependencies --enable-tests -f-test-hlint
+ - cabal --version
+ - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
+ - travis_retry cabal update
+ - cabal install --only-dependencies --enable-tests -f-test-hlint
 
 # Here starts the actual work to be performed for the package under
 # test; any command which exits with a non-zero exit code causes the
 # build to fail.
 script:
+ - if [ -f configure.ac ]; then autoreconf -i; fi
  # -v2 provides useful information for debugging
- - cabal-1.18 configure --enable-tests -f-test-hlint -v2
+ - cabal configure --enable-tests -f-test-hlint -v2
 
  # this builds all libraries and executables
  # (including tests/benchmarks)
- - cabal-1.18 build
+ - cabal build
 
- - cabal-1.18 test
- - cabal-1.18 check
+ - cabal test
+ - cabal check
 
  # tests that a source-distribution can be generated
- - cabal-1.18 sdist
+ - cabal sdist
 
  # check that the generated source-distribution can be built & installed
- - export SRC_TGZ=$(cabal-1.18 info . | awk '{print $2 ".tar.gz";exit}') ;
-   cd dist/;
-   if [ -f "$SRC_TGZ" ]; then
-      cabal-1.18 install "$SRC_TGZ";
-   else
-      echo "expected '$SRC_TGZ' not found";
-      exit 1;
-   fi
+ - SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&
+   (cd dist && cabal install --force-reinstalls "$SRC_TGZ")
 
 # EOF
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,17 @@
+0.0.3.0
+-------
+
+  * Tighten dependencies everywhere for cleaner builds.
+  * Fix old code (including compatibility with newer `QuickCheck` versions)
+  * New API: `toPublicKey :: SecretKey -> PublicKey`
+    - Used to derive the public key for a given secret key
+  * New API: `createKeypairFromSeed :: ByteString -> (PublicKey, SecretKey)`
+    - Used to create a deterministic Ed25519 keypair from a 32-byte seed.
+  * For GHC 7.2 and above, both `PublicKey` and `SecretKey` are
+    now instances of `Generic`.
+  * Improved documentation.
+  * Various cleanups and some fixes in the tests and benchmarks.
+
 0.0.2.0
 -------
 
diff --git a/LICENSE.txt b/LICENSE.txt
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,4 +1,4 @@
-Copyright (c) 2013 Austin Seipp
+Copyright (c) 2013-2015 Austin Seipp
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
diff --git a/benchmarks/bench1.hs b/benchmarks/bench1.hs
--- a/benchmarks/bench1.hs
+++ b/benchmarks/bench1.hs
@@ -23,7 +23,7 @@
 main :: IO ()
 main = do
   keys@(pk,sk) <- createKeypair
-  let dummy = B.pack [1..512]
+  let dummy = B.pack [0..255]
       msg = sign sk dummy
   defaultMain
     [ bench "createKeypair" $ nfIO createKeypair
diff --git a/ed25519.cabal b/ed25519.cabal
--- a/ed25519.cabal
+++ b/ed25519.cabal
@@ -1,19 +1,22 @@
 name:                ed25519
-version:             0.0.2.0
+version:             0.0.3.0
 category:            Cryptography
 license:             MIT
 synopsis:            ed25519 cryptographic signatures
 homepage:            http://thoughtpolice.github.com/hs-ed25519
 bug-reports:         http://github.com/thoughtpolice/hs-ed25519/issues
 license-file:        LICENSE.txt
-copyright:           Copyright (c) Austin Seipp 2013
+copyright:           Copyright (c) Austin Seipp 2013-2015
 author:              Austin Seipp
 maintainer:          Austin Seipp <aseipp@pobox.com>
 build-type:          Simple
 cabal-version:       >=1.10
-tested-with:         GHC == 6.12.3, GHC == 7.0.1, GHC == 7.0.2, GHC == 7.0.3,
-                     GHC == 7.0.4,  GHC == 7.2.1, GHC == 7.2.2, GHC == 7.4.1,
-                     GHC == 7.4.2,  GHC == 7.6.1,  GHC == 7.6.2, GHC == 7.6.3
+tested-with:         GHC == 6.12.3,
+                     GHC == 7.0.1, GHC == 7.0.2, GHC == 7.0.3, GHC == 7.0.4,
+                     GHC == 7.2.1, GHC == 7.2.2, GHC == 7.4.1, GHC == 7.4.2,
+                     GHC == 7.6.1, GHC == 7.6.2, GHC == 7.6.3,
+                     GHC == 7.8.2, GHC == 7.8.3, GHC == 7.8.4,
+                     GHC == 7.10.1, GHC == 7.10.2
 
 description:
   This package provides a simple, portable implementation of the
@@ -55,14 +58,15 @@
 
 library
   build-depends:
-    base >= 4 && < 5,
-    bytestring
+    ghc-prim    >= 0.1 && < 0.5,
+    base        >= 4   && < 5,
+    bytestring  >= 0.9 && < 0.11
 
   exposed-modules:
     Crypto.Sign.Ed25519
 
   ghc-options:        -Wall -fwarn-tabs
-  default-language:   Haskell98
+  default-language:   Haskell2010
   hs-source-dirs:     src
   c-sources:          src/cbits/ed25519.c
   include-dirs:       src/cbits src/cbits/include
@@ -75,16 +79,16 @@
   main-is: properties.hs
   ghc-options: -w
   hs-source-dirs: tests
-  default-language:   Haskell98
+  default-language:   Haskell2010
 
   if !flag(test-properties)
     buildable: False
   else
     build-depends:
-      base,
-      ed25519,
-      bytestring,
-      QuickCheck  >= 2.4
+      base        >= 4   && < 5,
+      bytestring  >= 0.9 && < 0.11,
+      QuickCheck  >= 2.4 && < 2.9,
+      ed25519
 
 --
 -- Style/doc tests below
@@ -95,14 +99,14 @@
   main-is: hlint.hs
   ghc-options: -w
   hs-source-dirs: tests
-  default-language:   Haskell98
+  default-language:   Haskell2010
 
   if !flag(test-hlint)
     buildable: False
   else
     build-depends:
-      base,
-      hlint >= 1.7
+      base  >= 4   && < 5,
+      hlint >= 1.7 && < 1.10
 
 -------------------------------------------------------------------------------
 -- Build pt 3: benchmarks
@@ -110,12 +114,12 @@
 benchmark bench1
   type:               exitcode-stdio-1.0
   build-depends:
-    base >= 4 && < 5,
-    bytestring,
-    criterion,
-    deepseq,
-    ed25519
+      base        >= 4   && < 5,
+      bytestring  >= 0.9 && < 0.11,
+      criterion   >= 0.8 && < 1.2,
+      deepseq     >= 1.3 && < 1.5,
+      ed25519
 
-  default-language:   Haskell98
+  default-language:   Haskell2010
   hs-source-dirs:     benchmarks
   main-is:            bench1.hs
diff --git a/src/Crypto/Sign/Ed25519.hs b/src/Crypto/Sign/Ed25519.hs
--- a/src/Crypto/Sign/Ed25519.hs
+++ b/src/Crypto/Sign/Ed25519.hs
@@ -1,7 +1,14 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE ForeignFunctionInterface #-}
+
+#if __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE DeriveGeneric #-}
+#endif
+
 -- |
 -- Module      : Crypto.Sign.Ed25519
--- Copyright   : (c) Austin Seipp 2013
+-- Copyright   : (c) Austin Seipp 2013-2015
 -- License     : MIT
 --
 -- Maintainer  : aseipp@pobox.com
@@ -18,16 +25,20 @@
 --
 module Crypto.Sign.Ed25519
        ( -- * Keypair creation
-         PublicKey(..)       -- :: *
-       , SecretKey(..)       -- :: *
-       , createKeypair       -- :: IO (PublicKey, SecretKey)
+         PublicKey(..)         -- :: *
+       , SecretKey(..)         -- :: *
+       , createKeypair         -- :: IO (PublicKey, SecretKey)
+       , createKeypairFromSeed -- :: ByteString -> (PublicKey, SecretKey)
+       , toPublicKey           -- :: SecretKey -> PublicKey
+
          -- * Signing and verifying messages
-       , sign                -- :: SecretKey -> ByteString -> ByteString
-       , verify              -- :: PublicKey -> ByteString -> Bool
+       , sign                 -- :: SecretKey -> ByteString -> ByteString
+       , verify               -- :: PublicKey -> ByteString -> Bool
+
          -- * Detached signatures
-       , Signature(..)       -- :: *
-       , sign'               -- :: SecretKey -> ByteString -> Signature
-       , verify'             -- :: PublicKey -> ByteString -> Signature -> Bool
+       , Signature(..)        -- :: *
+       , sign'                -- :: SecretKey -> ByteString -> Signature
+       , verify'              -- :: PublicKey -> ByteString -> Signature -> Bool
        ) where
 import           Foreign.C.Types
 import           Foreign.ForeignPtr       (withForeignPtr)
@@ -37,23 +48,34 @@
 
 import           System.IO.Unsafe         (unsafePerformIO)
 
+import           Control.Monad            (unless)
+
 import           Data.ByteString          as S
 import           Data.ByteString.Internal as SI
 import           Data.ByteString.Unsafe   as SU
 import           Data.Word
 
+#if __GLASGOW_HASKELL__ >= 702
+import           GHC.Generics             (Generic)
+#endif
+
 --------------------------------------------------------------------------------
 
--- | A 'SecretKey' created by 'createKeypair'. Be sure to keep this
+-- | A @'SecretKey'@ created by @'createKeypair'@. Be sure to keep this
 -- safe!
 newtype SecretKey = SecretKey { unSecretKey :: ByteString }
         deriving (Eq, Show, Ord)
 
--- | A 'PublicKey' created by 'createKeypair'.
+-- | A @'PublicKey'@ created by @'createKeypair'@.
 newtype PublicKey = PublicKey { unPublicKey :: ByteString }
         deriving (Eq, Show, Ord)
 
--- | Randomly generate a public and private key for doing
+#if __GLASGOW_HASKELL__ >= 702
+deriving instance Generic PublicKey
+deriving instance Generic SecretKey
+#endif
+
+-- | Randomly generate a @'SecretKey'@ and @'PublicKey'@ for doing
 -- authenticated signing and verification.
 createKeypair :: IO (PublicKey, SecretKey)
 createKeypair = do
@@ -69,12 +91,43 @@
   return (PublicKey $ SI.fromForeignPtr pk 0 cryptoSignPUBLICKEYBYTES,
           SecretKey $ SI.fromForeignPtr sk 0 cryptoSignSECRETKEYBYTES)
 
+-- | Generate a deterministic @'PublicKey'@ and @'SecretKey'@ from a
+-- given 32-byte seed. Note that this will @'fail'@ if the given input
+-- is not 32 bytes in length.
+createKeypairFromSeed :: ByteString             -- ^ Two byte seed input
+                      -> (PublicKey, SecretKey) -- ^ Resulting keypair
+createKeypairFromSeed seed = unsafePerformIO $ do
+  unless (S.length seed == cryptoSignSEEDBYTES)
+    (fail "seed has incorrect length")
+  pk <- SI.mallocByteString cryptoSignPUBLICKEYBYTES
+  sk <- SI.mallocByteString cryptoSignSECRETKEYBYTES
+
+  _ <- SU.unsafeUseAsCString seed $ \pseed -> do
+    _ <- withForeignPtr pk $ \ppk -> do
+      _ <- withForeignPtr sk $ \psk -> do
+        _ <- c_crypto_sign_seed_keypair ppk psk pseed
+        return ()
+      return ()
+    return ()
+
+  return (PublicKey $ SI.fromForeignPtr pk 0 cryptoSignPUBLICKEYBYTES,
+          SecretKey $ SI.fromForeignPtr sk 0 cryptoSignSECRETKEYBYTES)
+
+-- | Calculate the @'PublicKey'@ for a given @'SecretKey'@.
+toPublicKey :: SecretKey -- ^ Any valid @'SecretKey'@
+            -> PublicKey -- ^ Corresponding @'PublicKey'@
+toPublicKey = PublicKey . S.drop prefixBytes  . unSecretKey
+  where prefixBytes = cryptoSignSECRETKEYBYTES - cryptoSignPUBLICKEYBYTES
+
 --------------------------------------------------------------------------------
 -- Main API
 
--- | Sign a message with a particular 'SecretKey'.
+-- | Sign a message with a particular @'SecretKey'@. Note that the resulting
+-- signed message contains both the message itself, and the signature
+-- attached. If you only want the signature of a given input string,
+-- please see @'sign''@.
 sign :: SecretKey
-     -- ^ Signers secret key
+     -- ^ Signers @'SecretKey'@
      -> ByteString
      -- ^ Input message
      -> ByteString
@@ -84,17 +137,20 @@
     SU.unsafeUseAsCString sk $ \psk ->
       SI.createAndTrim (mlen+cryptoSignBYTES) $ \out ->
         alloca $ \smlen -> do
-          _ <- (c_crypto_sign out smlen mstr (fromIntegral mlen) psk)
+          _ <- c_crypto_sign out smlen mstr (fromIntegral mlen) psk
           fromIntegral `fmap` peek smlen
 {-# INLINE sign #-}
 
--- | Verifies a signed message against a 'PublicKey'.
+-- | Verifies a signed message against a @'PublicKey'@. Note that the input
+-- message must be generated by @'sign'@ (that is, it is the message
+-- itself plus its signature). If you want to verify an arbitrary
+-- signature against an arbitrary message, please see @'verify''@.
 verify :: PublicKey
-       -- ^ Signers public key
+       -- ^ Signers @'PublicKey'@
        -> ByteString
        -- ^ Signed message
        -> Bool
-       -- ^ Verification check
+       -- ^ Verification result
 verify (PublicKey pk) xs =
   unsafePerformIO . SU.unsafeUseAsCStringLen xs $ \(smstr,smlen) ->
     SU.unsafeUseAsCString pk $ \ppk ->
@@ -109,39 +165,39 @@
 --------------------------------------------------------------------------------
 -- Detached signature support
 
--- | A 'Signature' which is detached from the message it signed.
+-- | A @'Signature'@ which is detached from the message it signed.
 newtype Signature = Signature { unSignature :: ByteString }
         deriving (Eq, Show, Ord)
 
--- | Sign a message with a particular 'SecretKey', only returning the
--- signature without the message.
+-- | Sign a message with a particular @'SecretKey'@, only returning the
+-- @'Signature'@ without the message.
 sign' :: SecretKey
-      -- ^ Signers secret key
+      -- ^ Signers @'SecretKey'@
       -> ByteString
       -- ^ Input message
       -> Signature
-      -- ^ Message signature, without the message
+      -- ^ Message @'Signature'@, without the message
 sign' sk xs =
   let sm = sign sk xs
       l  = S.length sm
   in Signature $! S.take (l - S.length xs) sm
 {-# INLINE sign' #-}
 
--- | Verify a message with a detached 'Signature', for a given
--- 'PublicKey'.
+-- | Verify a message with a detached @'Signature'@ against a given
+-- @'PublicKey'@.
 verify' :: PublicKey
-        -- ^ Signers public key
+        -- ^ Signers @'PublicKey'@
         -> ByteString
-        -- ^ Input message, without signature
+        -- ^ Raw input message
         -> Signature
-        -- ^ Message signature
+        -- ^ Message @'Signature'@
         -> Bool
+        -- ^ Verification result
 verify' pk xs (Signature sig) = verify pk (sig `S.append` xs)
 {-# INLINE verify' #-}
 
---
--- FFI signature binding
---
+--------------------------------------------------------------------------------
+-- FFI binding
 
 cryptoSignSECRETKEYBYTES :: Int
 cryptoSignSECRETKEYBYTES = 64
@@ -151,6 +207,13 @@
 
 cryptoSignBYTES :: Int
 cryptoSignBYTES = 64
+
+cryptoSignSEEDBYTES :: Int
+cryptoSignSEEDBYTES = 32
+
+foreign import ccall unsafe "ed25519_sign_seed_keypair"
+  c_crypto_sign_seed_keypair :: Ptr Word8 -> Ptr Word8
+                                -> Ptr CChar -> IO CInt
 
 foreign import ccall unsafe "ed25519_sign_keypair"
   c_crypto_sign_keypair :: Ptr Word8 -> Ptr Word8 -> IO CInt
diff --git a/src/cbits/include/ed25519.h b/src/cbits/include/ed25519.h
--- a/src/cbits/include/ed25519.h
+++ b/src/cbits/include/ed25519.h
@@ -8,6 +8,8 @@
 #define crypto_sign_IMPLEMENTATION crypto_sign_ed25519_IMPLEMENTATION
 #define crypto_sign_VERSION crypto_sign_ed25519_VERSION
 
+int ed25519_sign_seed_keypair(unsigned char *pk, unsigned char *sk,
+                              const unsigned char *seed);
 int ed25519_sign_keypair(unsigned char *pk,unsigned char *sk);
 int ed25519_sign(unsigned char *sm,unsigned long long *smlen,
                  const unsigned char *m,unsigned long long mlen,
diff --git a/src/cbits/keypair.c b/src/cbits/keypair.c
--- a/src/cbits/keypair.c
+++ b/src/cbits/keypair.c
@@ -1,23 +1,35 @@
+#include <string.h>
 #include "randombytes.h"
 #include "ed25519.h"
 #include "sha512.h"
 #include "ge.h"
 
-int ed25519_sign_keypair(unsigned char *pk,unsigned char *sk)
+int ed25519_sign_seed_keypair(unsigned char *pk, unsigned char *sk,
+                              const unsigned char *seed)
 {
-  unsigned char h[64];
-  ge_p3 A;
-  int i;
+    ge_p3 A;
 
-  ed25519_randombytes(sk,32);
-  crypto_hash_sha512(h,sk,32);
-  h[0] &= 248;
-  h[31] &= 63;
-  h[31] |= 64;
+    crypto_hash_sha512(sk,seed,32);
+    sk[0] &= 248;
+    sk[31] &= 63;
+    sk[31] |= 64;
 
-  ge_scalarmult_base(&A,h);
-  ge_p3_tobytes(pk,&A);
+    ge_scalarmult_base(&A,sk);
+    ge_p3_tobytes(pk,&A);
 
-  for (i = 0;i < 32;++i) sk[32 + i] = pk[i];
-  return 0;
+    memmove(sk, seed, 32);
+    memmove(sk + 32, pk, 32);
+    return 0;
+}
+
+int ed25519_sign_keypair(unsigned char *pk, unsigned char *sk)
+{
+    unsigned char seed[32];
+    int           ret;
+
+    ed25519_randombytes(seed, sizeof seed);
+    ret = ed25519_sign_seed_keypair(pk, sk, seed);
+    memset(seed, 0, sizeof seed);
+
+    return ret;
 }
diff --git a/tests/hlint.hs b/tests/hlint.hs
--- a/tests/hlint.hs
+++ b/tests/hlint.hs
@@ -9,6 +9,8 @@
 main :: IO ()
 main = do
     args <- getArgs
-    hints <- hlint $ ["src", "benchmarks", "tests",
-                      "--cpp-define=HLINT"] `mappend` args
+    hints <- hlint $ [ "src", "benchmarks", "tests"
+                     , "--cpp-define=HLINT"
+                     , "--cpp-file=dist/build/autogen/cabal_macros.h"
+                     ] `mappend` args
     unless (null hints) exitFailure
diff --git a/tests/properties.hs b/tests/properties.hs
--- a/tests/properties.hs
+++ b/tests/properties.hs
@@ -86,7 +86,9 @@
       case r of
         Success n _ _           -> return (True, n)
         GaveUp  n _ _           -> return (True, n)
-#if MIN_VERSION_QuickCheck(2,6,0)
+#if MIN_VERSION_QuickCheck(2,7,0)
+        Failure n _ _ _ _ _ _ _ _ _ -> return (False, n)
+#elif MIN_VERSION_QuickCheck(2,6,0)
         Failure n _ _ _ _ _ _ _ -> return (False, n)
 #else
         Failure n _ _ _ _ _ _   -> return (False, n)
