Generate ciphers with a better entropy.
Unless highRandomQuality=false (or --fast) is set, use Libgcypt's 'GCRY_VERY_STRONG_RANDOM' level by default for cipher generation, like it's done for OpenPGP key generation. On the assistant side, the random quality is left to the old (lower) level, in order not to scare the user with an enless page load due to the blocking PRNG waiting for IO actions.
This commit is contained in:
parent
602baae12e
commit
00fc21bfec
6 changed files with 41 additions and 19 deletions
|
@ -69,11 +69,15 @@ makeRsyncRemote name location = makeRemote name location $
|
|||
, ("type", "rsync")
|
||||
]
|
||||
|
||||
{- Inits a special remote. -}
|
||||
{- Inits a special remote. Currently, only 'weak' ciphers can be
|
||||
- generated from the assistant, because otherwise GnuPG may block once
|
||||
- the entropy pool is drained, and as of now there's no way to tell the
|
||||
- user to perform IO actions to refill the pool. -}
|
||||
makeSpecialRemote :: String -> RemoteType -> R.RemoteConfig -> Annex ()
|
||||
makeSpecialRemote name remotetype config = do
|
||||
(u, c) <- Command.InitRemote.findByName name
|
||||
c' <- R.setup remotetype u $ M.union config c
|
||||
c' <- R.setup remotetype u $
|
||||
M.insert "highRandomQuality" "false" $ M.union config c
|
||||
describeUUID u name
|
||||
configSet u c'
|
||||
|
||||
|
|
11
Crypto.hs
11
Crypto.hs
|
@ -67,15 +67,16 @@ cipherMac :: Cipher -> String
|
|||
cipherMac (Cipher c) = take cipherBeginning c
|
||||
|
||||
{- Creates a new Cipher, encrypted to the specified key id. -}
|
||||
genEncryptedCipher :: String -> IO StorableCipher
|
||||
genEncryptedCipher keyid = do
|
||||
genEncryptedCipher :: String -> Bool -> IO StorableCipher
|
||||
genEncryptedCipher keyid highQuality = do
|
||||
ks <- Gpg.findPubKeys keyid
|
||||
random <- Gpg.genRandom cipherSize
|
||||
random <- Gpg.genRandom highQuality cipherSize
|
||||
encryptCipher (Cipher random) ks
|
||||
|
||||
{- Creates a new, shared Cipher. -}
|
||||
genSharedCipher :: IO StorableCipher
|
||||
genSharedCipher = SharedCipher <$> Gpg.genRandom cipherSize
|
||||
genSharedCipher :: Bool -> IO StorableCipher
|
||||
genSharedCipher highQuality =
|
||||
SharedCipher <$> Gpg.genRandom highQuality cipherSize
|
||||
|
||||
{- Updates an existing Cipher, re-encrypting it to add a keyid. -}
|
||||
updateEncryptedCipher :: String -> StorableCipher -> IO StorableCipher
|
||||
|
|
|
@ -31,15 +31,20 @@ encryptionSetup c = case (M.lookup "encryption" c, extractCipher c) of
|
|||
(Just "none", Just _) -> cannotchange
|
||||
(Just "shared", Just (EncryptedCipher _ _)) -> cannotchange
|
||||
(Just _, Just (SharedCipher _)) -> cannotchange
|
||||
(Just "shared", Nothing) -> use "encryption setup" $ genSharedCipher
|
||||
(Just keyid, Nothing) -> use "encryption setup" $ genEncryptedCipher keyid
|
||||
(Just "shared", Nothing) -> use "encryption setup" . genSharedCipher
|
||||
=<< highRandomQuality
|
||||
(Just keyid, Nothing) -> use "encryption setup" . genEncryptedCipher keyid
|
||||
=<< highRandomQuality
|
||||
(Just keyid, Just v) -> use "encryption updated" $ updateEncryptedCipher keyid v
|
||||
where
|
||||
cannotchange = error "Cannot change encryption type of existing remote."
|
||||
use m a = do
|
||||
cipher <- liftIO a
|
||||
showNote $ m ++ " " ++ describeCipher cipher
|
||||
return $ M.delete "encryption" $ storeCipher c cipher
|
||||
return $ M.delete "encryption" $ M.delete "highRandomQuality" $
|
||||
storeCipher c cipher
|
||||
highRandomQuality = (&&) (maybe True (/="false") (M.lookup "highRandomQuality" c))
|
||||
<$> fmap not (Annex.getState Annex.fast)
|
||||
|
||||
{- Modifies a Remote to support encryption.
|
||||
-
|
||||
|
|
1
Test.hs
1
Test.hs
|
@ -735,6 +735,7 @@ test_crypto = "git-annex crypto" ~: intmpclonerepo $ when Build.SysConfig.gpg $
|
|||
, "type=directory"
|
||||
, "encryption=" ++ Utility.Gpg.testKeyId
|
||||
, "directory=dir"
|
||||
, "highRandomQuality=false"
|
||||
]
|
||||
initremote @? "initremote failed"
|
||||
initremote @? "initremote failed when run twice in a row"
|
||||
|
|
|
@ -85,7 +85,8 @@ feedRead params passphrase feeder reader = do
|
|||
reader from
|
||||
|
||||
{- Finds gpg public keys matching some string. (Could be an email address,
|
||||
- a key id, or a name. -}
|
||||
- a key id, or a name; See the section 'HOW TO SPECIFY A USER ID' of
|
||||
- GnuPG's manpage.) -}
|
||||
findPubKeys :: String -> IO KeyIds
|
||||
findPubKeys for = KeyIds . parse <$> readStrict params
|
||||
where
|
||||
|
@ -97,8 +98,8 @@ findPubKeys for = KeyIds . parse <$> readStrict params
|
|||
{- Creates a block of high-quality random data suitable to use as a cipher.
|
||||
- It is armored, to avoid newlines, since gpg only reads ciphers up to the
|
||||
- first newline. -}
|
||||
genRandom :: Int -> IO String
|
||||
genRandom size = checksize <$> readStrict
|
||||
genRandom :: Bool -> Int -> IO String
|
||||
genRandom highQuality size = checksize <$> readStrict
|
||||
[ Params params
|
||||
, Param $ show randomquality
|
||||
, Param $ show size
|
||||
|
@ -106,8 +107,13 @@ genRandom size = checksize <$> readStrict
|
|||
where
|
||||
params = "--gen-random --armor"
|
||||
|
||||
-- 1 is /dev/urandom; 2 is /dev/random
|
||||
randomquality = 1 :: Int
|
||||
-- See http://www.gnupg.org/documentation/manuals/gcrypt/Quality-of-random-numbers.html
|
||||
-- for the meaning of random quality levels.
|
||||
-- The highest available is 2, which is the default for OpenPGP
|
||||
-- key generation; Note that it uses the blocking PRNG /dev/random
|
||||
-- on the Linux kernel, hence the running time may take a while.
|
||||
randomquality :: Int
|
||||
randomquality = if highQuality then 2 else 1
|
||||
|
||||
{- The size is the number of bytes of entropy desired; the data is
|
||||
- base64 encoded, so needs 8 bits to represent every 6 bytes of
|
||||
|
|
|
@ -23,10 +23,15 @@ The basis of this scheme was originally developed by Lars Wirzenius et al
|
|||
[for Obnam](http://liw.fi/obnam/encryption/).
|
||||
"""]]
|
||||
|
||||
Data is encrypted by gpg, using a symmetric cipher.
|
||||
The cipher is itself checked into your git repository, encrypted using one or
|
||||
more gpg public keys. This scheme allows new gpg private keys to be given
|
||||
access to content that has already been stored in the remote.
|
||||
Data is encrypted by GnuPG, using a symmetric cipher. The cipher is
|
||||
generated by GnuPG when the special remote is created. By default the
|
||||
best entropy pool is used, hence the generation may take a while; One
|
||||
can use `initremote` with `highRandomQuality=false` or `--fast` options
|
||||
to speed up things, but at the expense of using random numbers of a
|
||||
lower quality. The generated cipher is then checked into your git
|
||||
repository, encrypted using one or more OpenPGP public keys. This scheme
|
||||
allows new OpenPGP private keys to be given access to content that has
|
||||
already been stored in the remote.
|
||||
|
||||
Different encrypted remotes need to be able to each use different ciphers.
|
||||
Allowing multiple ciphers to be used within a single remote would add a lot
|
||||
|
|
Loading…
Add table
Reference in a new issue