assistant: When generating a gpg secret key, avoid hardcoding the key algorithm and...
authorJoey Hess <joeyh@joeyh.name>
Tue, 9 Jan 2024 19:31:53 +0000 (15:31 -0400)
committerJoey Hess <joeyh@joeyh.name>
Tue, 9 Jan 2024 19:31:53 +0000 (15:31 -0400)
This aims to future-proof gpg key generation. OpenPGP is in flux with a
conflict over standards ongoing. It seems not unlikely that different
systems will have different gpg commands that support different algorithms.

This also simplifies the code by using the --quick-gen-key interface rather
than the experimental batch interface. It seems less likely that
--quick-gen-key will break than an experimental interface (whose
documentation I can no longer find).

--quick-gen-key is supported since gpg 2.1.0 (2014).

Sponsored-by: Graham Spencer on Patreon
Assistant/WebApp/Gpg.hs
CHANGELOG
Utility/Gpg.hs
templates/configurators/genkeymodal.hamlet

index 3723d03907bbd65d0f267e99543027d64d6e43f2..79c36a2e0eac3ca423348ff57fa6d3a972053298 100644 (file)
@@ -54,7 +54,7 @@ withNewSecretKey :: (KeyId -> Handler Html) -> Handler Html
 withNewSecretKey use = do
        cmd <- liftAnnex $ gpgCmd <$> Annex.getGitConfig
        userid <- liftIO $ newUserId cmd
-       liftIO $ genSecretKey cmd RSA "" userid maxRecommendedKeySize
+       liftIO $ genSecretKey cmd "" userid
        results <- M.keys . M.filter (== userid) <$> liftIO (secretKeys cmd)
        case results of
                [] -> giveup "Failed to generate gpg key!"
index 3790992b0a3f210675714d8dbddb472164c69e4a..60aee29a071c3027d3295d13f427342112f1cfcd 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,8 @@ git-annex (10.20231228) UNRELEASED; urgency=medium
 
   * info: Added "annex sizes of repositories" table to the overall display.
   * import: Sped up import from special remotes.
+  * assistant: When generating a gpg secret key, avoid hardcoding the
+    key algorithm and size.
 
  -- Joey Hess <id@joeyh.name>  Fri, 29 Dec 2023 11:52:06 -0400
 
index 288499ff8e64da0ce12ed3e37131e85fa1380f5b..7a62066bb6b6cdde3b49f5e5d54a4f7a5334a4bd 100644 (file)
@@ -23,8 +23,6 @@ module Utility.Gpg (
        findPubKeys,
        UserId,
        secretKeys,
-       KeyType(..),
-       maxRecommendedKeySize,
        genSecretKey,
        genRandom,
        testKeyId,
@@ -60,6 +58,8 @@ newtype KeyIds = KeyIds { keyIds :: [KeyId] }
 
 newtype GpgCmd = GpgCmd { unGpgCmd :: String }
 
+type Passphrase = B.ByteString
+
 {- Get gpg command to use, Just what's specified or, if a specific gpg
  - command was found at configure time, use it, or otherwise, "gpg". -}
 mkGpgCmd :: Maybe FilePath -> GpgCmd
@@ -157,7 +157,7 @@ pipeStrict' (GpgCmd cmd) params environ input = do
  - the passphrase.
  -
  - Note that the reader must fully consume gpg's input before returning. -}
-feedRead :: (MonadIO m, MonadMask m) => GpgCmd -> [CommandParam] -> B.ByteString -> (Handle -> IO ()) -> (Handle -> m a) -> m a
+feedRead :: (MonadIO m, MonadMask m) => GpgCmd -> [CommandParam] -> Passphrase -> (Handle -> IO ()) -> (Handle -> m a) -> m a
 feedRead cmd params passphrase feeder reader = do
 #ifndef mingw32_HOST_OS
        let setup = liftIO $ do
@@ -260,49 +260,29 @@ secretKeys cmd = catchDefaultIO M.empty makemap
        extract c k (_:rest) =
                extract c k rest
 
-type Passphrase = String
-type Size = Int
-data KeyType = Algo Int | DSA | RSA
-
-{- The maximum key size that gpg currently offers in its UI when
- - making keys. -}
-maxRecommendedKeySize :: Size
-maxRecommendedKeySize = 4096
-
 {- Generates a secret key using the experimental batch mode.
  - The key is added to the secret key ring.
  - Can take a very long time, depending on system entropy levels.
  -}
-genSecretKey :: GpgCmd -> KeyType -> Passphrase -> UserId -> Size -> IO ()
-genSecretKey (GpgCmd cmd) keytype passphrase userid keysize =
-       let p = (proc cmd params)
-               { std_in = CreatePipe }
-       in withCreateProcess p (go p)
+genSecretKey :: GpgCmd -> Passphrase -> UserId -> IO ()
+genSecretKey gpgcmd passphrase userid =
+       feedRead gpgcmd params passphrase feeder reader
   where
-       params = ["--batch", "--gen-key"]
-
-       go p (Just h) _ _ pid = do
-               hPutStr h $ unlines $ catMaybes
-                       [ Just $  "Key-Type: " ++ 
-                               case keytype of
-                                       DSA -> "DSA"
-                                       RSA -> "RSA"
-                                       Algo n -> show n
-                       , Just $ "Key-Length: " ++ show keysize
-                       , Just $ "Name-Real: " ++ userid
-                       , Just "Expire-Date: 0"
-                       , if null passphrase
-                               then Nothing
-                               else Just $ "Passphrase: " ++ passphrase
-                       ]
-               hClose h
-               forceSuccessProcess p pid
-       go _ _ _ _ _ = error "internal"
+       params =
+               [ Param "--batch"
+               , Param "--quick-gen-key"
+               , Param userid
+               , Param "default" -- algo
+               , Param "default" -- usage
+               , Param "never" -- expire
+               ]
+       feeder = hClose
+       reader = void . hGetContents
 
 {- 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 :: GpgCmd -> Bool -> Size -> IO B.ByteString
+genRandom :: GpgCmd -> Bool -> Int -> IO B.ByteString
 genRandom cmd highQuality size = do
        s <- readStrict cmd params
        checksize s
index 23c386305482530daba11e538505f064adbf8a15..b8f47cb5131aea554dc18aa3383cfd31b121da1c 100644 (file)
@@ -5,7 +5,7 @@
         <div .modal-header>
           <h3>
             <img src="@{StaticR activityicon_gif}" alt=""> #
-            Generating a #{maxRecommendedKeySize} bit GnuPg key.
+            Generating a GnuPg key.
         <div .modal-body>
         <p>
           Generating a GnuPg key can take a long time. To speed up the process, #