Added new encryption=sharedpubkey mode for special remotes.
This is useful for makking a special remote that anyone with a clone of the repo and your public keys can upload files to, but only you can decrypt the files stored in it.
This commit is contained in:
parent
2d00523609
commit
e219289c83
7 changed files with 114 additions and 63 deletions
59
Crypto.hs
59
Crypto.hs
|
@ -18,8 +18,8 @@ module Crypto (
|
||||||
StorableCipher(..),
|
StorableCipher(..),
|
||||||
genEncryptedCipher,
|
genEncryptedCipher,
|
||||||
genSharedCipher,
|
genSharedCipher,
|
||||||
updateEncryptedCipher,
|
genSharedPubKeyCipher,
|
||||||
describeCipher,
|
updateCipherKeyIds,
|
||||||
decryptCipher,
|
decryptCipher,
|
||||||
encryptKey,
|
encryptKey,
|
||||||
isEncKey,
|
isEncKey,
|
||||||
|
@ -74,7 +74,7 @@ cipherMac (Cipher c) = take cipherBeginning c
|
||||||
cipherMac (MacOnlyCipher c) = c
|
cipherMac (MacOnlyCipher c) = c
|
||||||
|
|
||||||
{- Creates a new Cipher, encrypted to the specified key id. -}
|
{- Creates a new Cipher, encrypted to the specified key id. -}
|
||||||
genEncryptedCipher :: Gpg.GpgCmd -> String -> EncryptedCipherVariant -> Bool -> IO StorableCipher
|
genEncryptedCipher :: Gpg.GpgCmd -> Gpg.KeyId -> EncryptedCipherVariant -> Bool -> IO StorableCipher
|
||||||
genEncryptedCipher cmd keyid variant highQuality = do
|
genEncryptedCipher cmd keyid variant highQuality = do
|
||||||
ks <- Gpg.findPubKeys cmd keyid
|
ks <- Gpg.findPubKeys cmd keyid
|
||||||
random <- Gpg.genRandom cmd highQuality size
|
random <- Gpg.genRandom cmd highQuality size
|
||||||
|
@ -89,35 +89,40 @@ genSharedCipher :: Gpg.GpgCmd -> Bool -> IO StorableCipher
|
||||||
genSharedCipher cmd highQuality =
|
genSharedCipher cmd highQuality =
|
||||||
SharedCipher <$> Gpg.genRandom cmd highQuality cipherSize
|
SharedCipher <$> Gpg.genRandom cmd highQuality cipherSize
|
||||||
|
|
||||||
{- Updates an existing Cipher, re-encrypting it to add or remove keyids,
|
{- Creates a new, shared Cipher, and looks up the gpg public key that will
|
||||||
- depending on whether the first component is True or False. -}
|
- be used for encrypting content. -}
|
||||||
updateEncryptedCipher :: Gpg.GpgCmd -> [(Bool, String)] -> StorableCipher -> IO StorableCipher
|
genSharedPubKeyCipher :: Gpg.GpgCmd -> Gpg.KeyId -> Bool -> IO StorableCipher
|
||||||
updateEncryptedCipher _ _ SharedCipher{} = error "Cannot update shared cipher"
|
genSharedPubKeyCipher cmd keyid highQuality = do
|
||||||
updateEncryptedCipher _ [] encipher = return encipher
|
ks <- Gpg.findPubKeys cmd keyid
|
||||||
updateEncryptedCipher cmd newkeys encipher@(EncryptedCipher _ variant (KeyIds ks)) = do
|
random <- Gpg.genRandom cmd highQuality cipherSize
|
||||||
dropKeys <- listKeyIds [ k | (False, k) <- newkeys ]
|
return $ SharedPubKeyCipher random ks
|
||||||
forM_ dropKeys $ \k -> unless (k `elem` ks) $
|
|
||||||
|
{- Updates an existing Cipher, making changes to its keyids.
|
||||||
|
-
|
||||||
|
- When the Cipher is encrypted, re-encrypts it. -}
|
||||||
|
updateCipherKeyIds :: Gpg.GpgCmd -> [(Bool, Gpg.KeyId)] -> StorableCipher -> IO StorableCipher
|
||||||
|
updateCipherKeyIds _ _ SharedCipher{} = error "Cannot update shared cipher"
|
||||||
|
updateCipherKeyIds _ [] c = return c
|
||||||
|
updateCipherKeyIds cmd changes encipher@(EncryptedCipher _ variant ks) = do
|
||||||
|
ks' <- updateCipherKeyIds' cmd changes ks
|
||||||
|
cipher <- decryptCipher cmd encipher
|
||||||
|
encryptCipher cmd cipher variant ks'
|
||||||
|
updateCipherKeyIds cmd changes (SharedPubKeyCipher cipher ks) =
|
||||||
|
SharedPubKeyCipher cipher <$> updateCipherKeyIds' cmd changes ks
|
||||||
|
|
||||||
|
updateCipherKeyIds' :: Gpg.GpgCmd -> [(Bool, Gpg.KeyId)] -> KeyIds -> IO KeyIds
|
||||||
|
updateCipherKeyIds' cmd changes (KeyIds ks) = do
|
||||||
|
dropkeys <- listKeyIds [ k | (False, k) <- changes ]
|
||||||
|
forM_ dropkeys $ \k -> unless (k `elem` ks) $
|
||||||
error $ "Key " ++ k ++ " was not present; cannot remove."
|
error $ "Key " ++ k ++ " was not present; cannot remove."
|
||||||
addKeys <- listKeyIds [ k | (True, k) <- newkeys ]
|
addkeys <- listKeyIds [ k | (True, k) <- changes ]
|
||||||
let ks' = (addKeys ++ ks) \\ dropKeys
|
let ks' = (addkeys ++ ks) \\ dropkeys
|
||||||
when (null ks') $
|
when (null ks') $
|
||||||
error "Cannot remove the last key."
|
error "Cannot remove the last key."
|
||||||
cipher <- decryptCipher cmd encipher
|
return $ KeyIds ks'
|
||||||
encryptCipher cmd cipher variant $ KeyIds ks'
|
|
||||||
where
|
where
|
||||||
listKeyIds = concat <$$> mapM (keyIds <$$> Gpg.findPubKeys cmd)
|
listKeyIds = concat <$$> mapM (keyIds <$$> Gpg.findPubKeys cmd)
|
||||||
|
|
||||||
describeCipher :: StorableCipher -> String
|
|
||||||
describeCipher (SharedCipher _) = "shared cipher"
|
|
||||||
describeCipher (EncryptedCipher _ variant (KeyIds ks)) =
|
|
||||||
scheme ++ " with gpg " ++ keys ks ++ " " ++ unwords ks
|
|
||||||
where
|
|
||||||
scheme = case variant of
|
|
||||||
Hybrid -> "hybrid cipher"
|
|
||||||
PubKey -> "pubkey crypto"
|
|
||||||
keys [_] = "key"
|
|
||||||
keys _ = "keys"
|
|
||||||
|
|
||||||
{- Encrypts a Cipher to the specified KeyIds. -}
|
{- Encrypts a Cipher to the specified KeyIds. -}
|
||||||
encryptCipher :: Gpg.GpgCmd -> Cipher -> EncryptedCipherVariant -> KeyIds -> IO StorableCipher
|
encryptCipher :: Gpg.GpgCmd -> Cipher -> EncryptedCipherVariant -> KeyIds -> IO StorableCipher
|
||||||
encryptCipher cmd c variant (KeyIds ks) = do
|
encryptCipher cmd c variant (KeyIds ks) = do
|
||||||
|
@ -134,6 +139,7 @@ encryptCipher cmd c variant (KeyIds ks) = do
|
||||||
{- Decrypting an EncryptedCipher is expensive; the Cipher should be cached. -}
|
{- Decrypting an EncryptedCipher is expensive; the Cipher should be cached. -}
|
||||||
decryptCipher :: Gpg.GpgCmd -> StorableCipher -> IO Cipher
|
decryptCipher :: Gpg.GpgCmd -> StorableCipher -> IO Cipher
|
||||||
decryptCipher _ (SharedCipher t) = return $ Cipher t
|
decryptCipher _ (SharedCipher t) = return $ Cipher t
|
||||||
|
decryptCipher _ (SharedPubKeyCipher t _) = return $ MacOnlyCipher t
|
||||||
decryptCipher cmd (EncryptedCipher t variant _) =
|
decryptCipher cmd (EncryptedCipher t variant _) =
|
||||||
mkCipher <$> Gpg.pipeStrict cmd [ Param "--decrypt" ] t
|
mkCipher <$> Gpg.pipeStrict cmd [ Param "--decrypt" ] t
|
||||||
where
|
where
|
||||||
|
@ -223,6 +229,7 @@ instance LensGpgEncParams RemoteConfig where
|
||||||
- look up the recipient keys and add them to the option list. -}
|
- look up the recipient keys and add them to the option list. -}
|
||||||
getGpgEncParams c = case M.lookup "encryption" c of
|
getGpgEncParams c = case M.lookup "encryption" c of
|
||||||
Just "pubkey" -> Gpg.pkEncTo $ maybe [] (split ",") $ M.lookup "cipherkeys" c
|
Just "pubkey" -> Gpg.pkEncTo $ maybe [] (split ",") $ M.lookup "cipherkeys" c
|
||||||
|
Just "sharedpubkey" -> Gpg.pkEncTo $ maybe [] (split ",") $ M.lookup "pubkeys" c
|
||||||
_ -> []
|
_ -> []
|
||||||
getGpgDecParams _ = []
|
getGpgDecParams _ = []
|
||||||
|
|
||||||
|
|
|
@ -297,9 +297,9 @@ shellOrRsync r ashell arsync
|
||||||
setGcryptEncryption :: RemoteConfig -> String -> Annex ()
|
setGcryptEncryption :: RemoteConfig -> String -> Annex ()
|
||||||
setGcryptEncryption c remotename = do
|
setGcryptEncryption c remotename = do
|
||||||
let participants = remoteconfig Git.GCrypt.remoteParticipantConfigKey
|
let participants = remoteconfig Git.GCrypt.remoteParticipantConfigKey
|
||||||
case extractCipher c of
|
case cipherKeyIds =<< extractCipher c of
|
||||||
Nothing -> noCrypto
|
Nothing -> noCrypto
|
||||||
Just (EncryptedCipher _ _ (KeyIds { keyIds = ks})) -> do
|
Just (KeyIds { keyIds = ks}) -> do
|
||||||
setConfig participants (unwords ks)
|
setConfig participants (unwords ks)
|
||||||
let signingkey = ConfigKey $ Git.GCrypt.remoteSigningKey remotename
|
let signingkey = ConfigKey $ Git.GCrypt.remoteSigningKey remotename
|
||||||
cmd <- gpgCmd <$> Annex.getGitConfig
|
cmd <- gpgCmd <$> Annex.getGitConfig
|
||||||
|
@ -307,8 +307,6 @@ setGcryptEncryption c remotename = do
|
||||||
case filter (`elem` ks) skeys of
|
case filter (`elem` ks) skeys of
|
||||||
[] -> noop
|
[] -> noop
|
||||||
(k:_) -> setConfig signingkey k
|
(k:_) -> setConfig signingkey k
|
||||||
Just (SharedCipher _) ->
|
|
||||||
unsetConfig participants
|
|
||||||
setConfig (remoteconfig Git.GCrypt.remotePublishParticipantConfigKey)
|
setConfig (remoteconfig Git.GCrypt.remotePublishParticipantConfigKey)
|
||||||
(Git.Config.boolConfig True)
|
(Git.Config.boolConfig True)
|
||||||
where
|
where
|
||||||
|
|
|
@ -14,7 +14,6 @@ module Remote.Helper.Encryptable (
|
||||||
remoteCipher',
|
remoteCipher',
|
||||||
embedCreds,
|
embedCreds,
|
||||||
cipherKey,
|
cipherKey,
|
||||||
storeCipher,
|
|
||||||
extractCipher,
|
extractCipher,
|
||||||
describeEncryption,
|
describeEncryption,
|
||||||
) where
|
) where
|
||||||
|
@ -58,20 +57,18 @@ encryptionSetup c = do
|
||||||
encryption = M.lookup "encryption" c
|
encryption = M.lookup "encryption" c
|
||||||
-- Generate a new cipher, depending on the chosen encryption scheme
|
-- Generate a new cipher, depending on the chosen encryption scheme
|
||||||
genCipher cmd = case encryption of
|
genCipher cmd = case encryption of
|
||||||
_ | M.member "cipher" c || M.member "cipherkeys" c -> cannotchange
|
_ | M.member "cipher" c || M.member "cipherkeys" c || M.member "pubkeys" c -> cannotchange
|
||||||
Just "none" -> return (c, NoEncryption)
|
Just "none" -> return (c, NoEncryption)
|
||||||
Just "shared" -> use "encryption setup" . genSharedCipher cmd
|
Just "shared" -> encsetup $ genSharedCipher cmd
|
||||||
=<< highRandomQuality
|
|
||||||
-- hybrid encryption is the default when a keyid is
|
-- hybrid encryption is the default when a keyid is
|
||||||
-- specified but no encryption
|
-- specified but no encryption
|
||||||
_ | maybe (M.member "keyid" c) (== "hybrid") encryption ->
|
_ | maybe (M.member "keyid" c) (== "hybrid") encryption ->
|
||||||
use "encryption setup" . genEncryptedCipher cmd key Hybrid
|
encsetup $ genEncryptedCipher cmd key Hybrid
|
||||||
=<< highRandomQuality
|
Just "pubkey" -> encsetup $ genEncryptedCipher cmd key PubKey
|
||||||
Just "pubkey" -> use "encryption setup" . genEncryptedCipher cmd key PubKey
|
Just "sharedpubkey" -> encsetup $ genSharedPubKeyCipher cmd key
|
||||||
=<< highRandomQuality
|
|
||||||
_ -> error $ "Specify " ++ intercalate " or "
|
_ -> error $ "Specify " ++ intercalate " or "
|
||||||
(map ("encryption=" ++)
|
(map ("encryption=" ++)
|
||||||
["none","shared","hybrid","pubkey"])
|
["none","shared","hybrid","pubkey", "sharedpubkey"])
|
||||||
++ "."
|
++ "."
|
||||||
key = fromMaybe (error "Specifiy keyid=...") $ M.lookup "keyid" c
|
key = fromMaybe (error "Specifiy keyid=...") $ M.lookup "keyid" c
|
||||||
newkeys = maybe [] (\k -> [(True,k)]) (M.lookup "keyid+" c) ++
|
newkeys = maybe [] (\k -> [(True,k)]) (M.lookup "keyid+" c) ++
|
||||||
|
@ -82,13 +79,16 @@ encryptionSetup c = do
|
||||||
SharedCipher _ | maybe True (== "shared") encryption -> return (c', EncryptionIsSetup)
|
SharedCipher _ | maybe True (== "shared") encryption -> return (c', EncryptionIsSetup)
|
||||||
EncryptedCipher _ variant _
|
EncryptedCipher _ variant _
|
||||||
| maybe True (== if variant == Hybrid then "hybrid" else "pubkey") encryption ->
|
| maybe True (== if variant == Hybrid then "hybrid" else "pubkey") encryption ->
|
||||||
use "encryption update" $ updateEncryptedCipher cmd newkeys v
|
use "encryption update" $ updateCipherKeyIds cmd newkeys v
|
||||||
|
SharedPubKeyCipher _ _ ->
|
||||||
|
use "encryption update" $ updateCipherKeyIds cmd newkeys v
|
||||||
_ -> cannotchange
|
_ -> cannotchange
|
||||||
|
encsetup a = use "encryption setup" . a =<< highRandomQuality
|
||||||
use m a = do
|
use m a = do
|
||||||
showNote m
|
showNote m
|
||||||
cipher <- liftIO a
|
cipher <- liftIO a
|
||||||
showNote $ describeCipher cipher
|
mapM_ showNote (describeCipher cipher)
|
||||||
return (storeCipher c' cipher, EncryptionIsSetup)
|
return (storeCipher cipher c', EncryptionIsSetup)
|
||||||
highRandomQuality =
|
highRandomQuality =
|
||||||
(&&) (maybe True ( /= "false") $ M.lookup "highRandomQuality" c)
|
(&&) (maybe True ( /= "false") $ M.lookup "highRandomQuality" c)
|
||||||
<$> fmap not (Annex.getState Annex.fast)
|
<$> fmap not (Annex.getState Annex.fast)
|
||||||
|
@ -123,8 +123,8 @@ remoteCipher' c = go $ extractCipher c
|
||||||
- embedcreds=yes allows this, and embedcreds=no prevents it.
|
- embedcreds=yes allows this, and embedcreds=no prevents it.
|
||||||
-
|
-
|
||||||
- If not set, the default is to only store creds when it's surely safe:
|
- If not set, the default is to only store creds when it's surely safe:
|
||||||
- When gpg encryption is used, in which case the creds will be encrypted
|
- When gpg encryption is used and the creds are encrypted using it.
|
||||||
- using it. Not when a shared cipher is used.
|
- Not when a shared cipher is used.
|
||||||
-}
|
-}
|
||||||
embedCreds :: RemoteConfig -> Bool
|
embedCreds :: RemoteConfig -> Bool
|
||||||
embedCreds c
|
embedCreds c
|
||||||
|
@ -141,22 +141,26 @@ cipherKey c = fmap make <$> remoteCipher c
|
||||||
mac = fromMaybe defaultMac $ M.lookup "mac" c >>= readMac
|
mac = fromMaybe defaultMac $ M.lookup "mac" c >>= readMac
|
||||||
|
|
||||||
{- Stores an StorableCipher in a remote's configuration. -}
|
{- Stores an StorableCipher in a remote's configuration. -}
|
||||||
storeCipher :: RemoteConfig -> StorableCipher -> RemoteConfig
|
storeCipher :: StorableCipher -> RemoteConfig -> RemoteConfig
|
||||||
storeCipher c (SharedCipher t) = M.insert "cipher" (toB64bs t) c
|
storeCipher cip = case cip of
|
||||||
storeCipher c (EncryptedCipher t _ ks) =
|
(SharedCipher t) -> addcipher t
|
||||||
M.insert "cipher" (toB64bs t) $ M.insert "cipherkeys" (showkeys ks) c
|
(EncryptedCipher t _ ks) -> addcipher t . storekeys ks "cipherkeys"
|
||||||
|
(SharedPubKeyCipher t ks) -> addcipher t . storekeys ks "pubkeys"
|
||||||
where
|
where
|
||||||
showkeys (KeyIds l) = intercalate "," l
|
addcipher t = M.insert "cipher" (toB64bs t)
|
||||||
|
storekeys (KeyIds l) n = M.insert n (intercalate "," l)
|
||||||
|
|
||||||
{- Extracts an StorableCipher from a remote's configuration. -}
|
{- Extracts an StorableCipher from a remote's configuration. -}
|
||||||
extractCipher :: RemoteConfig -> Maybe StorableCipher
|
extractCipher :: RemoteConfig -> Maybe StorableCipher
|
||||||
extractCipher c = case (M.lookup "cipher" c,
|
extractCipher c = case (M.lookup "cipher" c,
|
||||||
M.lookup "cipherkeys" c,
|
M.lookup "cipherkeys" c <|> M.lookup "pubkeys" c,
|
||||||
M.lookup "encryption" c) of
|
M.lookup "encryption" c) of
|
||||||
(Just t, Just ks, encryption) | maybe True (== "hybrid") encryption ->
|
(Just t, Just ks, encryption) | maybe True (== "hybrid") encryption ->
|
||||||
Just $ EncryptedCipher (fromB64bs t) Hybrid (readkeys ks)
|
Just $ EncryptedCipher (fromB64bs t) Hybrid (readkeys ks)
|
||||||
(Just t, Just ks, Just "pubkey") ->
|
(Just t, Just ks, Just "pubkey") ->
|
||||||
Just $ EncryptedCipher (fromB64bs t) PubKey (readkeys ks)
|
Just $ EncryptedCipher (fromB64bs t) PubKey (readkeys ks)
|
||||||
|
(Just t, Just ks, Just "sharedpubkey") ->
|
||||||
|
Just $ SharedPubKeyCipher (fromB64bs t) (readkeys ks)
|
||||||
(Just t, Nothing, encryption) | maybe True (== "shared") encryption ->
|
(Just t, Nothing, encryption) | maybe True (== "shared") encryption ->
|
||||||
Just $ SharedCipher (fromB64bs t)
|
Just $ SharedCipher (fromB64bs t)
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
@ -166,14 +170,25 @@ extractCipher c = case (M.lookup "cipher" c,
|
||||||
describeEncryption :: RemoteConfig -> String
|
describeEncryption :: RemoteConfig -> String
|
||||||
describeEncryption c = case extractCipher c of
|
describeEncryption c = case extractCipher c of
|
||||||
Nothing -> "not encrypted"
|
Nothing -> "not encrypted"
|
||||||
(Just (SharedCipher _)) -> "encrypted (encryption key stored in git repository)"
|
Just cip -> "encrypted " ++ unwords (map paren (describeCipher cip))
|
||||||
(Just (EncryptedCipher _ v (KeyIds { keyIds = ks }))) -> unwords $ catMaybes
|
where
|
||||||
[ Just "encrypted (to gpg keys:"
|
paren s = "(" ++ s ++ ")"
|
||||||
, Just (unwords ks ++ ")")
|
|
||||||
|
describeCipher :: StorableCipher -> [String]
|
||||||
|
describeCipher c = case c of
|
||||||
|
(SharedCipher _) -> ["encryption key stored in git repository"]
|
||||||
|
(EncryptedCipher _ v ks) -> catMaybes
|
||||||
|
[ Just $ showkeys ks
|
||||||
, case v of
|
, case v of
|
||||||
PubKey -> Nothing
|
PubKey -> Nothing
|
||||||
Hybrid -> Just "(hybrid mode)"
|
Hybrid -> Just "hybrid mode"
|
||||||
]
|
]
|
||||||
|
(SharedPubKeyCipher _ ks) ->
|
||||||
|
[ showkeys ks
|
||||||
|
, "shared cipher"
|
||||||
|
]
|
||||||
|
where
|
||||||
|
showkeys (KeyIds { keyIds = ks }) = "to gpg keys: " ++ unwords ks
|
||||||
|
|
||||||
{- Not using Utility.Base64 because these "Strings" are really
|
{- Not using Utility.Base64 because these "Strings" are really
|
||||||
- bags of bytes and that would convert to unicode and not round-trip
|
- bags of bytes and that would convert to unicode and not round-trip
|
||||||
|
|
|
@ -10,6 +10,7 @@ module Types.Crypto (
|
||||||
StorableCipher(..),
|
StorableCipher(..),
|
||||||
EncryptedCipherVariant(..),
|
EncryptedCipherVariant(..),
|
||||||
KeyIds(..),
|
KeyIds(..),
|
||||||
|
cipherKeyIds,
|
||||||
Mac(..),
|
Mac(..),
|
||||||
readMac,
|
readMac,
|
||||||
showMac,
|
showMac,
|
||||||
|
@ -23,12 +24,19 @@ import Utility.Gpg (KeyIds(..))
|
||||||
-- XXX ideally, this would be a locked memory region
|
-- XXX ideally, this would be a locked memory region
|
||||||
data Cipher = Cipher String | MacOnlyCipher String
|
data Cipher = Cipher String | MacOnlyCipher String
|
||||||
|
|
||||||
data StorableCipher = EncryptedCipher String EncryptedCipherVariant KeyIds
|
data StorableCipher
|
||||||
|
= EncryptedCipher String EncryptedCipherVariant KeyIds
|
||||||
| SharedCipher String
|
| SharedCipher String
|
||||||
|
| SharedPubKeyCipher String KeyIds
|
||||||
deriving (Ord, Eq)
|
deriving (Ord, Eq)
|
||||||
data EncryptedCipherVariant = Hybrid | PubKey
|
data EncryptedCipherVariant = Hybrid | PubKey
|
||||||
deriving (Ord, Eq)
|
deriving (Ord, Eq)
|
||||||
|
|
||||||
|
cipherKeyIds :: StorableCipher -> Maybe KeyIds
|
||||||
|
cipherKeyIds (EncryptedCipher _ _ ks) = Just ks
|
||||||
|
cipherKeyIds (SharedPubKeyCipher _ ks) = Just ks
|
||||||
|
cipherKeyIds (SharedCipher _) = Nothing
|
||||||
|
|
||||||
defaultMac :: Mac
|
defaultMac :: Mac
|
||||||
defaultMac = HmacSha1
|
defaultMac = HmacSha1
|
||||||
|
|
||||||
|
|
4
debian/changelog
vendored
4
debian/changelog
vendored
|
@ -28,6 +28,10 @@ git-annex (6.20160420) UNRELEASED; urgency=medium
|
||||||
* In the unusual configuration where annex.crippledfilesystem=true but
|
* In the unusual configuration where annex.crippledfilesystem=true but
|
||||||
core.symlinks=true, store object contents in mixed case hash
|
core.symlinks=true, store object contents in mixed case hash
|
||||||
directories so that symlinks will point to them.
|
directories so that symlinks will point to them.
|
||||||
|
* Added new encryption=sharedpubkey mode for special remotes.
|
||||||
|
This is useful for makking a special remote that anyone with a clone
|
||||||
|
of the repo and your public keys can upload files to, but only you can
|
||||||
|
decrypt the files stored in it.
|
||||||
|
|
||||||
-- Joey Hess <id@joeyh.name> Thu, 28 Apr 2016 13:17:04 -0400
|
-- Joey Hess <id@joeyh.name> Thu, 28 Apr 2016 13:17:04 -0400
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,9 @@ to disable encryption. To use encryption, you run
|
||||||
* `git annex initremote newremote type=... encryption=hybrid keyid=KEYID ...`
|
* `git annex initremote newremote type=... encryption=hybrid keyid=KEYID ...`
|
||||||
* `git annex initremote newremote type=... encryption=shared`
|
* `git annex initremote newremote type=... encryption=shared`
|
||||||
* `git annex initremote newremote type=... encryption=pubkey keyid=KEYID ...`
|
* `git annex initremote newremote type=... encryption=pubkey keyid=KEYID ...`
|
||||||
|
* `git annex initremote newremote type=... encryption=sharedpubkey keyid=KEYID ...``
|
||||||
|
|
||||||
## hybrid encryption keys
|
## hybrid encryption keys (encryption=hybrid)
|
||||||
|
|
||||||
The [[hybrid_key_design|design/encryption]] allows additional
|
The [[hybrid_key_design|design/encryption]] allows additional
|
||||||
encryption keys to be added on to a special remote later. Due to this
|
encryption keys to be added on to a special remote later. Due to this
|
||||||
|
@ -53,7 +54,7 @@ probably to replace a revoked key:
|
||||||
See also [[encryption_design|design/encryption]] for other security
|
See also [[encryption_design|design/encryption]] for other security
|
||||||
risks associated with encryption.
|
risks associated with encryption.
|
||||||
|
|
||||||
## shared encryption key
|
## shared encryption key (encryption=shared)
|
||||||
|
|
||||||
Alternatively, you can configure git-annex to use a shared cipher to
|
Alternatively, you can configure git-annex to use a shared cipher to
|
||||||
encrypt data stored in a remote. This shared cipher is stored,
|
encrypt data stored in a remote. This shared cipher is stored,
|
||||||
|
@ -66,7 +67,7 @@ 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
|
that this is **insecure** unless you trust every clone of the git
|
||||||
repository with access to the encrypted data stored in the special remote.
|
repository with access to the encrypted data stored in the special remote.
|
||||||
|
|
||||||
## regular public key encryption
|
## regular public key encryption (encryption=pubkey)
|
||||||
|
|
||||||
This alternative simply encrypts the files in the special remotes to one or
|
This alternative simply encrypts the files in the special remotes to one or
|
||||||
more public keys. It might be considered more secure due to its simplicity
|
more public keys. It might be considered more secure due to its simplicity
|
||||||
|
@ -88,9 +89,25 @@ key has to be kept around to be able to decrypt those files.
|
||||||
that the key has been compromised, it is **insecure** to leave files
|
that the key has been compromised, it is **insecure** to leave files
|
||||||
encrypted using that old key, and the user should re-encrypt everything.)
|
encrypted using that old key, and the user should re-encrypt everything.)
|
||||||
|
|
||||||
(Because filenames are MAC'ed, a cipher still needs to be
|
(A cipher still needs to be generated (and is encrypted to the given key IDs).
|
||||||
generated (and encrypted to the given key IDs). It is only used for MHAC
|
It is only used for HMAC encryption of filenames.)
|
||||||
encryption of filenames.)
|
|
||||||
|
## regular public key encryption with shared filename encryption (encryption=sharedpubkey)
|
||||||
|
|
||||||
|
This is a variation on encryption=pubkey which lets anyone who
|
||||||
|
has access to the gpg public keys store files in the special remote.
|
||||||
|
But, only owners of the corresponding private keys can retrieve the files
|
||||||
|
from the special remote.
|
||||||
|
|
||||||
|
git annex initremote newremote type=... [encryption=hybrid] keyid=KEYID ...
|
||||||
|
|
||||||
|
This might be useful if you want to let others drop off files for you in a
|
||||||
|
special remote, so that only you can access them.
|
||||||
|
|
||||||
|
The filenames used on the special remote are encrypted using HMAC,
|
||||||
|
which prevents the special remote from seeing the filenames. But, anyone
|
||||||
|
who can clone the git repository can access the HMAC cipher; it's stored
|
||||||
|
**unencrypted** in the git repository.
|
||||||
|
|
||||||
## MAC algorithm
|
## MAC algorithm
|
||||||
|
|
||||||
|
|
|
@ -12,3 +12,5 @@ remotes (S3). In that case, I don't care much about hiding file names, but
|
||||||
would appreciate the increased security of not having the secret key on the
|
would appreciate the increased security of not having the secret key on the
|
||||||
backup server. It would only be needed if I wanted to verify or restore
|
backup server. It would only be needed if I wanted to verify or restore
|
||||||
backups.
|
backups.
|
||||||
|
|
||||||
|
> Added "encryption=sharedpubkey" [[done]] --[[Joey]]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue