* 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
import Common
import CmdLine.GitAnnex.Options
import qualified Utility.RawFilePath as R
+import Data.String
import qualified Utility.ShellEscape
import qualified Annex
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
, 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
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"
, remoteAnnexRsyncTransport :: [String]
, remoteAnnexGnupgOptions :: [String]
, remoteAnnexGnupgDecryptOptions :: [String]
+ , remoteAnnexSharedSOPCommand :: Maybe String
+ , remoteAnnexSharedSOPProfile :: Maybe String
, remoteAnnexRsyncUrl :: Maybe String
, remoteAnnexBupRepo :: Maybe String
, remoteAnnexBorgRepo :: Maybe String
, 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"
module Utility.StatelessOpenPGP (
SopCmd(..),
+ SopSubCmd,
+ Password,
+ Profile,
+ Armoring(..),
encryptSymmetric,
decryptSymmetric,
test_encrypt_decrypt_Symmetric,
{- 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
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
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
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.