diff --git a/ByteStrings.hs b/ByteStrings.hs
--- a/ByteStrings.hs
+++ b/ByteStrings.hs
@@ -1,5 +1,3 @@
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-
 {- Copyright 2016 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
@@ -9,8 +7,6 @@
 
 import qualified Data.ByteString as B
 import qualified Raaz
-import Control.Monad
-import Data.Word
 
 allByteStringsOfLength :: Int -> [B.ByteString]
 allByteStringsOfLength = go []
@@ -34,9 +30,8 @@
 			let (h, t) = B.splitAt n b
 			in go (h:cs) t
 
-instance Raaz.Random Word8
-
-randomByteStringOfLength :: Int -> Raaz.SystemPRG -> IO B.ByteString
-randomByteStringOfLength n prg = B.pack <$> replicateM n randbyte
+randomByteStringOfLength :: Int -> IO B.ByteString
+randomByteStringOfLength n = Raaz.securely gen
   where
-	randbyte = Raaz.random prg :: IO Word8
+	gen :: Raaz.RandM B.ByteString
+	gen = Raaz.randomByteString (Raaz.BYTES n)
diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,9 @@
+keysafe (0.20170303) unstable; urgency=medium
+
+  * Updated to use raaz-0.1.1.
+
+ -- Joey Hess <id@joeyh.name>  Fri, 03 Mar 2017 16:15:47 -0400
+
 keysafe (0.20170122) unstable; urgency=medium
 
   * Adjust cabal bounds to allow building with ghc 8.0.
diff --git a/Encryption.hs b/Encryption.hs
--- a/Encryption.hs
+++ b/Encryption.hs
@@ -32,10 +32,9 @@
 encrypt tunables kek (SecretKey secret) = 
 	EncryptedSecretKey (chunkByteString (objectSize tunables) b) (keyBruteForceCalc kek)
   where
-	-- Raaz does not seem to provide a high-level interface
-	-- for AES encryption, so use unsafeEncrypt. The use of 
-	-- EncryptableBytes makes sure it's provided with a 
-	-- multiple of the AES block size.
+	-- Raaz does not provide a high-level interface for AES encryption,
+	-- so we use unsafeEncrypt. The use of EncryptableBytes makes
+	-- sure it's provided with a  multiple of the AES block size.
 	b = Raaz.unsafeEncrypt cipher (keyEncryptionKey kek, keyEncryptionIV kek) $
 		getEncryptableBytes $ encodeEncryptableBytes tunables secret
 
@@ -104,8 +103,7 @@
 -- run the hash repeatedly.
 genKeyEncryptionKey :: Tunables -> Name -> Password -> IO KeyEncryptionKey
 genKeyEncryptionKey tunables name password = do
-	prg <- Raaz.newPRG () :: IO Raaz.SystemPRG
-	saltprefix <- genRandomSaltPrefix prg tunables
+	saltprefix <- genRandomSaltPrefix tunables
 	return $ head $
 		genKeyEncryptionKeys [saltprefix] tunables name password
 
@@ -144,12 +142,12 @@
 		Raaz.fromByteString $ B.take ivlen $
 			Raaz.toByteString $ Raaz.sha256 name
   where
-	ivlen = fromIntegral $ Raaz.byteSize (undefined :: Raaz.IV)
+	ivlen = fromIntegral $ Raaz.sizeOf (undefined :: Raaz.IV)
 
 type SaltPrefix = B.ByteString
 
-genRandomSaltPrefix :: Raaz.SystemPRG -> Tunables -> IO SaltPrefix
-genRandomSaltPrefix prg tunables = randomByteStringOfLength n prg
+genRandomSaltPrefix :: Tunables -> IO SaltPrefix
+genRandomSaltPrefix tunables = randomByteStringOfLength n
   where
 	n = randomSaltBytes $ keyEncryptionKeyTunable tunables
 
@@ -164,7 +162,7 @@
 	fromMaybe (error "hashToAESKey fromByteString failed") $
 		Raaz.fromByteString b
   where
-	b = B.take (fromIntegral $ Raaz.byteSize (undefined :: AesKey)) $
+	b = B.take (fromIntegral $ Raaz.sizeOf (undefined :: AesKey)) $
 		Raaz.toByteString $ Raaz.sha256 (E.encodeUtf8 t)
 
 -- | A bytestring that can be AES encrypted.
diff --git a/HTTP/ProofOfWork.hs b/HTTP/ProofOfWork.hs
--- a/HTTP/ProofOfWork.hs
+++ b/HTTP/ProofOfWork.hs
@@ -95,10 +95,13 @@
 
 newtype RequestIDSecret = RequestIDSecret (Raaz.Key (Raaz.HMAC Raaz.SHA256))
 
+-- | Random data is generated insecurely, eg not locked in memory because
+-- this is a transient secret.
 newRequestIDSecret :: IO RequestIDSecret
-newRequestIDSecret = do
-	prg <- Raaz.newPRG () :: IO Raaz.SystemPRG
-	RequestIDSecret <$> Raaz.random prg
+newRequestIDSecret = RequestIDSecret <$> Raaz.insecurely gen
+  where
+	gen :: Raaz.RandM (Raaz.Key (Raaz.HMAC Raaz.SHA256))
+	gen = Raaz.random
 
 mkRequestID :: RequestIDSecret -> IO RequestID
 mkRequestID secret = mkRequeestID' secret <$> mkRandomSalt
@@ -113,11 +116,15 @@
 	let rid' = mkRequeestID' secret (randomSalt rid)
 	in requestHMAC rid == requestHMAC rid'
 
+-- | Random data is generated insecurely, eg not locked in memory because
+-- this is a transient secret.
 mkRandomSalt :: IO RandomSalt
 mkRandomSalt = do
-	prg <- Raaz.newPRG () :: IO Raaz.SystemPRG
-	rs <- replicateM 16 (Raaz.random prg :: IO Word8)
+	rs <- Raaz.insecurely $ replicateM 16 gen
 	return $ RandomSalt $ T.pack $ concatMap show rs
+  where
+	gen :: Raaz.RandM Word8
+	gen = Raaz.random
 
 class POWIdent p where
 	getPOWIdent :: p -> B.ByteString
diff --git a/HTTP/Server.hs b/HTTP/Server.hs
--- a/HTTP/Server.hs
+++ b/HTTP/Server.hs
@@ -18,7 +18,6 @@
 import Storage.Local
 import Serialization ()
 import Servant
-import Network.Wai
 import Network.Wai.Handler.Warp
 import Control.Monad.IO.Class
 import Control.Concurrent
diff --git a/Share.hs b/Share.hs
--- a/Share.hs
+++ b/Share.hs
@@ -94,7 +94,8 @@
 combineShares :: Tunables -> [S.Set Share] -> Either String EncryptedSecretKey
 combineShares tunables shares
 	| null shares || any null shares || any (\l -> length l < sharesneeded) shares = 
-		Left "Not enough shares are currently available to reconstruct your data."
+		Left $ "Not enough shares are currently available to reconstruct your data. " ++
+			concatMap (\l -> "(Got " ++ show (length l) ++ "/" ++ show sharesneeded ++ ") ") shares
 	| otherwise = Right $ mk $
 		map (BL.toStrict . SS.decode . map decodeshare . S.toList) shares
   where
diff --git a/Storage.hs b/Storage.hs
--- a/Storage.hs
+++ b/Storage.hs
@@ -26,7 +26,6 @@
 import qualified Data.Set as S
 import System.Random
 import System.Random.Shuffle
-import qualified Raaz
 
 networkStorageLocations :: Maybe LocalStorageDirectory -> StorageLocations
 networkStorageLocations = StorageLocations . serverList
@@ -171,25 +170,24 @@
 storeChaff hn port delayseconds = forever $ do
 	say $ "Sending chaff to " ++ hn ++ " (press ctrl-c to stop)"
 	say "Legend: + = successful upload, ! = upload failure"
-	prg <- Raaz.newPRG () :: IO Raaz.SystemPRG
-	randomname <- randomByteStringOfLength 128 prg
+	randomname <- randomByteStringOfLength 128
 	-- It's ok the use the testModeTunables here because
 	-- the randomname is not something that can be feasibly guessed.
 	-- Prefix "random chaff" to the name to avoid ever using a name
 	-- that a real user might want to use.
 	let sis = shareIdents testModeTunables (Name $ "random chaff:" <> randomname) AnyGpgKey
-	mapConcurrently (go sis prg)
+	mapConcurrently (go sis)
 		[1..totalObjects (shareParams testModeTunables)]
   where
 	server = networkStorage Untrusted Nothing $ 
 		Server (ServerName hn) [ServerAddress hn port] "chaff server"
 	objsize = objectSize defaultTunables * shareOverhead defaultTunables
 	maxmsdelay = ceiling $ 1000000 * fromMaybe 0 delayseconds
-	go sis prg n = do
+	go sis n = do
 		msdelay <- getStdRandom (randomR (0, maxmsdelay))
 		delay msdelay
 
-		b <- randomByteStringOfLength objsize prg
+		b <- randomByteStringOfLength objsize
 		let share = Share 0 (StorableObject b)
 		let (is, sis') = nextShareIdents sis
 		let i = S.toList is !! (n - 1)
@@ -197,7 +195,7 @@
 		case r of
 			StoreSuccess -> progress "+"
 			_ -> progress "!"
-		go sis' prg n
+		go sis' n
 
 -- | Shuffles the list, keeping Recommended first, then
 -- Alternate, and finally Untrusted.
diff --git a/TODO b/TODO
--- a/TODO
+++ b/TODO
@@ -2,6 +2,20 @@
 
 * Finish vetting 2 servers to Recommended.
 * Set up --check-servers in a cron job, so I know when servers are down.
+* Remove gpg key passohrase from gpg keys that keysafe backs up.
+  The reason for this is that the user may well forget their gpg key
+  passphrase, and it's *weird* to restore a key with keysafe's password
+  and then have it passphrase protected.
+  The gpg key passphrase is intended only to keep a key from being used
+  for a short period of time (a week or so) when the device holding it 
+  is known to have been compromised, so the key can be revoked.
+  This doesn't really apply to keys backed up with keysafe -- if they get
+  compromised somehow, the user won't know, and cracking the gpg passphrase
+  should be almost trivial to an attacker who was able to break keysafe's
+  password.
+  paperkey can remove gpg key passphrases. Is there any better way?
+  It might make sense for keysafe to prompt for a new gpg passphrase
+  when restoring.
 
 Later:
 
@@ -25,11 +39,6 @@
 * Add some random padding to http requests and responses, to make it
   harder for traffic analysis to tell that given TOR traffic is
   keysafe traffic.
-* Argon2d is more resistent to GPU/ASIC attack optimisation.
-  Switching from Argon2i would require new tunables, and delay restores
-  (of keys backed up using the old tunables, and when the user provides the
-  wrong name) by ~10 minutes, so deferred for now
-  until there's some other reason to change the tunables.
 
 Wishlist:
 
@@ -72,3 +81,20 @@
   restore from working. (It also makes a malicious data attack (as described
   in https://keysafe.branchable.com/details/) possible by attackers who do not
   control the servers.
+
+Encryption tunables changes:
+
+* Argon2d is more resistent to GPU/ASIC attack optimisation.
+  Switching from Argon2i would require new tunables, and delay restores
+  (of keys backed up using the old tunables, and when the user provides the
+  wrong name) by ~10 minutes, so deferred for now
+  until there's some other reason to change the tunables.
+* The ShareIdents derivation currently appends a number and sha256 hashes
+  to generate a stream of values. Ben M points out that HMAC is a more
+  typical way to do such a thing. Even better, a HKDF-Expand
+  (RFC5869) can generate a stream which can then be chunked up into values.  
+  Either of these would avoid a full pre-image attack on SHA-2 breaking
+  keysafe. Of course, such an SHA-2 attack would be a general security
+  disaster. HKDF may prove more robust in the face of partial SHA-2 breaks.
+  Deferred for now until tthere's some other reason to change keysafe's
+  tunables.
diff --git a/keysafe.cabal b/keysafe.cabal
--- a/keysafe.cabal
+++ b/keysafe.cabal
@@ -1,5 +1,5 @@
 Name: keysafe
-Version: 0.20170122
+Version: 0.20170303
 Cabal-Version: >= 1.8
 Maintainer: Joey Hess <joey@kitenet.net>
 Author: Joey Hess
@@ -38,7 +38,7 @@
     -- the version ranges, it's important to run keysafe --test
       secret-sharing == 1.0.*
     , argon2 == 1.2.*
-    , raaz == 0.0.2
+    , raaz == 0.1.1
     , base (>= 4.5 && < 5.0)
     , bytestring == 0.10.*
     , text == 1.2.*
