packages feed

keysafe 0.20170122 → 0.20170303

raw patch · 9 files changed

+70/−40 lines, 9 filesdep ~raaz

Dependency ranges changed: raaz

Files

ByteStrings.hs view
@@ -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)
CHANGELOG view
@@ -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.
Encryption.hs view
@@ -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.
HTTP/ProofOfWork.hs view
@@ -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
HTTP/Server.hs view
@@ -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
Share.hs view
@@ -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
Storage.hs view
@@ -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.
TODO view
@@ -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.
keysafe.cabal view
@@ -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.*