summaryrefslogtreecommitdiffhomepage
path: root/Share.hs
diff options
context:
space:
mode:
authorJoey Hess <joeyh@joeyh.name>2016-08-19 16:36:46 -0400
committerJoey Hess <joeyh@joeyh.name>2016-08-19 16:36:46 -0400
commit0afe2e6177b48078db381d26334d3f4fd13363da (patch)
treece23c42a9273394c0738978a6e0724d69b90777a /Share.hs
parentfdc80b7a2416782d3208acf154fb8afb7fb2279b (diff)
downloadkeysafe-0afe2e6177b48078db381d26334d3f4fd13363da.tar.gz
chunking
This changed the storage format, not that it matters because nobody is using it yet.
Diffstat (limited to 'Share.hs')
-rw-r--r--Share.hs57
1 files changed, 35 insertions, 22 deletions
diff --git a/Share.hs b/Share.hs
index 2788f72..76d118c 100644
--- a/Share.hs
+++ b/Share.hs
@@ -18,18 +18,21 @@ import qualified Raaz.Core.Encode as Raaz
import qualified Raaz.Hash.Sha256 as Raaz
import qualified Data.Text as T
import qualified Data.Text.Encoding as E
+import qualified Data.Set as S
import Data.Monoid
-import Control.DeepSeq
data ShareIdents = ShareIdents
- { getIdents :: [StorableObjectIdent]
- -- ^ An infinite list of idents to use for shares.
+ { identsStream :: [S.Set StorableObjectIdent]
+ -- ^ Each item in the infinite list is the idents to
+ -- use for the shares of a chunk of data.
, identsCreationCost :: Cost CreationOp
, identsBruteForceCalc :: CostCalc BruteForceOp UnknownName
}
-instance NFData ShareIdents where
- rnf = rnf . getIdents
+nextShareIdents :: ShareIdents -> (S.Set StorableObjectIdent, ShareIdents)
+nextShareIdents sis =
+ let (s:rest) = identsStream sis
+ in (s, sis { identsStream = rest })
instance HasCreationCost ShareIdents where
getCreationCost = identsCreationCost
@@ -45,7 +48,7 @@ instance Bruteforceable ShareIdents UnknownName where
-- when the same name is chosen for multiple keys.
shareIdents :: Tunables -> Name -> SecretKeySource -> ShareIdents
shareIdents tunables (Name name) keyid =
- ShareIdents idents creationcost bruteforcecalc
+ ShareIdents (segmentbyshare idents) creationcost bruteforcecalc
where
(ExpensiveHash creationcost basename) =
expensiveHash hashtunables (Salt keyid) name
@@ -53,31 +56,41 @@ shareIdents tunables (Name name) keyid =
E.encodeUtf8 $ basename <> T.pack (show n)
mksha :: B.ByteString -> Raaz.Base16
mksha = Raaz.encode . Raaz.sha256
- idents = map mk [1..]
bruteforcecalc = bruteForceLinearSearch creationcost
hashtunables = nameGenerationHash $ nameGenerationTunable tunables
+ idents = map mk ([1..] :: [Integer])
+ m = totalObjects (shareParams tunables)
+ segmentbyshare l =
+ let (shareis, l') = splitAt m l
+ in S.fromList shareis : segmentbyshare l'
-genShares :: EncryptedSecretKey -> Tunables -> IO [Share]
-genShares (EncryptedSecretKey esk _) tunables = do
- shares <- SS.encode
- (neededObjects $ shareParams tunables)
- (totalObjects $ shareParams tunables)
- (BL.fromStrict esk)
- return $ map (\(n, share) -> Share n (StorableObject $ encodeShare share))
- (zip [1..] shares)
+-- | Generates shares of an EncryptedSecretKey.
+-- Each chunk of the key creates its own set of shares.
+genShares :: EncryptedSecretKey -> Tunables -> IO [S.Set Share]
+genShares (EncryptedSecretKey cs _) tunables = do
+ shares <- mapM encode cs
+ return $ map (S.fromList . map (uncurry Share) . zip [1..]) shares
+ where
+ encode :: B.ByteString -> IO [StorableObject]
+ encode b = map (StorableObject . encodeShare)
+ <$> SS.encode
+ (neededObjects $ shareParams tunables)
+ (totalObjects $ shareParams tunables)
+ (BL.fromStrict b)
-combineShares :: Tunables -> [Share] -> Either String EncryptedSecretKey
+-- | If not enough sets of shares are provided, the EncryptedSecretKey may
+-- be incomplete, only containing some chunks of the key
+combineShares :: Tunables -> [S.Set Share] -> Either String EncryptedSecretKey
combineShares tunables shares
- | null shares =
- Left "No shares could be downloaded. Perhaps you entered the wrong name or password?"
- | length shares < neededObjects (shareParams tunables) =
+ | null shares || any null shares || any (\l -> length l < sharesneeded) shares =
Left "Not enough shares are currently available to reconstruct your data."
- | otherwise = Right $ mk $ SS.decode $ map decodeshare shares
+ | otherwise = Right $ mk $
+ map (BL.toStrict . SS.decode . map decodeshare . S.toList) shares
where
- mk b = EncryptedSecretKey (BL.toStrict b) unknownCostCalc
+ mk cs = EncryptedSecretKey cs unknownCostCalc
decodeshare (Share sharenum so) = decodeShare sharenum sharesneeded $
fromStorableObject so
- sharesneeded = neededObjects $ shareParams tunables
+ sharesneeded = neededObjects (shareParams tunables)
-- | This efficient encoding relies on the share using a finite field of
-- size 256, so it maps directly to bytes.