From 63d7a7437ee3607ef66ee27b6839d52314b1b709 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 14 Feb 2013 00:00:00 +0000 Subject: [PATCH] Use a separate symmetric key per packfile (REPO FORMAT CHANGE) A separate key per pack is simpler and costs us very little; with repack changes later it will be possible to change keys regularly. --- README.rst | 36 +++++++++++++------------- git-remote-gcrypt | 65 +++++++++++++++++++++++------------------------ 2 files changed, 49 insertions(+), 52 deletions(-) diff --git a/README.rst b/README.rst index 90da3dd..b153026 100644 --- a/README.rst +++ b/README.rst @@ -24,7 +24,7 @@ Example use:: git push cryptremote master > gcrypt: Setting up new repository at ssh://example.com:repo > gcrypt: Repository ID is KNBr0wKzct52 - > gcrypt: Repository URL is gcrypt::ssh://example.com:repo/G/KNBr0wKzct52 + > gcrypt: Repository URL is gcrypt::ssh://example.com:repo/G.KNBr0wKzct52 > gcrypt: (configuration for cryptremote updated) > [ more lines .. ] > To gcrypt::[...] @@ -70,37 +70,35 @@ Repository Format Encrypt(K,X) is symmetric encryption Hash(X) is SHA-224 - K: master key, generated once, 128 bytes B: branch list - L: list of packfile hashes + L: list of the hash (Hi) and key (Ki) for each packfile R: Hash(Repository ID) - Store Manifest as EncSign(K || B || L || R) in filename R - Each packfile P is stored as P' = Encrypt(K,P) in filename Hash(P') - L is the list of Hash(P'). + Store Manifest as EncSign(B || L || R) in filename R + Store each packfile P as P' = Encrypt(Ki, P) in filename Hi + where Hi = Hash(P') and Ki is a random string To read the repository - decrypt+verify Manifest using private key -> (K, B, L, R) + decrypt+verify Manifest using private key -> (B, L, R) verify R matches Hash(Requested Repository ID) - for each entry in L: - get the entry from the server -> P' - verify Hash(P') matches the entry in L - decrypt P' using K -> P -> open P with git + for Hi, Ki in L: + download file Hi from the server -> P' + verify Hash(P') matches Hi + decrypt P' using Ki -> P then open P with git Only packs mentioned in L are downloaded. + The manifest looks like this:: - $ gpg -d < 9f42017de5cb482e509ff147d54ceeb0413d6379717f3f0db770f00a - T+pCUr/1FxbBC93ABIiIgG36EgqaxvgdNYjdmRSueGkgGETc4Qs7di+/yIsq2R5GysiqFaR0 \ - bGSWf9omsoAH84hmED/kR/ZQiOGT/vg2Pg7CGI0xzdlW9GQjeFBAo4vsDDDBxrn5L7F9E532 \ - LOnnPLSIZD7BpmyY/oZiXoP5Vlw= - b4a4a39365d19282810c19d0f3f24d04dd2d179f refs/tags/something + $ gpg -d < 5a191cea8c1021a95d813c4007c14f2cc987a40880c2f669430f1916 + b4a4a39365d19282810c19d0f3f24d04dd2d179f refs/tags/version1 1d323ddadf4cf1d80fced447e637ab3766b168b7 refs/heads/master - pack :SHA224:00ef27cc2c5b76365e1a46479ed7429e16572c543cdff0a8bf745c7c - pack :SHA224:b934d8d6c0f48e71b9d7a4d5ea56f024a9bed4f6f2c6f8e688695bee - repo 9f42017de5cb482e509ff147d54ceeb0413d6379717f3f0db770f00a + pack :SHA224:cfdf36515e0d0820554fe5fd9f00a4bee17bcf88ec8a752d851c46ee Rc+j8\ + Nv6GOW3mBhWOx6W6jjz3BTX7B6XIJ6RYI+P4TEyy+X6p2PB/fsBL9la0Tuc + pack :SHA224:a43ccd208d3bd2ea582dbd5407cb8ed6e18b150b1da25c806115eaa5 UXR3/\ + R7awFCUJWYdzXzrlkk7E2Acxq/Y4EfEcd62AwGGe0o0QxL+s5CwWI/NvMhb + repo :SHA224:5a191cea8c1021a95d813c4007c14f2cc987a40880c2f669430f1916 1 Pieces yet to be Implemented diff --git a/git-remote-gcrypt b/git-remote-gcrypt index b13b5b3..4666e60 100755 --- a/git-remote-gcrypt +++ b/git-remote-gcrypt @@ -15,7 +15,10 @@ export GITCEPTION="$GITCEPTION+" # Reuse $Gref except when stacked Gref="refs/gcrypt/gitception$GITCEPTION" Gref_rbranch="refs/heads/master" Repoid= -Packpfx="pack :SHA224:" +Hashpfx=":SHA224:" +UrlTag="G." +Packpfx="pack $Hashpfx" +Packkey_len=48 # bytes of pack key # compat/utility functions xecho() @@ -53,6 +56,7 @@ splitcolon() prefix_=${1%%:*} suffix_=${1#*:} } +repoidstr() { xecho "repo $Hashpfx$Repoid 1"; } ## gitception part # Fetch giturl $1, file $2 @@ -182,18 +186,16 @@ CLEAN_FINAL() ENCRYPT() { - gpg --batch --force-mdc --compress-algo none \ - --passphrase-fd 3 -c 3</dev/null || :)" - pboth_="$( (xecho "$Packlist"; xecho "$phave_") | sort_C | uniq -d)" - pneed_="$( (xecho "$Packlist"; xecho "$pboth_") | sort_C | uniq -u)" + pboth_="$( (xecho "$premote_"; xecho "$phave_") | sort_C | uniq -d)" + pneed_="$( (xecho "$premote_"; xecho "$pboth_") | sort_C | uniq -u)" xecho "$pneed_" | while read packline_ do - isnull "$packline_" && continue || : + isnonnull "$packline_" || continue pack_=${packline_#"$Packpfx"} rcv_id="$(GET "$URL" "$pack_" | \ tee "$TmpPack_Encrypted" | pack_hash)" @@ -392,7 +392,8 @@ do_fetch() then echo_die "Packfile $pack_ does not match digest!" fi - DECRYPT < "$TmpPack_Encrypted" | + key_=$(xecho "$Packlist" | grep "$pack_" | cut -f 3 -d ' ') + DECRYPT "$key_" < "$TmpPack_Encrypted" | git index-pack -v --stdin >/dev/null # add to local pack list xecho "$Packpfx$pack_" >> "$Localdir/have_packs$GITCEPTION" @@ -410,7 +411,7 @@ do_push() # Each git packfile is encrypted and then named for the encrypted # file's hash. The manifest is updated with the pack id. # The manifest is encrypted. - local remote_has= remote_want= prefix_= suffix_= line_= pack_id= + local remote_has= remote_want= prefix_= suffix_= line_= pack_id= key_= ensure_connected check_recipients @@ -447,16 +448,17 @@ EOF TmpPack_Encrypted="$Localdir/tmp_pack_ENCRYPTED_.$$" TmpObjlist="$Localdir/tmp_packrevlist.$$" + key_=$(genkey "$Packkey_len") append "$remote_has" "$remote_want" | git rev-list --objects --stdin -- | tee "$TmpObjlist" | - git pack-objects --stdout | ENCRYPT > "$TmpPack_Encrypted" + git pack-objects --stdout | ENCRYPT "$key_">"$TmpPack_Encrypted" # Only send pack if we have any objects to send if [ -s "$TmpObjlist" ] then pack_id=$(pack_hash < "$TmpPack_Encrypted") - Packlist=$(append "$Packlist" "$Packpfx$pack_id") + Packlist=$(append "$Packlist" "$Packpfx$pack_id $key_") PUT "$URL" "$pack_id" < "$TmpPack_Encrypted" fi @@ -466,15 +468,12 @@ EOF # Update manifest echo_info "Encrypting manifest to \"$Recipients\"" - echo_info "Requesting manifest key signature" + echo_info "Requesting manifest signature" TmpManifest_Enc="$Localdir/manifest.$$" trap 'rm -f "$TmpManifest_Enc"' EXIT - (xecho "$Masterkey" - xecho "$Branchlist" - xecho "$Packlist" - xecho "repo $Repoid") | + (xecho "$Branchlist"; xecho "$Packlist"; repoidstr) | PRIVENCRYPT "$Recipients" > "$TmpManifest_Enc" PUT "$URL" "$Repoid" < "$TmpManifest_Enc"