aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Assistant/MakeRemote.hs8
-rw-r--r--Crypto.hs11
-rw-r--r--Remote/Helper/Encryptable.hs11
-rw-r--r--Test.hs1
-rw-r--r--Utility/Gpg.hs16
-rw-r--r--doc/design/encryption.mdwn13
6 files changed, 41 insertions, 19 deletions
diff --git a/Assistant/MakeRemote.hs b/Assistant/MakeRemote.hs
index 448f7ad97..866585319 100644
--- a/Assistant/MakeRemote.hs
+++ b/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'
diff --git a/Crypto.hs b/Crypto.hs
index be326bf4c..21b1ae41b 100644
--- a/Crypto.hs
+++ b/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
diff --git a/Remote/Helper/Encryptable.hs b/Remote/Helper/Encryptable.hs
index f3b6bb787..ff7d4990b 100644
--- a/Remote/Helper/Encryptable.hs
+++ b/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.
-
diff --git a/Test.hs b/Test.hs
index 56c70573d..ec578f591 100644
--- a/Test.hs
+++ b/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"
diff --git a/Utility/Gpg.hs b/Utility/Gpg.hs
index c31755d62..4a13d456c 100644
--- a/Utility/Gpg.hs
+++ b/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
diff --git a/doc/design/encryption.mdwn b/doc/design/encryption.mdwn
index 45eb43cc9..6a380abe1 100644
--- a/doc/design/encryption.mdwn
+++ b/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