test annex.shared-sop-command
authorJoey Hess <joeyh@joeyh.name>
Wed, 10 Jan 2024 20:30:38 +0000 (16:30 -0400)
committerJoey Hess <joeyh@joeyh.name>
Wed, 10 Jan 2024 20:30:38 +0000 (16:30 -0400)
Test a specified Stateless OpenPGP command with eg:
git-annex test --test-git-config annex.shared-sop-command=sqop

Also documented that config and another one, but so far only the test suite
uses the configs, have not yet implemented using it for actual symmetric
encryption.

Sponsored-by: Joshua Antonishen on Patreon
CHANGELOG
Test.hs
Types/GitConfig.hs
Utility/StatelessOpenPGP.hs
doc/encryption.mdwn
doc/git-annex-test.mdwn
doc/git-annex.mdwn

index 60aee29a071c3027d3295d13f427342112f1cfcd..7e2796be3f31889b4752a96d14819aa5452b9558 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,6 +4,8 @@ git-annex (10.20231228) UNRELEASED; urgency=medium
   * import: Sped up import from special remotes.
   * assistant: When generating a gpg secret key, avoid hardcoding the
     key algorithm and size.
+  * test: Test a specified Stateless OpenPGP command when
+    run with eg --test-git-config annex.shared-sop-command=sqop
 
  -- Joey Hess <id@joeyh.name>  Fri, 29 Dec 2023 11:52:06 -0400
 
diff --git a/Test.hs b/Test.hs
index 9856974d7856da84775a67f22d72ef51ef577a1f..75a963ca8713b73fb108f40d2666db83e28fe4c3 100644 (file)
--- a/Test.hs
+++ b/Test.hs
@@ -27,6 +27,7 @@ import Control.Concurrent.STM hiding (check)
 import Common
 import CmdLine.GitAnnex.Options
 import qualified Utility.RawFilePath as R
+import Data.String
 
 import qualified Utility.ShellEscape
 import qualified Annex
@@ -82,6 +83,7 @@ import qualified Utility.FileSystemEncoding
 import qualified Utility.Aeson
 import qualified Utility.CopyFile
 import qualified Utility.MoveFile
+import qualified Utility.StatelessOpenPGP
 import qualified Types.Remote
 #ifndef mingw32_HOST_OS
 import qualified Remote.Helper.Encryptable
@@ -347,7 +349,8 @@ repoTests note numparts = map mk $ sep
        , testCase "rsync remote" test_rsync_remote
        , testCase "bup remote" test_bup_remote
        , testCase "borg remote" test_borg_remote
-       , testCase "crypto" test_crypto
+       , testCase "gpg crypto" test_gpg_crypto
+       , testCase "sop crypto" test_sop_crypto
        , testCase "preferred content" test_preferred_content
        , testCase "required_content" test_required_content
        , testCase "add subdirs" test_add_subdirs
@@ -1824,10 +1827,29 @@ test_borg_remote = when BuildInfo.borg $ do
                git_annex "drop" [annexedfile] "drop from borg (appendonly)"
                git_annex "get" [annexedfile, "--from=borg"] "get from borg"
 
+-- To test Stateless OpenPGP, annex.shared-sop-command has to be set using
+-- the --test-git-config option.
+test_sop_crypto :: Assertion
+test_sop_crypto = do
+       gc <- testGitConfig . testOptions <$> getTestMode
+       case filter (\(k, _) -> k == ck) gc of
+               [] -> noop
+               ((_, sopcmd):_) -> go $ 
+                       Utility.StatelessOpenPGP.SopCmd $
+                               Git.Types.fromConfigValue sopcmd
+  where
+       ck = fromString "annex.shared-sop-command"
+       pw = fromString "testpassword"
+       v = fromString "somevalue"
+       unarmored = Utility.StatelessOpenPGP.Armoring False
+       go sopcmd = do
+               Utility.StatelessOpenPGP.test_encrypt_decrypt_Symmetric sopcmd sopcmd pw unarmored v
+                       @? "sop command roundtrips symmetric encryption"
+
 -- gpg is not a build dependency, so only test when it's available
-test_crypto :: Assertion
+test_gpg_crypto :: Assertion
 #ifndef mingw32_HOST_OS
-test_crypto = do
+test_gpg_crypto = do
        testscheme "shared"
        testscheme "hybrid"
        testscheme "pubkey"
index 6ded7b6df3bc1b1c8561a195f23e9b06f796e4e4..cb8ecdf003f859d929bfb290c8740b5197b76e95 100644 (file)
@@ -372,6 +372,8 @@ data RemoteGitConfig = RemoteGitConfig
        , remoteAnnexRsyncTransport :: [String]
        , remoteAnnexGnupgOptions :: [String]
        , remoteAnnexGnupgDecryptOptions :: [String]
+       , remoteAnnexSharedSOPCommand :: Maybe String
+       , remoteAnnexSharedSOPProfile :: Maybe String
        , remoteAnnexRsyncUrl :: Maybe String
        , remoteAnnexBupRepo :: Maybe String
        , remoteAnnexBorgRepo :: Maybe String
@@ -439,6 +441,8 @@ extractRemoteGitConfig r remotename = do
                , remoteAnnexRsyncTransport = getoptions "rsync-transport"
                , remoteAnnexGnupgOptions = getoptions "gnupg-options"
                , remoteAnnexGnupgDecryptOptions = getoptions "gnupg-decrypt-options"
+               , remoteAnnexSharedSOPCommand = notempty $ getmaybe "shared-sop-command"
+               , remoteAnnexSharedSOPProfile = notempty $ getmaybe "shared-sop-profile"
                , remoteAnnexRsyncUrl = notempty $ getmaybe "rsyncurl"
                , remoteAnnexBupRepo = getmaybe "buprepo"
                , remoteAnnexBorgRepo = getmaybe "borgrepo"
index e6ca08b54c2986eb4487b23083818e5ec4a33dee..dfee3ec3c561d7cfae4b9243429c15033eefb12c 100644 (file)
@@ -9,6 +9,10 @@
 
 module Utility.StatelessOpenPGP (
        SopCmd(..),
+       SopSubCmd,
+       Password,
+       Profile,
+       Armoring(..),
        encryptSymmetric,
        decryptSymmetric,
        test_encrypt_decrypt_Symmetric,
@@ -98,7 +102,7 @@ decryptSymmetric sopcmd password emptydirectory feeder reader =
 
 {- Test a value round-trips through symmetric encryption and decryption. -}
 test_encrypt_decrypt_Symmetric :: SopCmd -> SopCmd -> Password -> Armoring -> B.ByteString -> IO Bool
-test_encrypt_decrypt_Symmetric a b password armoring v =
+test_encrypt_decrypt_Symmetric a b password armoring v = catchBoolIO $
        withTmpDir "test" $ \d -> do
                let ed = EmptyDirectory d
                enc <- encryptSymmetric a password ed Nothing armoring
index 50d479b898e4242e6cf13fdb5692d08f774bf008..970232d216a5183697990390d20bf50476f56620 100644 (file)
@@ -76,6 +76,14 @@ The advantage is you don't need to set up gpg keys. The disadvantage is
 that this is **insecure** unless you trust every clone of the git
 repository with access to the encrypted data stored in the special remote.
 
+By default `gpg` is used for shared encryption, but it is also possible to
+use other programs that implement the Stateless OpenPGP command line
+interface. For example, to use Sequoia PGP's `sqop` command, configured to
+be backwards compatable with `gpg`:
+
+    git config annex.shared-sop-command sqop
+    git config annex.shared-sop-profile rfc4880
+
 ## regular public key encryption (encryption=pubkey)
 
 This alternative simply encrypts the files in the special remotes to one or
index 18a219c6b2d893a63ef7e12bcf5a48fd03eed77d..83bdc5bd3e90af65419ae62679d99f85c7c0ace6 100644 (file)
@@ -44,6 +44,10 @@ framework. Pass --help for details about those.
   One valid use of this is to change a git configuration to a value that
   is planned to be the new default in a future version of git.
 
+  Also, some things can only be tested with a git configuration. For
+  example, annex.shared-sop-command has to be set for the test suite to
+  test using that command.
+
 * `--test-debug`
 
   Normally output of commands run by the test suite is hidden, so even
index 5f43deb1ee1d772cfff959c6bb4d02242c788d98..deeb4703eaf7b28515ed8006bd0008f59fccd0bb 100644 (file)
@@ -1655,10 +1655,29 @@ Remotes are configured using these settings in `.git/config`.
   precedence over the default GnuPG configuration, which is otherwise
   used.)
 
+* `remote.<name>.annex-shared-sop-command`
+
+  Use this command, which is an implementation of the Stateless OpenPGP
+  command line interface, rather than GnuPG for encrypting and decrypting
+  data. This is only used when a special remote is configured with
+  encryption=shared.
+
+  For example, to use Sequoia PGP's sqop command, set this to "sqop".
+
+* `remote.<name>.annex-shared-sop-profile`
+
+  When encrypting with a Stateless OpenPGP command, this can be used
+  to specify the profile to use, such as "rfc4880".
+
+  For a list of available profiles, run eg "sqop list-profiles encrypt"
+
+  sqop list-profiles encrypt
+
 * `annex.ssh-options`, `annex.rsync-options`,
   `annex.rsync-upload-options`, `annex.rsync-download-options`,
   `annex.bup-split-options`, `annex.gnupg-options`,
-  `annex.gnupg-decrypt-options`
+  `annex.gnupg-decrypt-options`,
+  `annex.shared-sop-command`, `annex.shared-sop-profile`
 
   Default options to use if a remote does not have more specific options
   as described above.