Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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.
  • Loading branch information...
commit 00fc21bfec2e24a9a41d3860ee9ac2fdf3f1a465 1 parent 602baae
guilhem authored committed
View
8 Assistant/MakeRemote.hs
@@ -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'
View
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
View
11 Remote/Helper/Encryptable.hs
@@ -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.
-
View
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"
View
16 Utility/Gpg.hs
@@ -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
View
13 doc/design/encryption.mdwn
@@ -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

0 comments on commit 00fc21b

Please sign in to comment.
Something went wrong with that request. Please try again.