Compare commits

...

2 Commits

Author SHA1 Message Date
Michele Guerini Rocco c6d85f51dc
secrets: rekey 2023-02-26 19:58:28 +01:00
Michele Guerini Rocco 40b7391aba
secrets/transcrypt: update to 2.2.0 2023-02-26 19:55:57 +01:00
28 changed files with 888 additions and 575 deletions

6
.gitattributes vendored
View File

@ -1,3 +1,3 @@
#pattern filter=crypt diff=crypt
secrets/*/** filter=crypt diff=crypt
secrets/default.nix filter=crypt diff=crypt
#pattern filter=crypt diff=crypt merge=crypt
secrets/*/** filter=crypt diff=crypt merge=crypt
secrets/default.nix filter=crypt diff=crypt merge=crypt

View File

@ -1,41 +1,41 @@
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
t/388/ErrQ==
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
uOXzjnI6xg==

View File

@ -1,224 +1,224 @@
U2FsdGVkX1+A0em6rvePAG/4CTVMdtdsDPMPqqrmWgMVubUww3BptRkglryp0y3H
DaSGNO6KralcjYzlmDxjdVfqmYqd0GERmAJ69oGeCdBY/UM3CsL/ykI/hy7vZdEJ
DD+LOUYBFR/vIktmG1K2QC9CXeMXgL09v1ugbgf8zPvjMrnDHCVe4sz/wx8A2zr3
gxhqg1EyMeRIj6CnH4cgVF34VoOdLnUMltqkvfXmOy+EQLcIcMxbOYT0iQF86nFy
QZHh+cYimOkwm9oXBEo2SMNOMy8eJLMi7N16IulnVGXaRK6mfTAJeG2NrMTTQrK5
o41S+7QHP43fFHO807UVy3opyVSg4JJH2+G343dNc4H3wWSngd8il12VtQHxBFYJ
VoMlB4wKxhUWaVDz689NXLT0EkF+MXb4wRIDNuu6vGt2QV/uvUWfK+kqsj/gdj43
KPMMYM0gPI1+j2J3g3nhBEGn/uKOUqtlQaEK5rN849kJzLWuqQ3JjqyzvtvKy5um
jP+PBHDf/91PWNYdkoCDlNgrUxMgtFP4KJz14mnK/lDkZHG9Ixi4IXav9+aSP0Vk
OEaK0+dkeQQYcYodxW/pE9z1CECe2TjFNhTOJfcUtpplX58HDVoIIG3+t26cUntK
nnlIoKBxWqMKjoFlRWPvMZsoi+Lru1d1IKXNxsbLvUpVF/L5lWiwRXRMBYoOl608
TYi5qcm11vgBN77Gn9/H5kHHVkqrRttWlV3rQo8aNGiMisjkYyTszqX2w4bR5qiA
aSTucR+b8siduY+DG1pAgr8xpsdoazHmuuefx47vZ5iNMuCcI1cKBgpPnkMZmMLd
3omCtcp2u6ENOGnpTn7P1hnVLw+2STXnnzFDpQ4D+B/Usk/KUENOs+2/JpGbEhsV
ivD17FrggjKQepUsyIe+ootwA7wWmXItyOuM2jXKr5dgfp/fR16CPpoh5cFMy1Jq
ev4SVCjv1j6Ve12Tq2V1eat1gdxT22JtwOAKMEg4JAeNlvTDwj81YMiR9eniM200
E6Jf23lpvNHTEDZznSAH2tQ1+8RVEqbPtCUSx/zBqNFGPScaU7GfRg4Pl5XEa1dg
mVv5iV8CcwEYK/GfJJXmc8nURnVP67T592Bk/UYaBiJFOxMr6c24MPaWAfUDCvPA
KZPs5x56TmdYC9rpVCD3a5E5pDLqkNPVYyi4SuqV929Ku05wbKsXrmL3cTPQX9Rx
/FguFUPfcIzKu2SGXhu7dp2rT0miu2yzsgaFKfsg1j5PpdBLkp5xx2cJiXEv/7QN
iiBsXCI2ZVFc8sibPRyqPYTRIfmqlSib0ErJfjd5jyToKVzRmDYUo9SWPKDLMYi/
7Q6Q3Sb0ihvyyVR2xHiyQctjD1GbPX8gDT7rNpEUqJqoSW/Kgii/d/OTNJ5T6x++
WWWbmnCZJ+pWiRYTElTqJ9ZA0mbVKcsHF/F4suZnhk6i6uYxb5M7iwPQPQDUDSLH
BE0bF16n82z7LoxHjm7pKzTTD8kK2IU8PNwQJ6aLJT8uFyoorZdemnYAvuFaKqn2
uVSxtdSAq34tCCrvfiC6ldKyynhlrLelHqE5mIvPZn8N+Z2KlNCqV91OUktW9s8C
NGOkYsVC2ZUb2hmljgS6G+o6IEpAj2YVy0EiP5baXlDqE+qT+hk24z51NuyXmPgL
loM4dmVZkvbWZ9K8tp+3mG9TkRfCCOx8vCAX70wHghGBjhBZDnaG/koj5+A8kNWr
sagCcZcbaoandMBo+n0SzSdw1wB+1K42ETkay5F0u/2scr3KIoqnG5fTaqZkIiOI
Ch2ZusD5vlv4DqLIeJ0AOdyK8CIpznFckdLB02vAsecsFmAznpGLx8Po0AFfwkfY
OPwoYmvVmZ2xfGaL6Oa6CQC8VBAlkWU4ZCtwZ14IKLd27kwznVvFcceBhClne1RJ
5i3qwkBlObXzrCC5wLwpjC/JoYpVG8ti97nbc3BV7MCVPC7xoC88KfADfjdbgxyu
f4cCSP+NOQBTmbg83qHBO8uXGlqoaO4YHiytggY1G0idGk0N3H68gkNMBXPbw+w7
gN3XW4CFaqNZYoRTZvLbHV+dYmFKCzUqiukS/nnr91pgFOHev4ZttSUdmnUseHPU
6ec8AsC81VCrOfevE9BoNZn00YJRuJqsRaT5mm5gnZeG3vkX2Y6Cva4RkwflAu2x
GdEeHR5KzOPrEZKlQXfGTNbYAXYaQJL9JEgwgGalGIp9t9xH4OqXccPSwK9yvMpf
Ih1JKigyrXb/xQM0IQeCPKvMR2623aC+LTyIFBFmAmEGrfDjWKDS/BKLNDfga3ro
5yYDjNGwzuc71Kh3PtXz7HuuVb+3ut17stwbEjz7HXBU7xy3bPwo0mvFyaG6zdqF
efsEqjmDG+ixe6liVtH1G9A6PlnChzS8c2LJfZVsnzGrJAmg/JNqoM/VrnnYBTra
hIUdPvxxPznPBWKxDlTLukxNxDExfKDee9SAru2ARUrsFrVmjuKHA0riP6i92hHI
32oOxQ57EEa9Zjk/gmKpV6mhyQ4EsIRKVbqIfXDXK9ux207EOqTTlNG1lrTvotsm
roESS1rXP1sqk60XSXmDGOp+M1VGBcNfMywW7fGI5DhFXi/X9yQ6GrbnhGA9VoSC
pXJZKFTwMzzbWu+gzptJjLt00hQNOPWHIssiJTWqccmDTCg3r4hQPRtVB+d0k2Vo
hxcCdm+0dfwANykqhtXExqCWdcHwu9dpYkZc5wVnWyn6NM6APg+7owGTk4y6j8vZ
RStbCj6utWvrCqzoUD6TNUMSrudR0Qi9bRFg7P00o+eKEDbSR0vhLcGWeoQ1/EGn
AO3KPw5L3DVKBwpv0WJPsS+a1IHAOlMzlTLO4bCPN3/YzwHT7BW6xP2cMtQRVpp5
IZBZ2Acn7Q8IwkgRf+tKqy59Xe6MlK0F/0v8I6rzbEZ4Q7pUOiXQLt7rwdHFFVNn
Rf1wjn8/ojKNghLVu5rO2My+laUjCqL9Kv+MzjaV/9fatYIb9F29F4jxPhnBYGYE
YXlb+Bdj5/1NR06YNeibGJPEceqyWk9ZEVX6pwlyIgVIU9KEY1kkKXNEk79oP/07
gbp4YF8hcoSxlmbM/ECsVb1HKd85TMmVpD8bIBXkD0RnhB/0LdIstPSDH9xM7bug
kbVlxJo0sXyhr0sXl3j3qzE0da1GuR+GAWntA/NvYrIIjhR2f/Ph/IXuMlLc7VaK
kMmBixWlJHdeTDXXCKTRkDHmWy1y2yIzicYyYgNHVvmWZzvGSmux1cZzgUdUOp6Q
RqzSMV2VdJMn5oBs8/T1uJysXZxiUIi/RuaKQ2UZo2MTViWNS3iWyJQfAUothUAd
BZLVd15D05jgkhd57usDV31lyOXVawAnzyawYYSpXFaCLrrwKi2YGr0ywNkCkhmK
nhJ94wlUiMoZOv1W2b4V3HkGAerim59AwWYXg253Qk0rJmAU9n+c8e3Ygzzn0MrY
o+btGjdJMV5z2TjOzOS/Tf80RwvbEOvYOHeQdIuzziGdaBNDtpMeXyZv5eazkGQp
D+7GvVmMWLoloeoe6NyLFNgTK4RcWqr1aUb4scZK1Tt02iXplNzyxNnZrb+Uv695
L+zPDjFwcxC8yqlyZl/82oyPPjAqhID4j7cfX4k8ml7IW6UMHutiLZJmT4uHE9hw
l4aAZXJcEYMGkc/ezx5T06yVur7v0Q+cQ/R/gxvToISJO7fCyekva4j2h83bkLX/
IjilachoeRV8OkL9kCmd5pb96JLYsoHXj2r0tVk89CnSWfDzIdTCaU3+0kcAGJWM
fY3WLywuDsuCXFUWAWWuOu8zcYcPugtYMpeuLxSOJ/8ag8UPePIPAk+6d28HLySo
DHDk4+g0o9W1pfGLVbjoT2lJjIpff7kTJclifoNJBSVKFK7bFkxhQIzXiFHPlwVv
1kHkt1fi7mbW0nNREzncU/rIi0VYnKruo+Qn87VDcJJ90l4Qrj04Zf+tFAMXj2HA
hfCJxP0YQp8olfERgB3kSP1jNCPkaVDYULzh3ro1CiyPuvF4xYVNtwDP1u6Earti
Zq9iW8v5UfBELoAxG0tymmUpNEvOTGE/qy47s59Vz+kVtONWxCW3AgYRLZ/iuNvZ
yGDGspKmOOT9cDXdN5RsmLVgYdCm3PUVoTXRUVuW0/HVech5b7ImStBmHLdiM6yB
pfrBqKJfr6spmzAnxO04WKfiy5d68WzjvOWHPk1SakPu8COMuHQfidlrccxRehh8
sLyxdmRTmZ+IIE4NaVNcmaLu2YXE4q7K0p6DJeTHpadjHwlmOwJOFcKWpc1qx4lb
FVYFFhttC2QOKJ9FCMJdPAXiHTd9MOJlDvXcN3ra/Cq3kYs+2Cb0JiDOvlU7tjBk
ZZu7pMr+lAaOR3kfvtnw2LZlWZaBgsgZYFgUEZyubFTSZoOEC2qAX0t7VjHu0jf2
s4BTV4qNclDdC1RdYLyfl9wy/vJ9fisfJzamWEIq3TxlijIZEFnV+u/J4o8HbumL
M+Q/mEBNgE70nHBQL+/1QG9ov5sDgjAbcMlz5mRnNRqLHqv1ByxK9vKbd+cH6MxN
ySJ22vHVpDnLsWdv4RvTSqtKw3/KXvg/vfxP7miwWJ5CGxDOv8m7MWMNGPvXGzQp
KANs0APK5F0hD1r6OVFf4r5Xb3NYLsaHe+Lfg67zgiVf07ag9e0KXscyyZx1sAT+
MX8I+cduUqBaVXSWCLkR0NIq+4GXRkwp7xg+xJj04FPyeYl5ErFP0BmcGAh5RB0B
Ms6X0aoXTorgI6jBy9F5UX0/2IT0tASwTvGCi6+Kj5wfqvNBrc2fdMb/x4vYg5Mc
JoNTFerJO9lBmhON2NOvh4cE9f6n5slDYCreUjdWfG184cNqSN+Y4KmY2Brw+uPj
8SMKsBdYKWHKlqrPqeN8s5UY5YzGtboY+5q9rdgaTqf3Idj+QCZWViX7SnzcQlHD
U7laE+EF8X8zREwKOpGz+anvbcer7J+DzDcOO1HTyedJn9YX6rb8ZURmYNjj5cUP
tXLX+p89/QHWt02b9wuE2df1zmwvYQMnN5P9Ct0/kh+aDPOZPedvsAN7AJEHUbyv
2yzAQb+A/Yx0cuTLXGa5jtONTcVq27IfBiwEcoq/MTbW9J/zxyqZPSKZBkL8ZuQq
pmjKG7zzcO4Z2kvhGJn9MqG4AvHJA2Rs7753uApyoIrVxT30XpVzGQ97py8fC1Vd
A2y2QODeu/svLWVwLnJz44tEiF1PbtBUG12jWcrKZJX1HNvOJRmwDVR6EQBe67+5
VCx4IynmVNjTYBT0rf2AmJloQ9lFnkjXX/wpulT4VPl5Re0wtm1dY9W+Du1yMkhL
zuYW4675EKe9Ytddl4GCC4YVQIMJAs1rElQiyeXQ0Xy/sv4QLEa88q3RdtoSaDZf
5koAeIaffbcvYjSGeT29kLHdp4r56OqE0u/OcjKAjdOhqVGPxDAtN12UbwXtvHeM
MVvPKD0PY/oyUWa5mW2zTqm4q8WHjoJinEV0xUVlDZHihQ0Y6Y9oEzZ45veTWyQB
mUpkQCxizY7eipf+JTjWqIYM2n3KGXxNUj6J/7qfUSI4OiQOUf7h8gdRsclFk3m7
+ZYIspXXPKts3ZGI/KuaEQebJpoZwZHY3z/zYwzCm8tiPTY7uCKyrU4EeFIZW37o
xgKkyfsQKhEPPhUvI+M87vMAV1bg56z2250iGG//UI062cDNaenEhUdxzjPtrIOk
9E13Im4KdLNVsKK/Zh6pJR4TJXILO+RAi3BB1R2AjTf6AtCTjPCld2FlIa7dxy4m
TCXKyYhoCMookMXnh+BO2frK9Yp46Wpxv2NkceQnW1AmwTCcmcbqp9xxFYMnhA73
DRCIu+2Hfqn9TN6/QhbA96gqdXYVzGV16WWENTlH1WbAFMETTLFUxfD6TmEi3SH+
/NGp21o5gS9KCi5lGXJjttZN5qtHZhjZndcPPtFAPArXlgQ2U/wA473nyy4ld4t4
k6rAWjqs7CZQKxWz8ZyjoyRb9LnIVK/gfXNhqZlWOHr3Rwyd2fuFFaDwemvxrkUb
P3+5jsGyr6CevoRAQ1/oL3gEXuBUWaRLiTtZ86A4mE4KC83b+0mdIN3Xvz98Yxgo
ROZJuiUF3BNDQ5yrMIGf2d62y8RJmOtnDsGOxFnYNl63GYWMgdHjfrZFB6mxia4z
cO0kWVjr34nMwIARCcxMDDmB4OnHx3fuhEy1Pyfbh1uZ1O6uShn58h3hzolcoerZ
8pAc7sEPt/BLfYtwbdJ8d4lhNrTQO0lK2b1lBG9VeVgXiLIsjAsqHnDESytIG9e8
1ndpr9JzYe8EJXv0BiOn1h9fyghhVF/036mbgfpRuRf8q9tA5YrGVi+d2oFsKWjL
KpVlytfhpW0fdwOzGEHNofN+Xv9yBOWvTCuuBix7QdGeWfRrGWCrtqjPvpm5aA14
YkLyMKVAB+JzKtQl+pyXfn1attAmVKuF77rW8CGLNrQhcDF4RIgLML1kXjUBF2aS
HQXpsZ/EYluRCFA9QDPDSlapZuyMdkAeRle3zN7RZ9bwbIXW+acjYoKpz3NpiKTt
gXtatgC32bcNhVS1Hqtvf3LurBGqllcAggot88KLNGyyVuz2Puy2DmE/rtWSSpty
Hc8UaT/eHhRtKQb4V2O9hnCCItHVokxNXQO8cZL/Acn83z3IWaTrAPoSSoO6K1mn
gzRymgyH+o8r/xiEHsDZT38ZNRXS9U+PtEZZ1tDx0NjXuHuMjTJWvngwPz8nY/D0
gMNefplaVx5gWX2b+nvtOHOh3D3KP5L3dkkvvFBUs1ZgLRhrghqPGWtrKvmL1saB
cNOQ8DU562syXxAxrVdw/eP2m1vtfTJ//xmN7DEL5sBPYVaDlJ7c4OqnTdWID8yq
tIR/I/kbP3f1Oty8Vu+gSfFEG0KURSPDLoAi8KaCK6M8y5v/KSaxTI7BPrRemGMo
SmxK01NXD8zX9UCG3BcwQ6DWD65kKCuERn8XNg7RjtQXEGrPu5aLqn2hiVz/4vvg
jxjCKRAyHdJz7A/JMNtDZrlk0QsEQoz97DoTgbMAEw7MXC/+w52ztASpcXCM0J+x
nzsGNqnITYxLwJPSuqF1MIuqxWhyqzCPsvtPNMrL3DrlRoe7O3IntGxJ0I9xr3W+
3Chy8+5+MDI0weG/t/tGVMMnGt07AaVI1LdFSO77g06JQZXPZkDsZOoGd9hG0kUz
GHmVa+0YJ5T+cwtmaT/Zzhd6z63HobPpp/HJKAbZowh8i3fm/GfOgOqRORk08UQl
Z9BJFWVlEho5rf1bU/NR6yB+LY4sUWpC2X9gAMyICgd2Sw6fxrOPXEkXavu7ippM
UgzELkRmmMuUrMvqUcv1MwhygElwPySt+ePAN/tROysyb3exl4loGI0gg72CRKii
CkkS0V0PEvsxyenfostbHZz7LOYu0RTRjCCVF+s1Ev7CaTAC/lkSSOUZetuKgs+d
Q0c1siYLGZJDT0qV4esu6FXbWNZw6AJQ/+UL9csxRp4NCyWA/VlMCOY/F1qOfnYF
2CNNdzDX8RGLaKd2VGUiDOCnUew2lhIAv8saLhSFXf0XB9yWORfePKolO4lueGsg
wfhBQL1LbH/YDk6DXB6EI9r8UDjiynfNEZJ5+fu4NKGA96cGUJGgoPV/Oi33E7ed
6/y71W555slkUdzquGivDwcemzCLai1HwTtn77vSXPTfqt4+A8I4evlsj8jJXYLr
OKjf0BQK0eeJSSFMyN1v/CjvABdi28dWqRjjCr851VSovwpM8+TnuL0dWtlMOzVD
ZXmTXw4C9UTeOme/0YBgRelJRVtS1Hz4gLZktDCZ121XJ5OqvZz95k56XEP6gPOu
woGuMZ3VFyN3A3VdE+yhyls4vQ0A2BBa/hprD2qf4yDjdAv+ruCkV4nvaH/GmHXl
lO9CXBQi4Ig7HzHQxKrIKUzVRtuHpB+sKtuhE752XXXlIXoJvjTzle1BGuiTPhTt
WW0HZOE2BJ54QiaS6I+s2Rveg34wpFkHDXS90Hk0TqJ3JqSK3xz+WNaYluXatO0z
4TVXUlugYvWzLe0L9T76wyUm0FWFuutX800/kwDnOvhwc9LjocoCYz+dvsi5A8/P
hjLwRWbF8fMpjlSRNwL8lA5XcaXu8UhC6d57w2IpYWz6KusO1SC+h/z0N3xKdt/j
SFshEePUBVtTfYNmkq7veZQK3gQqjDEFeP8iRvG3fzVbJiEWmlvx97G/GM1R5l1M
Gh1G+CoaSTu0USuewezvGp4+x9iSinXjGqduI0ci5Ab6e8xlYMQGnKHaCy/YvpLP
pbhNj6P9yjyIBNv2YqSObFwJF0ewxzQj2STIk9nUDR6EvgzUgUWPzsaOgZinfLjS
u/+RCdnBDRJKkmUgxuRLskD9+CmLSA+lXtXg/H3bnjkczPL2nND3qNUtEsGiBHBS
wfYQzZLu6EMNdoGRAFEq1Ek59MesdHVIGK5zqbckC0+OHrhwx2BJNeimlHZ5rxie
LMWtBCqrh9F9ZXl7A3dM5uG980SHYb7xKobfjI2TfMHAo/cyGsJvJkXjHt/bmGFv
v19Ap/CDpcFcI8oc7LLwKKIUAxB3CZGPrsUILlsvv5oOixuj+7gzCB6LGNl7RCaA
YumPXfVxQ79/yHdj1/VvO6wGB5vkt/MM9DcDKgkXawtPmTsnkkBepy83s/3pUqnz
2onv6Ks3x7lTigHa86O4tHMAWwd0DMazm/wUMNoM6sW3s/82ESMLYAXzMTeNAExo
kMca+aIg2S+vMwK+L4iiKWgDEexBffZUV6SH2Kg+v1oyVOkdQVwZ7PoMNxkHHsro
NhLKRftg1WhR9saGUfv00S2ANzXIQoVcOlY2zfUW8GSjgDBIwc0Zejvm5eLqsZK+
Mzvvo1HLNV/EOvdjCpYV9f/pJMkESi1K868ttJa0s+r2UPjMi2YLX1kt1pe02aWq
M6wsa+7QmrprpI6/Uedr6vfhVwprtM7sKtSH7OYKES0uuVidScuxocLWdOXvvi4M
e8taYiUtEPl7vFuWUaGth62CcYpkrlZW/cIOqoC9VYHtXeGyspFKqFfCQSHXsdzt
49FkvzM8y/NJklocpnNhUKsglypONgLqk7s4qhqV2RLG2gLjyiQHSzoDhoQldgtW
7GepIvIidGVl6JBY2vH38HPqB67P3nyNdw3AGzmAn5Wb9yaq2KXVgURqLC8EKB6O
hR0DuBkJhzvBxbSdGOKGGHEYLZM45U1RsMRm3aEzUVnL9qwhw/HzbdCkwtHJ2tIG
0C8u4uCgnu8BdyXURk+KhwGTrE31lBgYnr7cr+5k+bI0nGhhUbSemMSjdvAMW+Xj
laQMcLKtjTHpXx47BeS8TtrERX3/Zd1ddTSMssYeTtHDdFyBNvJSl0LQuF65Dd2l
0MI9t7PeX6lwN6Z+n6xWhEJRdeohjTK7lynZrv/aQLo+WvynANYU78OSj1ozejSd
VPoOws2GPyNoSXhBmrFFVO59io2az+9xD1SFrTCQcH1XT/sfswDosGJrgsD/Iblg
EB0ulEfrpj3r9E5AsRYh4Njic76elWxm4KLfjqLjuNbXGiNP+K+HC1rjf3tQBOGb
WckmTPHsgw/ZO+sSgbWy61Hz6/kQMvZKJnqJQlpx2GLZuittd1wq+6wQr9wI016s
SjLI7NKsPmJCFeY2lJASBaDuPg45QOEJpnkGIPAQdjroQkO33Kuho0ZOTZsM0Q9g
Ofi+fiO9npNG4hSHs8CYf3Kb0Ilhimmhk+kH5GJBiS9/2JTg4SGUVqS1sh/81ZEp
cZalr2nc3jIM5pyayFTO3gcuyksXqmukhbSKOTupL8sBqtblbUQuCowTYL21ZF1O
obbGJxwMG854qYPvcExDW3I9slytjL2dcFgFcEO/Tf+fOQL8LZ7FaZZ0zfy0SNAn
7m51Z9+u4nG+mcT1db+2mdKJqUJ2L72WUVpSJ6ynzvqzLi3+tO2bUlPNLJZAHgbL
wRM9+vOuroNVCxxKQFk7q13CjnzCzpVIkIBFTlGd1iZDujYMQ6FtF4lwT0R0fhW7
QNKdQ5eMfLti+g9NnnjOk7bxFq+DOODQTHiymKDieoUnzD/X7Bq1GGTeWhO+Oc+W
/jwFx+lZQH0s1DaZB+jqeUOFv1wBc71q3OLNA4EbJjEEGSs55+IWNQo4+wyDRuSg
AKUnh5JmQkzC64uE/JkNsWCad1Tna4YEnS2YnVUvaCrbKrS9KaUcivQ6I1J1mwzo
4/ka+r37dO9jT2JqUos3uv+FiPu99aTuBLGsgWj5sVkQS/rlPDDhmH6WYOFz/EOK
qGzr+lhSn5FoLA/XY5zNtbW/lHDCuowyJCJWntOGMUP+xXhSGKsTs8RSEU+5Dr2R
Oa/VPxZSU15++nrWAIWWXlg82pL0/WXGjm/OxEeplYhDdfQLLJY66zqsxkQBFAit
7XKIR7b4Ob/CCVexVufZtWix9O2JNCjh2g/77JnllmtmctWH3hJ1RLdAHdpwEaqk
UgxUMY1syCCbM3BegcvvYhQmLHwt8LmVjvjI2Xej94+puY/SdCcqyG3svWD6Eoct
CRaFhgXpYEtl6j1OplEkFylc8BbBetPDEwFk6x3QDbYRMT92Gq+6WI1RiXo/imLW
MgKtRTQTnMmlIpI9a2EHUi6AdDTLUSFHFgyQAlU4vkI4O/cXlhkSkVb1LyYBqKl+
5AgXI6gXbIZl5UIabwppBOutm/u+EK+D1AQL+Z/DHLWSc/hcx0Y4RlmGKaVdnZrT
tpb3prqwUQVDq5r9DPGQrhw1Kf7y2RAOv//8K3VyQQUQad72beB2dgnb2qFcSB4e
1Ls0vlVjUnIs6w2f4ixajFjk6Jw1Sd9aNmta03XxUn2eONCRelPL7Vn65Nz5W2Oq
TDRnKImOiE9qTz8bE1TRDj8Cr9hOek8m3n2Zmqo4xvIzMyOqlKhdYaBXFFmf2uSc
CLyF3pwIlg7ViGpnE0Jp7pKiKGUft9owNTFba99RV+oA0LcMr8ZV2zLFOOrwAlUK
8xtr/wCoDQqg9DsdOKRV9JlI2AIzCDVddMkgImmdzYrbQCfxJrJAjubnpWfSYgq8
g7sEglTeoNON7O4oojTANMGSsia/26p5NvHosFNlE3DbPRS0aothnX+H4ZN1MqTC
Sj24sRjGTwGJR0ARRrC4Q6uWWI6S1F5QVt+U4wZjNaJSJ7UyL019oBQIiTAopddy
m+h/H+iGx5U4JyA/Crmzn1Ms2bGIaWmy3N1bnFMowFSa7BeRtLZ849A1jVs0xJgY
7Td0o38Pyzbqocrgx16/fO2PYqkHxvcPNhDpw6njwGW1eXOs7j3AaZF81uEfenMG
oJLWoTySOsGw04DpyQMlPTE7wj8E1aCcPjAoyPE/49F5GMBum7qpPjvuen8vsIS0
ZvELMupA73be4yovlUqzhk4TzUCswGDnDrO5WSEy8yyy8+UYf2JZFE2Cxvbda58e
TpNAU6dN3YJKgphX9gDotcFsc5zYrQIMXJBF9CZpTnCQmQi2SNHtQhsniPr6OHQG
LfEgDKUrr9oKfbHTqtdzjOCbQQ2mLzY1fpKWlHiQ2Tb7hZzm+LCqC+4eZ6rL8gWy
8VmcjyvmkxD45w9GcFdKJw2w7hj8sBk9/orAk0jAs/hrUv/Tak+XbSDNIRKYbgnm
/9RWMsYSmbzIz+FjxDlC6qjAOShKgsJvt6PD+NllffYWbNHE2lj57stmUnAtw0xI
1Oe250yVwcHt6cMYHeyJAP+oacJdme004Q54OCniwIBjqQ3lzQjOqA8X5dH+zYpy
cR8rYFkOuTv4QAX9Kb9JIksWM4P2jUezfr3Wh94VDXcey1L31Lv8bp72paYuhhRe
QBRWRB4eT3vzKmPR49Z3/teXDAySlNAPaOYfcLNU/e48amBrDMID4j9FEtECBtvz
nj4faYdi+70j/YWGuW10egRNMyxHOZWiig6+PvclKsrZPfeoBVTOySFjgzb73r3I
lHBeZrpKQq0Yt6y2sVfyyG5GltQchB1BWmmFM94/3duf4PhQ9kxEC/R4Og05beQC
VxCZizZ1mENxsQ/C3nnEfLzGsigAPBqHg3oMmRTOWT1K/lTo1jULcHlPJv0+qu3m
S4yZkB9bw7jh/R2P7j1uF760bZNgFb0Q2u8qm2QY7ZlogdSPdYjKCrobCnTKd4gb
9sHTjqeLTRzCw82L06ByAuGUTXWGwVROFxnVXEbTr3SO5H2f2w+UyQbUbN9U+5UK
2TdkSVd8GsZ4dwSu9DE56GoqJXHyKtEJjmnzD61Sg+k8cvzhTUjxBpxTSFYQdD3R
KIZflN+4Hm/1HqjoRRx11mZzneHehHA8sJs8Nrz+h/xHB/PhxugeyRFRmt5IRoqI
zQjborJ1nEXH09rSxWhiOjiNoSUpritNDR0Abt7Ixg/rXFAG78b7aU3L7t2rG29K
hjwWWU/azZfefJkek9NLTYgOWIppmuvt02gFlrhFPgzzdwPRo6cMyinT2lwt2PR4
z6OT4pMVhpmnhFgSDoXvjlYHvMiS0YzLB/1rw6a+u3QzdPXy5TT0miBwuWiSYIbk
4lst/O+qNRc3HxZQ2V1557JpPZXoy/ye7Rc/McXRROv+Mqat1pUe1sCAtKZlK98F
QPcWdT5+bAAEJK0ZvgAg56oE2xwGMN2JJm0z2++JMStZ/8Gg4xdliC2vsjY/UYNM
sKq6NbeehlUgeVJsuTQg0Z9u1egbhFmmVurnHL3qeSSxsn8wNR08Q83XyLA9J117
Lfu/MLCl0KIPEIAnNZQRJv2/fYi15JGq/OIs33iauxD5dLIhLe4juxKpz5708d/I
/v7xkZifGGpzNT2uRIHA0eY9TLehpfZ0AUGsBi+yOaYwOKZfsj89q22UGddIc0Lz
BXy0h5SzfRS5ZUT7k40o2ATFOHU3Oa7Rd6pAMJR+uszsLKVr6ye1w7sKG38v+t4E
w159UuuVOqEVZU11xuRJU0N/AdEXr1utHc330fR+kqtemuCTw5jwjzBwQwMGsA3P
lrNioMdzSnkf4efQtSp2+NhxZEJQbRNkh/r+NgLCcKyMGGmWbcinNk3dNKX0+Xva
AqEkvcpnQNCjknAhGmaj3fWV77oqERpOg3gyRsr6FH1dfqwV+lFBHhnS50R2Sob5
8DCF3+zWhg5vmhpiuBSUTkzlpSO2uRr9+ZtxC0aj2hGwqhnQLY7vdLkDMNZeqJER
rwQXnpiIB2Q7z7y2p47tzfkiQEiFkOgMbXkJql5KOI0QiutKFYF+knUAVQwllXEp
3jeMbQjHshYy/oH5dcqay7xFaKHM6gtKb4pZgWa9Pa1MC28viv3SLAeQSCNR6dQw
F7kheTtPuQs0BHN85Lh2I29K1xfMRfHek5SAgdt8/g3oE4CcyXbNRnIGp9pBokOH
41ZU/yrnbD7PSTT1XfZQQI3vpomHTEFQRDUJ51ODHypThbsZxmM5SZR8UGYL1/Xx
J09C8DRf5mk+oIdcthbL/wPQaN3QW/qMjfwsLJ0rEG7NRZUB4D9l+j2VtDA+dISu
MICBFjgiVa7uG2/Fy+HTfEes89Ribjvqzyqa/57Czqzjn2J49Jd6DmiCXVI2zVSO
sM7I/prVqoUV9MQToSnht18fprFGe2ATbFm4M7PYs6adQ0ZxAmpxVetOkFM94kJg
/8fCOLl3MDXwmkZ+8bWPn1aFxcYfc5LoqMucgyNrvmsXSblo+dK27Lthu9VhxRMk
qqYwDMo1C3SJLJ8NZT+rsZGOjgQqhxX1ubO+snV2x67XyluDQ4hJEq27D2DOxKF+
TpFHcJdNEfE2NleXxVGz+QVSU20qOGctU2EuusCsgfxTgJnun1SjfXbJ+V2aHMgO
bzzFdkURV3xHOuqADSVU4ptDL64pnc6Sxz3EsNoSutUc7LaTsnhockWls1DDLPa9
YWzyz4J5F467yr0jQ1uG52jiwZ2qntMroOQFQlgbJFDUOcfSOqHH5dKcTRHUybaj
RslFYjy0/umoAag7eKl765SAMQvOn/LAi0qonQ4dv52Aw+1rz6lu1ujTpSUV2QVc
UPocb/0c55xxsWE0uOnqZe/QtZ0IiDtVa2TuH36KvD74CE8xDYRlecp48g+vfjah
G5kV7Jr+3v7l/zzgYTBPO7ChFZowVBjafY/p48vLREkcKirZiFtjp4C+empM15jd
E0qze3bdjatx1ZNvIQHnWNGxlpNM7LYqDJsxafIAuO6oe+pJ4LRjFdEM/2oL0Zn9
N7FR49qKUp70uiDo6J0ZuU7Th835XEeeemapfBhTt98Yg3BZMyJp7WwLj6bD0YFn
bVSh8SJqq74qfaesIU1+PMumTFv4Thr64Dufl59wT4gToPXcFwbxsJumhx9UsXuD
QqOqjhx226JxRePH+uyE0RjodtNDpwY8CH12HodT7LmrpiK3CMkWF4kyYkg=
U2FsdGVkX1+hcE9rD+NH09ZQisXOFot7OQRWa8U3QCGMOZ62NNqZgIwLj21iC+Jq
NtvIo/FNtvjvmsvCwEfjQCxkfl3uAk+jHpML+z9O8WXkFy15wsIFuJj61SGoOE6a
X/F/liFdEIQJVGEAj+CaYlRGUj7W5qkqm5iegK7vMS5zEM022OBKGQ/A1MzAZVsC
fPQk5tbjjqlePzIdYM1T2y07agykHJPe0pHaBIDnjWwaZerkqL+9IhOryxGjPE2z
gl93cQThQ3h4J6sEhox0dXENqd61lWUFfvEMLafLGRVc1W//XLULgQTuHHVotJZE
iWKJwCLK98PHrVEaz3p7a7hjLQZ6XZnBLdF2ETTrJRhPbnJ5/pgyN8P406GMkfHC
+hHiglA7mm33EmyYC1DcyKjFhXQUJ6l/oD7h20pgOSk51k1BQoivG3zjW/JBFqby
DKdQC1u8UA6r6HLlQNEYrVdxyJmNzGJXSFafspZZqyzdf60OxQe/0G6cpnH+IqBV
Hz4HBDf1jDbrwLNloBnJ54jYOVqwCschUbFUXhW5L6+R/pfD8Gx/Pfi9gELkAUj6
6XviQvi5N1bi3T2z0cb2LoX46PUzPIKA2biuJaCV8IDL7SNdA9mu2AvWns6TXyn6
w619eO4lVTCiX4p451Ot7oNIc2SxhVviB5s2FhBBHTWyDgd849A1fO+Gzi3nqr/m
F9OkKfd0Z2yUOTYWoxInzpT8W652FJl1OX7eAHo5ZBek1k9SmUyi8g4AME/COQor
AqTHpNaiUl7I7MIvxr96SgQW9QUBFqP5HLrExBwSy0os6xTg6s66vjBEbq4eTwLq
bV5Wq+Koi9d6MRRrFSBv7YgVY32m56d3/qiD5rTu6x5viB4UToPlcuKBfxW/6gce
fQsvxfCAosx+tCvr8bYbVa5uf7/CB6qJeVZRUSrg9ipQUAbCp0enzbYg5KbpW/mw
kJ/vj/turhHRNUcDAu8skLr2JU93uIiv6Ho7neQ2u5BOGxmaCDWzHrQOTqw2kMK1
6m7fQfNMxWxIJnt/yuqEEtuMrjhSSan71B2P3/FwjCZcfMYxrUcFJSIvHUaP9HfB
hYM2aJpBb+KnLQMYWSBt4wh5adOn+JMngqRw1qw4JpZVrqQKwdNTngFNEzDhhVzL
r1W0P65cArZKeIbq8mJ3TwzqWZ2Agy9UPnRiIfYLiDpJCVlFrWV3iPqdVJA1k+sH
IY3VSTYPaGu9UcTsy3VaGcGrmRjuDvoHD7JB9LcuRDj9o7bs1zMazDzOJ3EzrfwW
FL7fLzJjGDKswYCzeygK6Qe/QWZxgJRe+am7z6XqhoF/MIVVPxxNnSVGah4k1LUe
LxrSqNNNI8z9okyczDVbKmpdmLV4vP6I/T3ElF5E6UrhIyMd9UjWK6kdnrWZuaqT
//QFxG5qUji6PInm5WKz3AvlXIC6iNq0IHX71c+0E4256A0YxHHjqvKZJITSmy3g
LNZZW4QQH7jXVfWARfy2EdO6Mfg54HBI+st22NQra7NzH795tpqUAqAHU/SZKIdl
iXzmMJvIuPLTLq8I8LfkPK2pfLJoDsP6XyOmuXf+gNibCVylMnTqDFbr10O0T5+w
xoPnRc5dcsGWWHw4b24TD2CuZ4RJ8+5w0kL8KSZZAF70ozaqanmkSERsgpf7+1gT
ftY60YJL7oXxfEH7AvA4YQcLGZtw+3XhkZStwS53QK9FcOuUw9QHg/UHzoT64Oa7
7odCq48rDiuqOmS6OtMq3uhRDf5TIOZDroUK8dykRe9+fF6NEiX8R8OhtOFyM8yj
zpo6SJoNe17rTnKzRyBm7V0krysRn6boK84GLqZabEBPkUL6U06YtYuf4iQ9rC9Q
d8fHyM47zwr2rPiXz/eGat77FpIy3Tb7GUx518UFICFcQwqEZr5tun/Od5IJIRYL
xzqzMZW1nevhpQLdG1gXod9HgBokMqIqYDgmYanpp1/VisX7PHhSTjiEMWldLL+J
7fs4mQIMFzkbc5H7SADG92FQjbFUIn40Mio7LlrivoLGOe3CbudZ96rSnvRIQkjF
wu9b4HtSEHuKJmKK+kmQ4WLZ8NxalJ952bhpd+1PdhtzD+5YwCwQdNB+HNaI/iAe
YZteRD3elHbKMxqG51Zp4InAJAJdNQ+OoHcS2MTuxa/P9NXBLnUD861e7YLj/6Kr
9e3O6CbehQEzG1we6YOwACUauIj/a6WnKts/vrgIWWrxkD3cMnmOurCsM7RGo5Gr
x2yqjZnhAQ6EYzTf9u7RIwgySJC6L2eo+8tdt0aIAGWRrEfKouPg4DvJ0lgwvDp2
UIUmcSbFJ6siE3YL6yz6e60IXzKnM44i+Gf/DZUg9hZM29dfPi8eveLSGxArdYIX
xCdwTLi5bccHlGLuAqtZ3TbaZnmskB2++82ce3mq6FUJEWQuuAMajxei7LVuJ1zz
5CDYOwB09SaeqGjZXM6nZVPcI9Uz9BH7Dy3Rl7Nn9dVh4JpVJloTO+aMiH++OQ5D
jGh8TFhwvV0GhTY4sLWxx6DGGQQkYEFWpmYkrneiXaYusc0GZOFJsECPWSlTORiH
2w2cq0gX8tNdsnu+FtF6PvpMyzwmPcu33IUwuR6Ui9epB4RzFcT2s8CWtPZ1nDHW
8HFWfs156yBB7yIubAJi/4igTKjH9BYciuBLsPrY2HIxCr7Y0H3I0fbzXgB2LFBD
VgM9wAn5jVG4HATVnx4AVAcQCMS9Cna9u7Ixk/4M2HL81kC6ZmMKqN2ZS6IYaNxA
aKIMN7LTm4ZCBBctrWBfYLzbOKVZakomKXQO1EzMTY8YknhbLSE7DQQ1AsCPYZcL
XfWhrpbCl7fOL0Z9JnWtc6AHopALYOdDoM67CLQgAFZ9CsaTr7gMo4RH1ggY7kJp
825mvmJeUa5Acq7m0QlElQ6s0VJZy1evwgV7Kvor/Xu6KYlPDe9usBN7SsB8DFfh
zFKZ9XDDNTGAvVEnR7ijMleR58cirLpF91XlpfZtqOURZLbUhc+Lse5IgB1QII0M
WHUY9ejpob9pbiUay3IR+GGRygamiV+7LakhWF1shA+HczeFqdd4kbrIplLxFa/B
hmfaMlcIx0EUEkvcWtYIDYg5LYT+fiLMoRqsOp7pXfykBNp4AakgzFNSxI1Pt9QQ
uE/VdFB7crvPQGrLOATwosbTVA4ZDYb+sY4+/RDdvJugPXhv/U/v5UMcYx/Hs3uO
NAsNhWxLiZBL8r5ADaDi4a0YCWLrUD576/+dIy7Wk0PV8zfs02IKB7+dAMQ4UpyK
RrmIbcWqLtYQmX03gqPp/QcxlANwfVszr7HcTI+6cR0hHE93L/3b4S2kLeTh1BRJ
ROnC8Qq5B41WPH3gL8dd/Nz/BZQyQ5L+phb9cydVG2vaQWus4Ork1jaLIsUHYAnh
2mT/TtpZNARNu6RsVCwqn8Y0+lVJ1wyj0rektavAW+TWsZdvjx39p7dddiDjKXf0
dZL7GjZuQO0z/6Du9Qew+Uj/mNT7iK3HNPwfSO1wQhlDt5OyRlIP35ATodG6S16I
pXSijQz7aEER4puVdRVzlfRmGNmxvD6kRN+N+tRBfB3ZkC+EhYkSjJ9cfcYhTpOZ
1cB+CJfx+79ggivqJa0awCTUWGUJbkpQIZjLSSke4ApqT1IQoDDWKwblFrXxIFcm
e7PkXTsVefncPIPhJba4HCNlznFkDDlt/8G3nUz5cMPpgjBzdU+hfbrBu0folOmn
nIiWIvUOGfRYi+e3mkTuhVU4xrFhpTf9GdsFeCJZVAtFEU7XHjjn7qU084Hukcxl
QpSQtCqrYw128XS+IEHaEw9fkdGNOY4vSnnN+Fs5Tc1qNNIZm6KiS+RoZZ4BfSNC
TgDvuCjZjsEZNphRaXwpAbpJxqjgjw6g9QgXhHuocVo8CIjoG18Tfr4EmaNVKu3I
EWQqmoGWkYvbCDo3lqbavdkYPTXSq7MnEd2skwYOV0KsLqSBEIAK00VI344Sgnn8
MYB6Z770SfzEiqAzETURjxt5lcypZVjS6Gx10iIRuibnU7+yl9rdG1xnFmWEhMAh
cEfpd35ql9S5UaqKHVOPQEfRy8VtWCDtlb2yBWFioIdZS0XpapJNcxVOkG62wjKu
owQ2uoz33r1JbIZSQ9N3jndTNQeWirMtGe/uIPjChUctOpXGd0olSyfBye1b8+G9
djNFjz/kmS7+Hbl8R6WW5DEwZexVEdugpL6BrmBZ+iYaiSCt3KZKONWHHvS8530i
JZzUgT1lo5gNGaNnj//Xq+2LJAR26gIWkY4DRniD6UvkSdEQyOKf/tHHwXpjlFLk
QsmbK0fVCTW0eyaQpn/jvS/J842/Z8CV9KQY2M9Qz6KxLqe/zzN0/xzGUwlSOttV
xWc0xxRkYx7HeqyMk6ackNfrg37KKTIcDNO/Uh2zYY3yG8LohTq8fyAJZ7sZljnr
kuDjIzq5lqEUSDSDn4Irn0Pcs/mQP4MSl6dF8oVjxD23xqrsJXKw7Uj1w6NDRWhm
OSXe5avp85+6mBvEsJ2TCUa9ffIyMwESJHjfW+280fF5rmwkAlcFYoraoPP8OmDE
kRzOwYjmmpm4V2mQvR+SvSwY6sFfey31wSjaQ0lbS8N48D54yO+pbtF+wcv55TyR
W0ddT9V0Hae63zDg+0LgXqwJXmisGWscil3O6Agb8caoKwLNKL+/fxrFTcwbj9Ti
A6EGk+FMz8AujztGxqYNT/4zkG1hurA6m9UkYrysI/ZsgJ0CRn6dCNipFjtJMy+l
5adu33MJyjMEp0nmco1AL2Nk/oa7RIWCHKi/txlxu9tDbHSmGUGSQOVcupW0GXnx
OaqrEzl4IF1YDGrJ4VnxFeiK+kZSNKpYqN/eddBzV0oSfCH4de9zquCDjaCg6hPx
ljPIKis/439IgPb9YeM/hLqsVdva1WKfGLPBSJ5gC2qxuIicot8xNNKVGY5jff/W
96m5584xdUqyYZWTRKEJ3Vj6+6ze8Dwo8YIlnOMyUW2xpAU0r+5Kk27kBcCE80zk
j3TYVhO15uLK+/ByhfHNZl+wM1wg+ApbJqNKNCSFlqTvLct4FgYF8/oPUcpaYmbl
ff5PtNwlQJQ84OD8EG73AeLiOWYyBCLBV4R7g3dcJeUx/qzdZWWjJNklFFuuhwbI
VX18dw7cpyCWY2RfagPQHjCzWdh5fqotxNX5zTGm4mTrEXWjgJivvuerxHTh9lGu
ghhnuYEOiMfMui1Frn01MFLeE5XjhBPZpuSFlWxcrV0FrAAHI6WZUaI1OFma3Fft
v0DSNMq1Jors+U2aXbGNfw0c1kuXtXvvI3RS3tnfvZEXdetTTD8PmOpeArsGFxt3
/+x8wtOqz2NUGoEM57/y4JMQIDzVjrmFvVPCPJVa4k3+LRKljCK9wtOJpFDcroBU
bfHVKBYQIYgcABZE5f7DaMuABdpQNm2T78W7nBnY/3TjwdMKmVxySy8oWiPENY2j
TZhBp70nuONUzDewOw2xFU7lscAZwMYZPt5xBbxIAeX719f3A0Nhu5/prl10CH/p
0PxDdLp0yxoxEHHTHTZu/pE/TlGYY+Uu5KHkb/xru5YU4VScsqT/g6p07U5k7NNo
iJQ0noGU8DGV2z+XtA4WKah/XKH/QP2y/++avoGyLOKJrLX8p5npLjOieZ9utiEo
mVR0ZtBa0KBu05HUlmQDGSIymSJhpIFlViP6GRvrqKccsUgaHecvpcPwPDNylX6+
RsCDLYhijKfO4ujOjHLzJX0z/TxwuZktVPcTVtzJdz9PqGWXV8KCLBYZmmIPjCnd
hyI19VakNVpVcjc06x5ZK7pqTV9sVnyu58wg4YMLa8ZidkPZ7ddQxcDvkWJfe1Ur
aFt41sxNXzKza61STKxx/m0V7vE3vi9xtrSQVvJ6XMGaq55KFwNh01Pnb9obs39W
yA4jZsWeLVVeJPFWL37Ppl6wdsfOi5lGODnbiqqElj1IQ2wQwDaXzh32lB5oiNg5
IeEBM8idDilMi/mXDpVSaAbBSyk090NJqTyfso8VKLcXddasZrqye9dMtzt4tdpz
sHkIUsBtXdKQ52qoOsCeKxEqcbYc265Kz+IzFJkUemACzAXxzw6veW1hkiaFLZV0
BM3vwozV1NkDDMp8gRawHON6Df7mL00kk+mkK2VS48uPfnEb0UjkHVUfqvKbGCJ/
ZQ87YcxS0pVC/n/MyvpT+7l8arc4kWPJVUXhXou/fp6L0gen7znz/UXl4n5FZwh1
qo0gMBrRo2cCoyDF1EgelhJL4fn3QRBGVMtxzictTM5FeeyunTICKRggD9g6tXfA
qUT7F5ha2CBJmtLFGCSU6u5IZf4p8/zJj1Xt/sn+/ecDiJMaBvdF1Nieyyoyy6QH
eHzSuVj9dhB9ZJiJTy26GUy+QjwwMtPiJZRiryzEnh01P79ZEyOAWTx645t2re24
STSfT30r/zVEepfLyVD2Nkn9ILqXWNbmFLkUrIVs8keWvzh9aTz0K5+r81mfzD0m
SoticAwLVpqWIeuwsJDu3GjPi2DfxhSa6E8zlb7btzvpXcUgPkc75psTIA4K6KtJ
oSCsZLHbmiSo3c+CJLF2Q1t8XMzqBFygiXcaOqoB0jXTaeV5C8PYbJj/an0+wjc4
0J5B3FPywDR+IO0D79Jb1doQGwhD1mtLNE0Jq1LIV+R6HBo19BFxWUZ/SrkWh7Ji
f/bkiTop1by+9qWwv1Lgvz2PSomNAZ/ZMMZ4Cuy410aH1Z/Qm47S5r15suzKX4t0
+M9BnCY6/6Dx5ABFiw06BPN5RjSsq2FCcwtaH3JYSY7ZmADc+4hs2IjBQFVtKScP
80oqPj7Io2FH1kHNhp9n4CgEDjze/AztQ+uia/QzP6XtUhajDV7P6UbpwWDKPG3u
QRakjnfBAz3Zpo5iN5T909mT1lbb1MpxmPPg0w3zHD2yHlr3pqUS/2j3FXTc9JJZ
00rDmsUL796InNwUjcWLFfAKWJUWwvc8lTO0TbocSyTws3Nh2qgLfsrf6r62RktS
guHhquTZmuEfPS27+LGeacRr1dWHuIcAhUzzq4xXsP7ps+Dfz+RnzJCpxCSERWmV
2EVfB53mVm83b4qsrRN9qw+YmiISzPdipFnEp1L5iJvzQ39HwfWGr+APY1R971qY
lV9hjbp+MKF9JyxFGEsFvh/vL32mzF7l1EzI4OCOeWCV7czmjTe36Ndazvy+9DpW
V8yIxr0qlD79nOB1Ot5dbF8QmY4rQv+GtUfHCosUWFjG2GZI1iQuS3y4JdQmoZpl
7JTKc4y4SX4XGMEZ6iU3x5Q+yM7sK9nRFL2X1nxg/vK+PACn1DORBg0ItFKr8+cZ
7oFZxv5A6W7j3vffDd2fifkpKkv1XKAMxdfh7MXd64+/dFYYd5hGjLeJV358Fjgf
yJa1RORvzCpR3DqFANULVOJL6DkCilvYVlRU+/8r8D0vtL2OgTCzQyNXo37/uYGc
c+G1Unfr0W8v0FKEknd8x8MXj97m7OM65L3dyE2YkJz/nTQO4OlGHZcZ9bzxW+LK
WRrM8Hpb2f0teSbOGpMQ6gpMPOkzRgTjr2N19Leoahb+KFCJCgGMXRctseS95Iwm
WEXRDtEtuzW7L+mZTjIDVNRLiR0eKjuhtmv0TABFWSytuZxV/mY/rJTXKaM5eQSP
gZEfkh7CsYPPOGPpOHjUIx6NS1QgNFQAlmdVw6L3OeorDijBxj3RZYa0cw0B/pXz
a3LOBmLH0pIoWva390fqPjRF+BrsAqBvuv0S4WQ2N/26PRX0zTQJ+KsTZ/+o44tB
5nuXo/xTnh/ExDtsaYBfZfMvc44SwSSKiPv710lUoZD7c5av4C0CGFte89FqJhVN
9nj1k5bCnVbrlW+oRLFU3DAPzEG5EOhzSXN6Gs64T7jGobKVwAkPi+YyssvdXH3c
8b7wb0sufiZQDmnm9yH0wKF5YqI1a71j+h16CRZg8N78/9SyE8lsO6aKF5TgSZKI
BJASZRBU03KCILEumI+3/l0haUssyp3YM8cmhMGkoXYk+/zx1sqTAOThIu+fokZY
2tRVD50QwIW/AYzYiAzH8I/X4LEjwaK+c+u0YlERcTzhgYu6f81XfNdDsuGDUpBW
HgaSnHAhWmGn6U/58NfoRiVqPC/Ulox4FWgaBz26S9vbdkbSVxb64EbsfmqSBv4N
e1/vMwtq6K+BFcMB3cWxrb1aD1167wvCT0od0EV3EOwt4EO75RyV4s5k9PrwkEqw
kDtr9OmRtFWjb52hiX8tL/rrnvxsqjuLuoE6Kj8oNNMi+BQWe95yOxt8RBmlF8aq
fhfFjQ7JxLxBP/1gNK/U8c7rB19hAPm+/pwGPQK3s8Lguxz4BMkI2bp225VbKDeW
UP67mgNSg8wObwMu1BrzkDJo+eo7jSJH1kFwjlDhn4o68la7C4tPQpjZYMgZFZw3
CvujHixc0cGSYT/eK3WtWiRcllEaACT8lKZpVDTNCwX/n4GBiiQVIcXXpZ7w7VYn
TLK9Tsc+qbynu4bKGtd4fx7jRgcBqA9Q0dXci8Tl1BNiCI+AetWLiFe9nj70qVS1
GrbUaN2mrjJnvVlACSpB41NE9mqPAeIuJapryWTELQtspIfsjX4qO7YnLze2J3j9
FkTzi7znxUnqyG1YcaZWoK0fTEw/jZOSl8It1fkKhwdgiZuBwRm8D0b0Sf4E9GZ5
4xnftEHhKvLULwLJ9UKah9jPaVtXUKlQYhtBUjoF6Hg3LFFLJF8tEt9nVcnLtLjR
uMdYCPt5GBHSV4p/jBHRfMgM8cVwch0ucwpCytt2JaNBRpwfy1RZ3/qGWFlcOsUN
rLVATvHz/echszfVxR2s2+o18gsw/+Km/2yQFwqrzDex/m2VAX0QUfHMohDJ+mp/
vWM+Y08/hcKT4fjWPsjb4zfHcn49IlfFxcwkuCreYeqew9nTgBfpUB/id/tGBiTl
zP49CGut1cIX6JBxxy7Eof4unMphDnxp7PK5SeKLP9EeDX5MgBNGjHy5luLP9EBY
6ezdUZ2RS6+Jz2xXtOUf3y2WHqKxNeBzTtcgWvZZCNZt+UsqPl/jqwWp2ApuoryP
jZP7YK3emGRB2tKJwGMegIvDILOyu4Keen0gIAR2rc1rL+i4OpuNJG7BskhuIFkj
OaRpfDsNSO+F88ObwCRs5H3vc5Rhv+q6FcuzRK+/DStsj+nSHKipPwABpNzE/7hW
H8WKMSebsYDFG4JZS9WHoS/VcknHwvT+U8bp4UH8iZokYSwOaUD5++9TJ4JI4WlZ
VWFJakzp3A/955nKYvf5meb7fx4XOPsaCPMelq7xz3zZAsDNqKiStNi0ur4zaw/e
cmgcfAuqR6AupEPdc3OVsAg8K84kk1s/tOLPC4ytXW37bgCYZl+sLNbeG5+7lHM7
SEl/IsP8IoHDsmrabSoYtYTtkSJvGYrjOlsKGdVIe/4xJtJ+sJAVNBsb9Sgf+IDn
Fr0uY/pOsNZlaeRo1ynVirRuLIKlQgKuGv6sKRIq9mAeCdDwR7V5SbrVC823jttq
OjqDiCcyFMDxo1VxTpTLt7NWHG4VP4OTNUX5KXUhSO0H87g+roCB9j0a/P0maS6q
/T19Ap6cMwYIxQr4h6grHdbkNZELhGzjCATrvT8js1OQ+OAtuFfZ/gkTPbjXwhmP
FB4MZ8K+dSAfqitdERXGqLZA7REQBPf0MKZXkFDvOUUkgNhqVuFAvDFedL9M+/cS
1Y1uo42WylBQmbqiBl9wn353KBFzSCpkbkc0mwajzs5MF0brJ92SyMFOMFjgI2gF
A+pfuoYaR9v5dyu8lNUpfY+DwiWCD/lowrlN7dGgxPGxxe5qMGHt6WiWE3Bovv73
WZblIy4T3jJDJJzYSzAna79go0t574uRxoYduglj4xfr6oC1MEbjerQwiIPyVr0I
WqvIRIIwnf9XOLSd4KfruiTEx8N9iNZMADNuqtXT0r1EDWLLvLpRzLdwvlF1CMwb
ZHSABnwKIfY3p5V8k5Tshv4mg/jo4AfjSOxvThiLWOZDdyNGcY5v3LEs5XluoqZY
AspRGldTw1HG0KKpnzmw+jCqbDOkRSds5h/FrerFfaLA/ZzpY/D+q+vJNPk5Obhe
StSGcERP/9uZbpU6k9p+L+iEl4TAyygvaUnCqO+leJ12WDgoeBzjtXMcgdsoQ0DS
93Q1HoMRd3LDdpuldFTgAHr01Xw8Tbig+85b5Mc4bxzsnu6Vm9tSAfo4dxRJn4G+
XH8CdL9MgHaFyF7KJtDRkWYyfEVwdzeluQmJtR/hpQwv0bLyzploASxCoH3+U8Nh
lAr3zFRVZRgA0wUBIgctrInDqtTMPNKlmdPObghnECA1Khfo+jcKTRIFZtDGK3bq
xjduL9NukOBSjOpO6V8dUs0Cfqbgm9wLeo5ME1bwsttszgEPrkRydXJ7y7u2+iKo
TBvKiEAIVvRYi1GpUCGsZWsJKPkvm5JVpLyNBAP1FShLJlcywS2d3CmAJNSLUV85
WwGJvXmJgmZd+LzQoCowZVirlEYVILfN+gZKXpOQPzRx9gUiNc1mfXiMUnNW0tog
mKuRvjsSU6w3nFtXpWTK/nVS7sjcmMH1MhwSofvldXd/CNNGaafeVNx2UD9uv0rT
oCESHmkuj4GqP5Ky/t/EKEY/gbFswcROUvGUBa6pgjiU5J3tsBNCLbrRl5NS5vKN
aDtGneggltXPcUwidDZHk1IMeNmmQY11B7IL26AOslEGyiAq7MivNKot2gqcp66Z
Oky4OM8PJqp5l1/bowomSETODQEHzIdVQ0nEnnYnMPX00BJzON3GhpJb1WDm1iZA
6RexYHoZkGKwCPJOOG517Xar36pu14YP6bKElmvyYJSLYbz4O0Wg4lxvbzCLuyeI
Pul3/fA1GsJEvTClENjc1M9OPWZQ73xPWQmetUMxwDcB0GWYY9jUgSte2eoVJcfC
oMI2pe6qnkgYf7JYRb9GdyGRqEszYfPQ094HK8aEjDIyJg0y+LDFyywdFkalOya3
yiKHio1gc0vdwOArjvNTwQdCXvisULBK84+SPSybXUEw4o05L8jhAPGW0eQQNr+v
Rnj9eukvcTEVWB3BKF5kp9fi69+YqCFol3SDELEiVaPeucl0Yx/C4LyPaRNtayGP
8aZUVZ6PM3bdqECEZDC5bPYB29mPoDVA2A+MSWIdtzg8eW1T6FGNy7UAjGc64fLO
nH1FWaGmJYsv9Gh+lrFlD9uHD5rvZPAnbYDHYZr3E0ZAWVxSFNTkut6wRWCVcyr7
+g/Drx8ZLb67Pr8kHHdq84mudYBCUqe8Fyp2KkKzKfe5+4E8QdzD8YBYRBrD5hb0
13CZdadFntP70mC75w3+Px4Id4VkD/9aOibgdqpb16Q+l51I3ORya16Z5e3OMTvL
2dgyxVgvnMyhsuJtDn8HctHLE+YWv7aHWBduTPJ0RkMzCiLpxY/Eka//0YGWpf3t
9x95Y2iNDMSNbo5LWpk+7cPtNVg3dRg3R/46osYE5i93KzmecCzq1RHQWtIg0v4T
D/dqAY80jOrO4kRfXNIVBJi/UwobaFnEw+djoCEFQL/1T0buEGsCH7EK4nu0hO2G
Nm9RdOi5SvN4mxC3QbNv/xz+9/fGBZihVWDBbwia24zqxz3eEz47wqQQ2eOabOxN
QSkCdy1n9iIerYcqADrjQD4hsbHwrNYV+L7R6r9dXxVSGH4dhfYwD3EZo+SVzJTL
CVeUW2K9Ew/t9gLInCzUH4P+kkYGfNvkF1gUS3DlU7UDTTu2nNHqIxnYOXLc8jfM
XwMaHKu72ls9SSy03hQ3/ir3rWbI1gvLXnfmMwvwsriA6ugZvB1vPA34Qb8Ii7Yk
8Mg+CbVIW9Dmr/3v5qsllJEQ7Yh8II+pcvm/Zftq82P1N4KaxKT3CJAsSk8/sJz/
LwJlRRy6uJXubivqb3KpSOMwCaXC7WIkT0wBF4ma7mG7/ANNgwELojK4q3xdrriT
OdaNi9W1Aapxk0fC6CyEoS9GlL9BdPV4eEKph32d0whr5GDXtHcuUmkV/bhFHGzk
6sdKJuvKsy5z/EZhRWw5QaFmCNYdV1bd8IWw4kR4/gyyxjK/LMM7o2pr3pmxC+Bd
5+k18NAC1wSnN9SmNPVcdI8pFEY8tdJNAs3QNTmuxvECCUqpw3b6aBJWPhIg6BT1
XSOafr7EwAQNqTS5uYD7AWJZVINSA7gsaGuI2OB4bhp/7ir/rWJ4+ARr1unBV+xO
LtUl/yqBMhbHyyglKVI6HvoAYq+GrXJF+TbvCqpCwWxci2DV3qvWXB5LFI4ynwEc
krp5GHhRJRqGzgqwLi2NGsCaIdOfe9vLmx6ln2T/042RvJNxPgbhtGnIMipgfd6d
asgeVmBd/a9uh1J0tyg9XMooRzm6lmmVtzZy29tQMwsgy5NeluRpYBJ3aO1bcu92
Vncn6l0DcZX82eI+RNPFTDcMyVyjTPCH0MlKfEdPi0oTF6aZR+CP7mfjBFugyq78
ClfKLoA0x4r+LgPZoniE7gG+vXgR7PuFKzTKjEezSjC4gjzZm24s/Hrpn0Lz0+S4
KtEfHxnCiIdMHn37qesulV2s80JBFxh/avcoy5E/gGjnZGcrUO4OsKBpu9gHvftD
QNM85yqnyTDX5Hdefy2Vo6YlDPvL1QYSzut6lfFaESnYrGmHN7GNjzZEdKv6F7p1
KlyUDG7ASGcqxkUWKBv+VT6QSAd2Hdxd/EjLQPDTK6gldoIkuZSv5fcX2O+TwvZK
Ytyc6aaDKaQP5tnbrfqgm9H+E1j8d1JsCCffalgcroP9AWxUBM6aFagrp03VVzTY
FGJm90E+3ZC1C1zvvcs4Rb4J3AefL78G4DnTrqfzJsnCY7/EOKJzHYxt+496DTGO
UUhhGoA+kq3Sg1sxZSZ+8XzJ/uGJ8atpHeF+Q16UUUX7xA8MWklke7y6+waQLLKd
v2wwpJzfI9fr1Xn1+7PlmzEDZQdJPEJPPRyTR4TVUS5pEN45webh3u6GIUU3BT5W
7R0ohC6IFZq7fNvRPn43dTEWHmRTJxVFxm/4oWM9rr6z8vd/ynoaw6oCTv8c2I1F
X07/OhIdUxp/SAy0v3MuXLErPVWxmWSbnwHvTXBYFFxdENlDbgu19i1gNLbVJ7FY
7PZy3vWACvf7pf3Zq9QAC/LmQIC1ZqgwLWTsBahMb9vQNSJhudK3ydELZ5XI6+Gw
XfnJATQVJM0+zBz7Lqa9GjS3uP2h/rGLX76S8utm+QOvYngSvurMVbgaS6NQpzZy
VHxbZF3kBEsikmj/HhacqC36fb1MkRRRkqX7gYOdXp8N692c444I9G4NNseDj1Sh
+Vfk+39mWSJXz5b4+I6o066DML7XgIBNjkXoAtyEERclVDENyRovBdSwQ8YfKpvm
BYLtH/4I9ssz2m2vcq5NzGsdLW16AwEJf+P/48aeEeN6lm2iX795sOsEoASb7gBU
tqa/SRbZHLj7rkmlIQ6/uZmVoJk0XfvV5gOFayBWUwSigqISifrFq8nlMBUtn56q
ii0so6oUcpaj1d1ro+qezxwtvS26QEtWZqYlsu0SGf0ZLzHFkgUNVFKyRkPgVpYn
QOG7htmME76UyilUJYsBmPBCWgPSzgy2i43jGXbld3w3RXEzGdG6JPdnSeKNZV7q
+6HY48aZ6fnejzhrCDSrFpfUV0IB4YpMaYiw4jiN0MN+R8M9IYtlTPUoHIY53GMj
FChoDLwuKBFHuW4/4EMnjuAPdxrY0xwWXGNj6wXYleDs6odH7wCaLRmtG772oi5G
h2Z5J9nDupTlRJKbayFjURqW6sbxBL5Oz2ZbbJW6oiDBw0Tr2zPpadFOAemPfIU2
ifrxfqaINbkR4uJUcvISECY+po/J4Eh3/cTtN87bKUqYPWL1xyPHPCieN6r2Z4TC
FyXy9YDHN6rP2P/q5if1q/stAN98pwOWL4zNtoaIIcbm5IzoDvV3xdG/hFRdMFdA
nPmPFbp3MnWkcNLnFsWeB6e2uA94pIwJFn1exASFxVDt5fOqMPeNAruOC9p8Lo6s
C5UnmG1sNh738eO1hKU01xKLOIFzJ6r3YRIJOiLC8lcPd83shEIOlFNVcGTFWzE3
aHHz7HM3MlPFu+Di+trOYSRAw2FeXbTmWCyHa0gby65TtwMx5I+JqkIG+8avwjPb
jKp8NWbFugKPfb9OvfBxxg+MXw8TNK3q7BYNQBrBDwid5NzuflSVCLMFbWRKrTVY
iCzAbEbG0I9cN2prWt3ZtgUKRD9S/niRayhQMUPcCCe63EwopRh66DbsBH34dGzP
9+ro1k4zazZaGe7FfojxiFPhXLeNW9cZpEkMdOsu4yCavi3XSkw9tcGVN5as9vXB
LKhP+e518R+mbc1rxNmfg4Ic0qY37d1aHK/gpfv+rl8hAbbCAyhex4c8AFI=

View File

@ -1,69 +1,69 @@
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

View File

@ -1,10 +1,10 @@
U2FsdGVkX18IAOQU8oTBM3c3nBw5yOIoVP4AA6FBlpvZ+25f5SRxKlHQdqqBQ3X7
e5dbKC5sUAIKWrqpEOpTZIxHF7s6Az1Xkl0cpn8BT6pnVQIfJ7pTlwVEzVxj9buX
cg6Xu0Bf6aZflTQZ2L69s7xcFmZ9U2RrTfvaGx1IBOAW9EkUMKjzCfrPkGXyMUrS
XNZghxobefc772QGU8k1mBoIHWFiE6ZvgMyr7ygYxtvuoQ8Yf6qNLqpTm8DA16jC
jfFOw7PJJETfkXohGoYjmAql1GuqTs+3seZ0kaHe1Of21ej4ksqpQk6MGXcF12DG
oBXzFwc/T8ePbFVMckmXsAqs8W7mqpof5FFVitI5gdnMRvPygwDGkA6kNPh/8SJJ
ylFBaFXalhUfq8ZhOuHDflncP1+PRIG5tnF3FXPSzUw9l0cVrMEYPb8zJsJ8R+f5
BrKtQVH31HsCezfs5EwGxPdqTc51VEMgK3NFHEW4sObEBqJJ8ZZh2oEO0+2No9jR
rj+X8957OZb9D7hqSy5Bxl2fBBF0kkA3pdBM+3gl4kxkcWFkKugdeChdUtU8bmf8
/yxtdK0euG8mziY77dt0dpgekmpBR2XoBUHV1/ZogEd5mKEPDmDhvv3LO/c=
U2FsdGVkX19SrNDcNQsdjfo/tfZAOq9SOyciusnUhmQwo3TTr+19L5zWErgFPF7n
FLIPBXWOHWJp8S8NwGbwGmg22Pp7rvns/5QeMVlwrRZErsdcmW16OOx36s0fO6Yj
xH2wLL8P3YDsEdTRAKwWmjzng/DCFH+3xhy2NbpsdAoiDIQTXt33v0damhj7Mj0I
Yc2uoSzYjGuV/AMmIW56uR9GLY27dFT+AdbSoQThRHiy9EMjPDsyg1e4a1TjOje+
Ls/DO7nGpqIwZx2ZMbo8glTJPR+oYnzepmGNB3ehdLsivJirDxbsIc6Js9uE36er
qB4usUsIrz8H6HYNg/VHVQBNm4BhLDf9ij0NZC1dryuY/zBGgLYHcoVa9Bj7qhOn
A3tWtKc9/MgINf/kRlMdchKZG6sGRc3VcsB9mDYngJeuiShuysmCgajBCahdY4O1
Ctx9VSIFhVlkrlZoE6SoCw/z3MmJsJa/7Aoa2c2hzbIj+m6C0LyEHbCleP+6zCAF
YY5aJdXWbr2mDTOiaFYprtcYC4A7ZEgt3c51H+Lx/r/GLzhU28BYc81SL4+9LUwv
4cDJf/HNTxxp4YyDl52BZD5wS2tzlgwW5ekkXWC3OVpcC0Nlstrd6blHGVM=

View File

@ -1,3 +1,3 @@
U2FsdGVkX18Dp45zb8ShQdHBDj6YBfY/NQIu55pXo48Dk4/rL5BvttD142Ykb9xB
7QkDzeXo8IH8BWA8JtI0DW3zZgE7fq9tGKfqYNHrxxrmK6kQQWwh4A5ugNHSsyZ5
G706htw=
U2FsdGVkX1+iMoNxF8ynmoanDXQhWQndNxROETBHF/DNS0Guiy+YKkV6GhpotHjY
0xWuD3VVFP8zwOx3rWfnlvd34+cqrjgbBoyXDh9Q+mlMMGd3HMHJ1UxnXZSJV5Jx
6+NIKbE=

View File

@ -1,5 +1,5 @@
U2FsdGVkX18FUDhr6TfAfFw+dAljqEqriws+OfI0VQZ4JoOKbRVZcZeXnjV94ozM
W2VlZKDP7Sfd7XGdJmZZ1qlghABEFdE0z3dyzDDru5lR/UgOBQK660n+5dGA2BkW
NARm4aiB8yiYZakAkensNqyiJelwjJWUGFT3cJ9+bZRLmon52EGhNilcN9fU4ZF6
P6VbZqSzDOIJZbRLIlJs9d9b/YoGACWf17MXnBYsb8KW7h40tG4WPrCU9qzIiB7Z
jAV64U34n9UP0lRbphRpmjDDuGM9EtBru9G1RHaL5ucQ/Z8auLiN8yWoGws=
U2FsdGVkX1/iadIyfkanSYsP/deFkKz7qDB6n1fgcrrwJRFipVuyd1R5ph4g9+fs
jI0a9x+VDI5BWiEVnG6jPHH0uYf5OvAEJp+lGAB2Qqs3TyNEQzAUTs80Ag2V6SuF
KPAiahzl0afwe37jWmjktO7nuMqc5aZZdF+SpgFW9rM6UCsOwe7DYXMOWxUZ+7Lu
f1aCBQOgSq1ISkY2if80RrsYqDiOED7GuEWSoxRA7oS3LWVE0Ieic3WdvHm1+4gP
r8hqrKB44MtDSg/GCSlECM0jBy0yMfEqlY45EaogS54LUphox/o3luVaV+A=

View File

@ -1,2 +1,2 @@
U2FsdGVkX1/PRx8JqT5kqoPxhcYvWD1RLu+dRc2YqNQdFJ6yIWbw+IwSL+fFfvJE
A7VJOHSTrbbDsnUNhvZG9Idyp736V38icbYm79LTdn/jtZpiXcYtQQIkWg==
U2FsdGVkX1+5F6P8h69+QAnCJMdTCeqcwHAhi7MkI7FXIe8QkyTm6p+/9Q/cNXYL
LooOUU2iwIpzfsllori+qaQ5g6wR1nHJc3MM0KuSWupwLIVxK4YbM6E3bA==

View File

@ -1 +1 @@
U2FsdGVkX18b5NlteArdllLCmrXQfit7yWS6pgZ4896+2BLosJFP0y/BauxAkNjU
U2FsdGVkX19BEmmTgg2xvmlXY68UW/HM4hzhrFSMp/m/6R4gICH9vYcjhOtX0OI9

View File

@ -1,2 +1,2 @@
U2FsdGVkX1+O0rTJQvBCLAdswjOexMM5VjlnGw3sVO/i1dYF/T0UrhTBhsqLboLA
jMv9wkzfbf2LiejBVhnOM0BEOU2FYRt5crZDkUAO090=
U2FsdGVkX1/VnjxajHAC1EY3kK5t+Ukk7nGg1HpCu1vasPgeslltagLIpZPWCVZB
Q2pgMIb4xT7JZf5W/YHVlsk7btYR9bf9tI+RMCULwdE=

View File

@ -1,9 +1,9 @@
U2FsdGVkX1+Ay4K0S+xuJiyoMRj00oMkaw5sYVvu9VBR68aypK8eLTng8xoqKwzm
uD1YNhLdh515CgHyMI7/LraT2yDYIlF+pNEfftH6U2qU5IfWSoukD59RscfaAft+
/dend9Y6HyG1WdlyPyLVabruHFScx3d+oaLwEcgggnI/M9coWnHyvBXspo6E75um
gyvFntN4GmJLf1sMQIn0I7lW9djC8nupjSTstRo5HNLM/LwlhwAYRb/jbJUOkYSK
D/SDHW5p/9OrACQzAKHFB3mg4+9SufD+cju8qIAn9uFcyCJxkri6Mz+SGqdXtSgi
fEZE2r1aCUXFa8Nq+qoYbxVue3BFlzxetC7fZrx2zWnmkSgOn7LWDn6q3B3KWeT5
om/g+Ph/RE4piKzm9m2jIx+0TlkUHlpOKAf4Xzwdaivmm6HaCNc5pt1Hw0le1fTW
JE+6BkXFDJz/8ytROujTGlMaMCB/JHgK04diEAnQJmNQnYVG03PxmRHmmqXc1czQ
OnIzyUraBCpBsHSAVsN/afC8
U2FsdGVkX190tK2fRtlU6XqGGKq0rzfIAZQz12ysC+Ltrjgwt95tduUxOcHr32x1
sXgMjc+ZjL76jQV5UVxCRSqpLj46lqJoAQX4CujTk1yoRbG0fZFGqgJr8OQIQGI3
gkwVqtpMyxSE91o62IAmnHFztL+MUTJ+hZjpDo8IkcHDAZIXB7gRgrRUye1Jj0hV
f6eDIaw5P0wzzq5y7fNzbNzM4cK5IjWQtOyhrpcsmjaTzy2S9qzKib3xtAqwMfUC
7or6RLdKWrDcUOZPJWp8nI/cbIITGpNA0hsSK+LV4gbSwzcfhyr00OCGHKMVTf/5
sEBFZmrcdsGxqvWe1D3Hf2CZS3e9iWzBlu4v78jHhLuXc/6+ltPFosZ5AwSJbnMo
m7tTLPMWMmUYmD4E5I2znITrtg7dtPYXItqsTMoHQJFMX0Kst/U6TqFF3Jcxv55s
uTS1p0I/kqldY4p8Fmz2XgNCgm0QvQu5UJukQkuAj0PVOdRtpOR47CqqF0basD82
LQ6EbLe863TL1hhdo+bP907A

View File

@ -1,3 +1,3 @@
U2FsdGVkX18rlFwpzFGY5yOY8oTOToM6ObbcaBBQ3MvWsqZ854+wi09Sf6ArG8Uo
Xsie5UmcjpecYJfoqt2KQBu6fOzugyHxscRWeVF+LOR21/VcCKJ8xwwTifiWf/wg
qeKbVRQ=
U2FsdGVkX1/H11TSJKN/qICnL3UpcHDu7b7mnYfvFE76gKtmueKaKgT45+XTI+Ye
3IBFJDs2p7goQawjXjbN4IWS+6q+DQFnLXcOwQiJiMJtCipLLDImg/TrK/9yyiC1
M7AmptY=

View File

@ -1,3 +1,3 @@
U2FsdGVkX1/9FHgictimSwkJc5uNp4aXHgLVSUUUrvyNekgNTINfsfEJ5Mfcm46+
aNd+f3UWK6EZoQMupTs7iEiL/AsqPsMS0+5uUjZ7GsuWk9q30qjvV624SgIwHvYi
uoJ2eEk=
U2FsdGVkX1/UgigdAI8G1DADfHlOdqKX2TLIy/33gEUA+sADMY2MjCsBnVgirHe6
oFyts9qlwfUmRjiIiB1GYm0GhZ9YkgzZLgRSw7sSqtqiyjt6glZd7OXwt3/pyTs8
TY7U3rA=

View File

@ -1,3 +1,3 @@
U2FsdGVkX1/StXpT1GfebxPB+1TyCHLo5fjFZLNkkWXnCS04WnREE2xlV7OXw0Iq
llqZTflZ/z1hSz7NuUO/vrR57RRo6icf3UXnxvJ8HD6Z9q7uxI+WpIj+ME2zij6B
Jg==
U2FsdGVkX1+j3nwfqf4SUkH2HoSAMqkoYJYgRDPRknNOur7PZ5Ctx+eh2RYufCXd
5yrTs/23jetpqjBGztmrPwZcN1AioGDEMKruyI+Cpr1RLE8SKrRjSvTXXK7nJHhI
Fw==

View File

@ -1,7 +1,7 @@
U2FsdGVkX19J8VE7lArWiwLIURQ8NjPEUwkOAh4m1oR0yrmBCI5u/vhwSQTC+ETb
S3b80dqDKkR8QKRxIaquJHw/KRvQqKViZbu1OsHQTPQhK//mvs6vZ8G00vfucphc
6XIuiJS0u1zbzP6CKoLlkUyVOxFsmVSmxRx8460vgqK00JHSXf82mCAXcePVfHX9
uV9w34x3QkqSzmptx1orJrWa/Y/+et19ghJ/d6Utll+kg5Ldkd6vYcSA5bYFMe6L
LzAjJDLSvRpGkwP7EH2/9Kin5qDA7OUQmrXyFvmb9viCnYSD4TUaxXHYy4SPYcPY
qgFFeNDry5PAhkqLCTKgQWylCZXNbnA7JHp5fdbQCyRFD2sNxVN9ptuqNJd5x+hf
0PzTFokhgtE=
U2FsdGVkX1+asRsSHeh0/QMEflP9kIgC9Fz6cYDcej5HWQZmPkAemCfoFLV5TkuI
1hyzwwhvOtZWdBBDdMi9dG2x5m+/fdVIPpMHb9gc7aGuiudXW2uuPIEve9Z4HaTp
Do6VX/9NTnzRNLZAaFpoBob3r+GF36NJ0tLzaM2VaR/emo0wPkm/0/v3nq/vUZCB
xCOM7sG2MAQU/3FDcLPpoJL0TwU2AJo+PLdX64+ksOcZDdrv3jy9W+oIpn85VWnO
YQAQco4rn0zd2zIIj90pIoCZt3MA6hiJlaFnZ1LTRQ/qE8VVTfwsnvAkkaVsmhoU
fDB1OCVkrg5yVgs/pTwPVQSuXARt3Fg0xYcAz5NhTil08P7DM+D1XSr4NjR9mAwz
uwAXB3aMn+0=

View File

@ -1,3 +1,3 @@
U2FsdGVkX18yVvW7ZvcS0Xc/LsBJmDBTjmHeODQqsVSq8AlzjHH0Z15cY2ibL0+2
/fq+Sb12nfYhXkdFePGNJl+pwTVN2KmQhQtTPUawwa0bmvqC3wPXmHn8O1AndVP9
8g==
U2FsdGVkX1//NF0E4XObFG2/rvsrFG7AG6OaLwJDSaJlOed/DbGkXE1d7bTa9SX1
7g7SeTKm7KdXsb8vxyjWbjRIBw/RQln3IM77bdDBCSCmsLp+HsHndv0QeXSUhSMP
rg==

View File

@ -1,3 +1,3 @@
U2FsdGVkX19MH3jJZJHEhLZLqIGcQCvd7JS2I8vWztP1Htde6A/xfy3zP8U6NUOc
QPBYfycwXLqUM89gVrKnnj28HQiAzQNf2zzPqG7MOpQKA6zdRF6i9n+CGtvXC36u
zQ==
U2FsdGVkX18Qd6gBIE7im5jGZlFK2r9QRPtRj/MtweDdMtXPxO/JbN8zxlGIibcx
5XxR5dtAQE5++pBw1mY8nxrtZIJLAWSS4r3TWDQnNr7XSM3wP8/kxCUL7KvhJ0d+
Tw==

View File

@ -1,3 +1,3 @@
U2FsdGVkX18X2ltRnCWQnXMSt/FSKiq/ScbhdjFP4wmPHi5njgtam/c1Dg+0T1fj
JzOYe53LglUBfjDMbIepcIymHXPteizligpJzNE7DwuzsCp2JTkn9KWzKJb45Qa/
/UtVdTfkS9WH
U2FsdGVkX1/OVD62ZQPn1AUSo2ZWvjHbmfv9x52rv//gH+5wO0bApyxtHHsCZe63
DbfdwiQNPCYKZOYvvf6tzqQsxbZwN0kBeyWKmxK35ZZpuVqA1RGgMB1pk7Ue1iBQ
z9Ta00qOXeWw

View File

@ -1,2 +1,2 @@
U2FsdGVkX18z0J2fwZ9aJR7qoLXW1fmQCUqW0sVF9AMeWVVrkHFRO5FZWQUuMQ9s
fBLm3Q13bT9nM46wXg75DzB15gPmYN/m+4oePxk=
U2FsdGVkX186wcN9NuydqFDXes3OG2eoric99wmndrgVNV0RXxmEYK3MRkJHFYwj
24nAVlJ8yc8jzXbd7tcewDCzXn0Ac1ERKsuxvFw=

View File

@ -1,7 +1,7 @@
U2FsdGVkX18r1KmsRlmD3PA6ycT3FviUjhF4vrJ5mxrfTeVC0eZBHUqHJJ3c0UZ5
wBbPGzN4tQWIlrIfFVHX+dsNkj3/OJtDh1pjoUAi/UkVzmzNnMWWfqh0wLHypk0l
mF+gWyVdzKSDHj0JKobobUgO3Bxq/MMNQmReJ9RgR+Z4D73L/V8Gmx8i867/ofoK
INZZhiUzQRHEz3LEOBL2Tbwzuq6YGS3KMf6lS3VlKeVO8SrXWz7C7Kbc+sehkD5P
Chi35s7zmF2sHJzIN3cio5WQnQkPcFIbTlLRPCE7Y46XyYep5qhlFJDVIswUFy2p
94XzyV+bFCrTR/rzGsZqhBZvkFuWV9UCqH/OFp0mQs+zxmElQrJldwUG+SI260U3
qo2HnA5bRH+Qqp6UnafvWi0EbhnocbOHngg9pm26qOt0rrzmqzRmcw==
U2FsdGVkX1/lMbDFKwGd30MFQm79KYXpJ39/KWo0eDhweuW6JgBZXCzIQfsgo0xZ
Md54zBAYpQ7u+E8G8tuJtnszcFiBDV9ZPCPPCNIzZxT3X4/k3Z/BJrBz8n8tIiLI
zB+aECv9WZfUfposKAUAVHXnjTQAQcJHArPH3+wEAhxU7Ck6CoPzWQi7jPqP7KbT
V8wTTGUbRUA+PGGur7D8z+Eg9Jr+Uj/3N/bOtMxLAvTcJDiJ7LqEkSG7tBJvx1gx
gXk9BQZ6ZWZ9z2DS3AITRXakiJ85o1cUf6eVjtgmTfpzN6E5TL3nsNHpBxsZEjmM
sJs4945wvrMzLCmraXzoqIXONEDhZtDaRxI2go3SKep6t2m6fRyiw2tb39X8FHO5
cL2KstGwC7aH82Y/5r3bV94eSdObuCMUxmbM659bILok05kWM8DYbA==

View File

@ -1,2 +1,2 @@
U2FsdGVkX1+llDB5VqCr1IypfnYvO/G6YP0LZIcGXf5rJXiD7yFgmfag9uqoLpUS
OdevSmwuZRxQf7OMJC//qWZBnKt6RQgtebhWYgecmbJpXkI=
U2FsdGVkX1/r1JwvxVZfT2snMpDmQdldp0FvWJ+szrSoIpvmW0MRzqu9t5sC/hvC
XZPhTw7lwakhlw+sERpjQBxBN5TFVy1OBenOERtnnvW9D+E=

View File

@ -1,2 +1,2 @@
U2FsdGVkX1/LQEXVW9522X9Wk7X9Rjn4vTSUguvsQH7S3hXHFZp440yYE0bWElPm
Bn+iWLLaZNQ=
U2FsdGVkX1+mkPj37zyGLNB/Qg6Q3FjuEP4Ui1J2FoFFsgsJYvAnKqJPtfPo0NR1
wW8teMYlxw8=

View File

@ -1,2 +1,2 @@
U2FsdGVkX1/+v3zwfqsp7i87S5sGEoBaJoWzXDh8hUGn9gRs7KUGFgfE66GwOwjG
1ZfgMEiT3NA8mzboyEA/V+4aX5sl8ATnRVvkojoF
U2FsdGVkX18oUm7/hmXd15uxhFTGsOoCuLTVYTWCdEcdAy7is9ABVXi8sQ0LEd2f
A6RiB4GsVavTcFi/rFHZXCs1r800TDHj1lNieLw3

View File

@ -1,2 +1,2 @@
U2FsdGVkX196+2n2N30QJgKlS5tkir0VWlFSEcP4Yrqg38w/Il8PL/8SRklXLXwD
5NTcgNA4EXp8+ccS8n3cmS2RjqSZNp8ZGlgONxZPxwdcY2gV
U2FsdGVkX19LFU3NQZnhBBFTrDOdHX2yWfKjrFlvjtajfTZQhkpXIxRDiUnUntr4
lZ5dHXrJok1O7bWlVKCZ59zLtA+e5hHBrjxSnYIErWvnUUDO

View File

@ -1,2 +1,2 @@
U2FsdGVkX19YVs+neL4R4JDT1CSsndTtbggYoDxEF2iwRCRDJRtrBBJthnxRrUsr
c+A5NSSRRAu0LQ5vjaHlOYiCtmVCdYu7ECrpHQ40KqYgYhXJAw==
U2FsdGVkX1/pO8dHm5elQ+5CIICbNLeWCuO5rVEPX6Are8Hxj9SYXfM47dWUTm4z
wLMdCqxgQBKTxxfs7l+P9RCDLG03K8d6Z9Aqw5S9j1oFoxxANQ==

View File

@ -1,2 +1,2 @@
U2FsdGVkX1+hzdJWty+aSUN/FIN3b8/9VyaEVNG5G+2FG0CgFOavWfW3g/o4ZcwD
3OCWEgTo7rqsQGGCbi92y/TnuTbMytrN+84eGQ0dVkV1COJD
U2FsdGVkX1+N08asPnuy9GeOFSnq7pgilg4VwkPidE3n6qu934b9crw009t05+kE
kTfFouHdrcIDLX+Gry1kn3WSZNgIT47A8N9tSE2h33aRRqJV

View File

@ -1,3 +1,3 @@
U2FsdGVkX1+1zBjw7Y2NlBeTLcGS8o3Er/ngQMU57HLCN8jSfKBU0/C4o9D4NDjl
C7pRu3oOHmz0Pn9ipLaP87ST9RzVncHw/kqNBh8Dg29n3jNoTdSfwTn6xV/mBwQO
a4OsKusYMI/dCriATixomxe1GkC06YfwJg==
U2FsdGVkX18ukCHRMwgdh9+FALCgM9f4u6hqx2xC/6OB/XhMSkRHllfF5GUJ6kYk
O6UyamMNnMyrg0Us2RkP4ax95HskaPSt6uy7DsmV53cZ0hpoxQAfN+SxBLOU36TW
RhMdt6gT/t/zN+yBwFStJi13oCVQXWDMQA==

View File

@ -1,6 +1,6 @@
#!/usr/bin/env nix-shell
#! nix-shell -i bash --pure
#! nix-shell -p bash openssl git unixtools.column
#! nix-shell -p bash openssl git unixtools.column perl
set -euo pipefail
#
@ -18,37 +18,15 @@ set -euo pipefail
##### CONSTANTS
# the release version of this script
readonly VERSION='2.0.0'
readonly VERSION='2.2.0'
# the default cipher to utilize
readonly DEFAULT_CIPHER='aes-256-ctr'
# the openssl options to encrypt/decrypt the files
# shellcheck disable=SC2016
readonly ENCRYPT_OPTIONS='-$cipher -pbkdf2 -iter 200000'
# arguments of the openssl enc command
readonly ENCRYPT_OPTIONS='-pbkdf2 -iter 200000 -pass env:ENC_PASS'
# regular expression used to test user input
readonly YES_REGEX='^[Yy]$'
## Repository Metadata
# whether or not transcrypt is already configured
readonly CONFIGURED=$(git config --get --local transcrypt.version 2>/dev/null)
# the current git repository's top-level directory
readonly REPO=$(git rev-parse --show-toplevel 2>/dev/null)
# whether or not a HEAD revision exists
readonly HEAD_EXISTS=$(git rev-parse --verify --quiet HEAD 2>/dev/null)
# https://github.com/RichiH/vcsh
# whether or not the git repository is running under vcsh
readonly IS_VCSH=$(git config --get --local --bool vcsh.vcsh 2>/dev/null)
# whether or not the git repository is bare
readonly IS_BARE=$(git rev-parse --is-bare-repository 2>/dev/null)
## Git Directory Handling
##### FUNCTIONS
# print a canonicalized absolute pathname
realpath() {
@ -78,21 +56,46 @@ realpath() {
fi
}
# the current git repository's .git directory
RELATIVE_GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
readonly GIT_DIR=$(realpath "$RELATIVE_GIT_DIR" 2>/dev/null)
# establish repository metadata and directory handling
# shellcheck disable=SC2155
gather_repo_metadata() {
# whether or not transcrypt is already configured
readonly CONFIGURED=$(git config --get --local transcrypt.version 2>/dev/null)
# the current git repository's gitattributes file
readonly CORE_ATTRIBUTES=$(git config --get --local --path core.attributesFile)
if [[ $CORE_ATTRIBUTES ]]; then
readonly GIT_ATTRIBUTES=$CORE_ATTRIBUTES
elif [[ $IS_BARE == 'true' ]] || [[ $IS_VCSH == 'true' ]]; then
readonly GIT_ATTRIBUTES="${GIT_DIR}/info/attributes"
else
readonly GIT_ATTRIBUTES="${REPO}/.gitattributes"
fi
# the current git repository's top-level directory
readonly REPO=$(git rev-parse --show-toplevel 2>/dev/null)
##### FUNCTIONS
# whether or not a HEAD revision exists
readonly HEAD_EXISTS=$(git rev-parse --verify --quiet HEAD 2>/dev/null)
# https://github.com/RichiH/vcsh
# whether or not the git repository is running under vcsh
readonly IS_VCSH=$(git config --get --local --bool vcsh.vcsh 2>/dev/null)
# whether or not the git repository is bare
readonly IS_BARE=$(git rev-parse --is-bare-repository 2>/dev/null || printf 'false')
# the current git repository's .git directory
readonly RELATIVE_GIT_DIR=$(git rev-parse --git-dir 2>/dev/null || printf '')
readonly GIT_DIR=$(realpath "$RELATIVE_GIT_DIR" 2>/dev/null)
# Respect transcrypt.crypt-dir if present. Default to crypt/ in Git dir
readonly CRYPT_DIR=$(git config transcrypt.crypt-dir 2>/dev/null || printf '%s/crypt' "${RELATIVE_GIT_DIR}")
# respect core.hooksPath setting, without trailing slash. Fall back to default hooks dir
readonly GIT_HOOKS=$(git config core.hooksPath | sed 's:/*$::' 2>/dev/null || printf "%s/hooks" "${RELATIVE_GIT_DIR}")
# the current git repository's gitattributes file
local CORE_ATTRIBUTES
CORE_ATTRIBUTES=$(git config --get --local --path core.attributesFile 2>/dev/null || git config --get --path core.attributesFile 2>/dev/null || printf '')
if [[ $CORE_ATTRIBUTES ]]; then
readonly GIT_ATTRIBUTES=$CORE_ATTRIBUTES
elif [[ $IS_BARE == 'true' ]] || [[ $IS_VCSH == 'true' ]]; then
readonly GIT_ATTRIBUTES="${GIT_DIR}/info/attributes"
else
readonly GIT_ATTRIBUTES="${REPO}/.gitattributes"
fi
}
# print a message to stderr
warn() {
@ -114,26 +117,209 @@ die() {
exit "$st"
}
# The `decryption -> encryption` process on an unchanged file must be
# deterministic for everything to work transparently. To do that, the same
# salt must be used each time we encrypt the same file. An HMAC has been
# proven to be a PRF, so we generate an HMAC-SHA256 for each decrypted file
# (keyed with a combination of the filename and transcrypt password), and
# then use the last 16 bytes of that HMAC for the file's unique salt.
git_clean() {
filename=$1
# ignore empty files
if [[ ! -s $filename ]]; then
return
fi
# cache STDIN to test if it's already encrypted
tempfile=$(mktemp 2>/dev/null || mktemp -t tmp)
trap 'rm -f "$tempfile"' EXIT
tee "$tempfile" &>/dev/null
# the first bytes of an encrypted file are always "Salted" in Base64
# The `head + LC_ALL=C tr` command handles binary data in old and new Bash (#116)
firstbytes=$(head -c8 "$tempfile" | LC_ALL=C tr -d '\0')
if [[ $firstbytes == "U2FsdGVk" ]]; then
cat "$tempfile"
else
cipher=$(git config --get --local transcrypt.cipher)
password=$(git config --get --local transcrypt.password)
openssl_path=$(git config --get --local transcrypt.openssl-path)
salt=$("${openssl_path}" dgst -hmac "${filename}:${password}" -sha256 "$tempfile" | tr -d '\r\n' | tail -c16)
openssl_major_version=$($openssl_path version | cut -d' ' -f2 | cut -d'.' -f1)
if [ "$openssl_major_version" -ge "3" ]; then
# Encrypt the file to base64, ensuring it includes the prefix 'Salted__' with the salt. #133
(
echo -n "Salted__" && echo -n "$salt" | perl -pe 's/(..)/chr(hex($1))/ge' &&
# Encrypt file to binary ciphertext
ENC_PASS="$password" "$openssl_path" enc -e -$cipher $ENCRYPT_OPTIONS -S "$salt" -in "$tempfile"
) |
openssl base64
else
# Encrypt file to base64 ciphertext
ENC_PASS="$password" "$openssl_path" enc -e -a -$cipher $ENCRYPT_OPTIONS -S "$salt" -in "$tempfile"
fi
fi
}
git_smudge() {
tempfile=$(mktemp 2>/dev/null || mktemp -t tmp)
trap 'rm -f "$tempfile"' EXIT
cipher=$(git config --get --local transcrypt.cipher)
password=$(git config --get --local transcrypt.password)
openssl_path=$(git config --get --local transcrypt.openssl-path)
tee "$tempfile" | ENC_PASS="$password" "$openssl_path" enc -d -$cipher $ENCRYPT_OPTIONS -a 2>/dev/null || cat "$tempfile"
}
git_textconv() {
filename=$1
# ignore empty files
if [[ ! -s $filename ]]; then
return
fi
cipher=$(git config --get --local transcrypt.cipher)
password=$(git config --get --local transcrypt.password)
openssl_path=$(git config --get --local transcrypt.openssl-path)
ENC_PASS="$password" "$openssl_path" enc -d -$cipher $ENCRYPT_OPTIONS -a -in "$filename" 2>/dev/null || cat "$filename"
}
# shellcheck disable=SC2005,SC2002,SC2181
git_merge() {
# Get path to transcrypt in this script's directory
TRANSCRYPT_PATH="$(dirname "$0")/transcrypt"
# Look up name of local branch/ref to which changes are being merged
OURS_LABEL=$(git rev-parse --abbrev-ref HEAD)
# Look up name of the incoming "theirs" branch/ref being merged in.
# TODO There must be a better way of doing this than relying on this reflog
# action environment variable, but I don't know what it is
if [[ "$GIT_REFLOG_ACTION" = "merge "* ]]; then
THEIRS_LABEL=$(echo "$GIT_REFLOG_ACTION" | awk '{print $2}')
fi
if [[ ! "$THEIRS_LABEL" ]]; then
THEIRS_LABEL="theirs"
fi
# Decrypt BASE $1, LOCAL $2, and REMOTE $3 versions of file being merged
echo "$(cat "$1" | "${TRANSCRYPT_PATH}" smudge)" >"$1"
echo "$(cat "$2" | "${TRANSCRYPT_PATH}" smudge)" >"$2"
echo "$(cat "$3" | "${TRANSCRYPT_PATH}" smudge)" >"$3"
# Merge the decrypted files to the temp file named by $2
git merge-file --marker-size="$4" -L "$OURS_LABEL" -L base -L "$THEIRS_LABEL" "$2" "$1" "$3"
# If the merge was not successful (has conflicts) exit with an error code to
# leave the partially-merged file in place for a manual merge.
if [[ "$?" != "0" ]]; then
exit 1
fi
# If the merge was successful (no conflicts) re-encrypt the merged temp file $2
# which git will then update in the index in a following "Auto-merging" step.
# We must explicitly encrypt/clean the file, rather than leave Git to do it,
# because we can otherwise trigger safety check failure errors like:
# error: add_cacheinfo failed to refresh for path 'FILE'; merge aborting.
# To re-encrypt we must first copy the merged file to $5 (the name of the
# working-copy file) so the crypt `clean` script can generate the correct hash
# salt based on the file's real name, instead of the $2 temp file name.
cp "$2" "$5"
# Now we use the `clean` script to encrypt the merged file contents back to the
# temp file $2 where Git expects to find the merge result content.
cat "$5" | "${TRANSCRYPT_PATH}" clean "$5" >"$2"
}
# shellcheck disable=SC2155
git_pre_commit() {
# Transcrypt pre-commit hook: fail if secret file in staging lacks the magic prefix "Salted" in B64
tmp=$(mktemp)
IFS=$'\n'
slow_mode_if_failed() {
for secret_file in $(git -c core.quotePath=false ls-files | git -c core.quotePath=false check-attr --stdin filter | awk 'BEGIN { FS = ":" }; /crypt$/{ print $1 }'); do
# Skip symlinks, they contain the linked target file path not plaintext
if [[ -L $secret_file ]]; then
continue
fi
# Get prefix of raw file in Git's index using the :FILENAME revision syntax
local firstbytes=$(git show :"${secret_file}" | head -c8)
# An empty file does not need to be, and is not, encrypted
if [[ $firstbytes == "" ]]; then
: # Do nothing
# The first bytes of an encrypted file must be "Salted" in Base64
elif [[ $firstbytes != "U2FsdGVk" ]]; then
printf 'Transcrypt managed file is not encrypted in the Git index: %s\n' "$secret_file" >&2
printf '\n' >&2
printf 'You probably staged this file using a tool that does not apply' >&2
printf ' .gitattribute filters as required by Transcrypt.\n' >&2
printf '\n' >&2
printf 'Fix this by re-staging the file with a compatible tool or with'
printf ' Git on the command line:\n' >&2
printf '\n' >&2
printf ' git rm --cached -- %s\n' "$secret_file" >&2
printf ' git add %s\n' "$secret_file" >&2
printf '\n' >&2
exit 1
fi
done
}
# validate file to see if it failed or not, We don't care about the filename currently for speed, we only care about pass/fail, slow_mode_if_failed() is for what failed.
validate_file() {
secret_file=${1}
# Skip symlinks, they contain the linked target file path not plaintext
if [[ -L $secret_file ]]; then
return
fi
# Get prefix of raw file in Git's index using the :FILENAME revision syntax
# The first bytes of an encrypted file are always "Salted" in Base64
local firstbytes=$(git show :"${secret_file}" | head -c8)
if [[ $firstbytes != "U2FsdGVk" ]]; then
echo "true" >>"${tmp}"
fi
}
# if bash version is 4.4 or greater than fork to number of threads otherwise run normally
if [[ "${BASH_VERSINFO[0]}" -ge 4 ]] && [[ "${BASH_VERSINFO[1]}" -ge 4 ]]; then
num_procs=$(nproc)
num_jobs="\j"
for secret_file in $(git -c core.quotePath=false ls-files | git -c core.quotePath=false check-attr --stdin filter | awk 'BEGIN { FS = ":" }; /crypt$/{ print $1 }'); do
while ((${num_jobs@P} >= num_procs)); do
wait -n
done
validate_file "${secret_file}" &
done
wait
if [[ -s ${tmp} ]]; then
slow_mode_if_failed
rm -f "${tmp}"
exit 1
fi
else
slow_mode_if_failed
fi
rm -f "${tmp}"
unset IFS
}
# verify that all requirements have been met
run_safety_checks() {
# validate that we're in a git repository
[[ $GIT_DIR ]] || die 'you are not currently in a git repository; did you forget to run "git init"?'
# exit if transcrypt is not in the required state
if [[ $requires_existing_config ]] && [[ ! $CONFIGURED ]]; then
if [[ $ignore_config_status ]]; then
: # no-op, no need to check $CONFIGURED status
elif [[ $requires_existing_config ]] && [[ ! $CONFIGURED ]]; then
die 1 'the current repository is not configured'
elif [[ ! $requires_existing_config ]] && [[ $CONFIGURED ]]; then
die 1 'the current repository is already configured; see --display'
fi
# check for dependencies
for cmd in {column,grep,mktemp,openssl,sed,tee}; do
command -v $cmd >/dev/null || die 'required command "%s" was not found' "$cmd"
for cmd in {column,grep,mktemp,"${openssl_path}",sed,tee}; do
command -v "$cmd" >/dev/null || die 'required command "%s" was not found' "$cmd"
done
# ensure the repository is clean (if it has a HEAD revision) so we can force
# checkout files without the destruction of uncommitted changes
if [[ $requires_clean_repo ]] && [[ $HEAD_EXISTS ]] && [[ $IS_BARE == 'false' ]]; then
# ensure index is up-to-date before dirty check
git update-index -q --really-refresh
# check if the repo is dirty
if ! git diff-index --quiet HEAD --; then
die 1 'the repo is dirty; commit or stash your changes before running transcrypt'
@ -143,24 +329,20 @@ run_safety_checks() {
# unset the cipher variable if it is not supported by openssl
validate_cipher() {
local list_cipher_commands
list_cipher_commands='openssl enc -ciphers'
remove_dash() {
sed 's#\(^\| \)-#\1#g'
}
local list_cipher_commands
list_cipher_commands="${openssl_path} enc -ciphers"
local supported
supported=$($list_cipher_commands | remove_dash | tr -s ' ' '\n' | grep --line-regexp "$cipher") || true
supported=$($list_cipher_commands | tr -s ' ' '\n' | grep -Fx -- "-$cipher") || true
if [[ ! $supported ]]; then
if [[ $interactive ]]; then
printf '"%s" is not a valid cipher; choose one of the following:\n\n' "$cipher"
$list_cipher_commands | remove_dash | column -c 80
$list_cipher_commands | column -c 80
printf '\n'
cipher=''
else
# shellcheck disable=SC2016
die 1 '"%s" is not a valid cipher; see `%s`' "$cipher" "$($list_cipher_commands | remove_dash)"
die 1 '"%s" is not a valid cipher; see `%s`' "$cipher" "$list_cipher_commands"
fi
fi
}
@ -200,7 +382,7 @@ get_password() {
if [[ $answer =~ $YES_REGEX ]] || [[ ! $answer ]]; then
local password_length=30
local random_base64
random_base64=$(openssl rand -base64 $password_length)
random_base64=$(${openssl_path} rand -base64 $password_length)
password=$random_base64
else
printf 'Password: '
@ -276,100 +458,73 @@ stage_rekeyed_files() {
# save helper scripts under the repository's git directory
save_helper_scripts() {
mkdir -p "${GIT_DIR}/crypt"
mkdir -p "${CRYPT_DIR}"
openssl_command="openssl enc $ENCRYPT_OPTIONS -pass env:ENC_PASS"
# The `decryption -> encryption` process on an unchanged file must be
# deterministic for everything to work transparently. To do that, the same
# salt must be used each time we encrypt the same file. An HMAC has been
# proven to be a PRF, so we generate an HMAC-SHA256 for each decrypted file
# (keyed with a combination of the filename and transcrypt password), and
# then use the last 16 bytes of that HMAC for the file's unique salt.
cat <<-'EOF' >"${GIT_DIR}/crypt/clean"
#!/usr/bin/env bash
filename=$1
# ignore empty files
if [[ -s $filename ]]; then
# cache STDIN to test if it's already encrypted
tempfile=$(mktemp 2>/dev/null || mktemp -t tmp)
trap 'rm -f "$tempfile"' EXIT
tee "$tempfile" &>/dev/null
# the first bytes of an encrypted file are always "Salted" in Base64
read -n 8 firstbytes <"$tempfile"
if [[ $firstbytes == "U2FsdGVk" ]]; then
cat "$tempfile"
else
cipher=$(git config --get --local transcrypt.cipher)
password=$(git config --get --local transcrypt.password)
salt=$(openssl dgst -hmac "${filename}:${password}" -sha256 "$filename" | tr -d '\r\n' | tail -c 16)
ENC_PASS=$password @openssl_command@ -e -a -S "$salt" -in "$tempfile"
fi
fi
EOF
cat <<-'EOF' >"${GIT_DIR}/crypt/smudge"
#!/usr/bin/env bash
tempfile=$(mktemp 2>/dev/null || mktemp -t tmp)
trap 'rm -f "$tempfile"' EXIT
cipher=$(git config --get --local transcrypt.cipher)
password=$(git config --get --local transcrypt.password)
tee "$tempfile" | ENC_PASS=$password @openssl_command@ -d -a 2>/dev/null || cat "$tempfile"
EOF
cat <<-'EOF' >"${GIT_DIR}/crypt/textconv"
#!/usr/bin/env bash
filename=$1
# ignore empty files
if [[ -s $filename ]]; then
cipher=$(git config --get --local transcrypt.cipher)
password=$(git config --get --local transcrypt.password)
ENC_PASS=$password @openssl_command@ -d -a -in "$filename" 2>/dev/null || cat "$filename"
fi
EOF
local current_transcrypt
current_transcrypt=$(realpath "$0" 2>/dev/null)
echo '#!/usr/bin/env bash' > "${CRYPT_DIR}/transcrypt"
tail -n +4 "$current_transcrypt" >> "${CRYPT_DIR}/transcrypt"
# make scripts executable
for script in {clean,smudge,textconv}; do
chmod 0755 "${GIT_DIR}/crypt/${script}"
sed "s/@openssl_command@/$openssl_command/" -i "${GIT_DIR}/crypt/${script}"
for script in {transcrypt,}; do
chmod 0755 "${CRYPT_DIR}/${script}"
done
}
# save helper hooks under the repository's git directory
save_helper_hooks() {
# Install pre-commit-crypt hook script
[[ ! -d "${GIT_HOOKS}" ]] && mkdir -p "${GIT_HOOKS}"
pre_commit_hook_installed="${GIT_HOOKS}/pre-commit-crypt"
cat <<-'EOF' >"$pre_commit_hook_installed"
#!/usr/bin/env bash
# Transcrypt pre-commit hook: fail if secret file in staging lacks the magic prefix "Salted" in B64
RELATIVE_GIT_DIR=$(git rev-parse --git-dir 2>/dev/null || printf '')
CRYPT_DIR=$(git config transcrypt.crypt-dir 2>/dev/null || printf '%s/crypt' "${RELATIVE_GIT_DIR}")
"${CRYPT_DIR}/transcrypt" pre_commit
EOF
# Activate hook by copying it to the pre-commit script name, if safe to do so
pre_commit_hook="${GIT_HOOKS}/pre-commit"
if [[ -f "$pre_commit_hook" ]]; then
printf 'WARNING:\n' >&2
printf 'Cannot install Git pre-commit hook script because file already exists: %s\n' "$pre_commit_hook" >&2
printf 'Please manually install the pre-commit script saved as: %s\n' "$pre_commit_hook_installed" >&2
printf '\n'
else
cp "$pre_commit_hook_installed" "$pre_commit_hook"
chmod 0755 "$pre_commit_hook"
fi
}
# write the configuration to the repository's git config
save_configuration() {
save_helper_scripts
save_helper_hooks
# write the encryption info
git config transcrypt.version "$VERSION"
git config transcrypt.cipher "$cipher"
git config transcrypt.password "$password"
git config transcrypt.openssl-path "$openssl_path"
# write the filter settings
if [[ -d $(git rev-parse --git-common-dir) ]]; then
# this allows us to support multiple working trees via git-worktree
# ...but the --git-common-dir flag was only added in November 2014
# shellcheck disable=SC2016
git config filter.crypt.clean '"$(git rev-parse --git-common-dir)"/crypt/clean %f'
# shellcheck disable=SC2016
git config filter.crypt.smudge '"$(git rev-parse --git-common-dir)"/crypt/smudge'
# shellcheck disable=SC2016
git config diff.crypt.textconv '"$(git rev-parse --git-common-dir)"/crypt/textconv'
else
# shellcheck disable=SC2016
git config filter.crypt.clean '"$(git rev-parse --git-dir)"/crypt/clean %f'
# shellcheck disable=SC2016
git config filter.crypt.smudge '"$(git rev-parse --git-dir)"/crypt/smudge'
# shellcheck disable=SC2016
git config diff.crypt.textconv '"$(git rev-parse --git-dir)"/crypt/textconv'
fi
# write the filter settings. Sorry for the horrific quote escaping below...
# shellcheck disable=SC2016
git config filter.crypt.clean '"$(git config transcrypt.crypt-dir 2>/dev/null || printf ''%s/crypt'' ""$(git rev-parse --git-dir)"")"/transcrypt clean %f'
# shellcheck disable=SC2016
git config filter.crypt.smudge '"$(git config transcrypt.crypt-dir 2>/dev/null || printf ''%s/crypt'' ""$(git rev-parse --git-dir)"")"/transcrypt smudge'
# shellcheck disable=SC2016
git config diff.crypt.textconv '"$(git config transcrypt.crypt-dir 2>/dev/null || printf ''%s/crypt'' ""$(git rev-parse --git-dir)"")"/transcrypt textconv'
# shellcheck disable=SC2016
git config merge.crypt.driver '"$(git config transcrypt.crypt-dir 2>/dev/null || printf ''%s/crypt'' ""$(git rev-parse --git-dir)"")"/transcrypt merge %O %A %B %L %P'
git config filter.crypt.required 'true'
git config diff.crypt.cachetextconv 'true'
git config diff.crypt.binary 'true'
git config merge.renormalize 'true'
git config merge.crypt.name 'Merge transcrypt secret files'
# add a git alias for listing encrypted files
git config alias.ls-crypt "!git ls-files | git check-attr --stdin filter | awk 'BEGIN { FS = \":\" }; /crypt$/{ print \$1 }'"
git config alias.ls-crypt "!git -c core.quotePath=false ls-files | git -c core.quotePath=false check-attr --stdin filter | awk 'BEGIN { FS = \":\" }; /crypt$/{ print \$1 }'"
}
# display the current configuration settings
@ -396,6 +551,7 @@ clean_gitconfig() {
git config --remove-section transcrypt 2>/dev/null || true
git config --remove-section filter.crypt 2>/dev/null || true
git config --remove-section diff.crypt 2>/dev/null || true
git config --remove-section merge.crypt 2>/dev/null || true
git config --unset merge.renormalize
# remove the merge section if it's now empty
@ -406,6 +562,20 @@ clean_gitconfig() {
fi
}
# Remove from the local Git DB any objects containing the cached plaintext of
# secret files, created due to the setting diff.crypt.cachetextconv='true'
remove_cached_plaintext() {
# Delete ref to cached plaintext objects, to leave these objects
# unreferenced and available for removal
git update-ref -d refs/notes/textconv/crypt
# Remove ANY unreferenced objects in Git's object DB (packed or unpacked),
# to ensure that cached plaintext objects are also removed.
# The vital sub-commands equivalents we require this `gc` command to do are:
# `git prune`, `git repack -ad`
git gc --prune=now --quiet
}
# force the checkout of any files with the crypt filter applied to them;
# this will decrypt existing encrypted files if you've just cloned a repository,
# or it will encrypt locally decrypted files if you've just flushed the credentials
@ -419,7 +589,7 @@ force_checkout() {
cd "$REPO" || die 1 'could not change into the "%s" directory' "$REPO"
IFS=$'\n'
for file in $encrypted_files; do
rm "$file"
rm -f "$file"
git checkout --force HEAD -- "$file" >/dev/null
done
unset IFS
@ -433,7 +603,8 @@ flush_credentials() {
if [[ $interactive ]]; then
printf 'You are about to flush the local credentials; make sure you have saved them elsewhere.\n'
printf 'All previously decrypted files will revert to their encrypted form.\n\n'
printf 'All previously decrypted files will revert to their encrypted form, and your\n'
printf 'repo will be garbage collected to remove any cached plaintext of secret files.\n\n'
printf 'Proceed with credential flush? [y/N] '
read -r answer
printf '\n'
@ -446,6 +617,8 @@ flush_credentials() {
if [[ $answer =~ $YES_REGEX ]]; then
clean_gitconfig
remove_cached_plaintext
# re-encrypt any files that had been previously decrypted
force_checkout
@ -461,7 +634,8 @@ uninstall_transcrypt() {
if [[ $interactive ]]; then
printf 'You are about to remove all transcrypt configuration from your repository.\n'
printf 'All previously encrypted files will remain decrypted in this working copy.\n\n'
printf 'All previously encrypted files will remain decrypted in this working copy, but your\n'
printf 'repo will be garbage collected to remove any cached plaintext of secret files.\n\n'
printf 'Proceed with uninstall? [y/N] '
read -r answer
printf '\n'
@ -474,11 +648,30 @@ uninstall_transcrypt() {
if [[ $answer =~ $YES_REGEX ]]; then
clean_gitconfig
if [[ ! $upgrade ]]; then
remove_cached_plaintext
fi
# remove helper scripts
for script in {clean,smudge,textconv}; do
[[ ! -f "${GIT_DIR}/crypt/${script}" ]] || rm "${GIT_DIR}/crypt/${script}"
# Keep obsolete clean,smudge,textconv,merge refs here to remove them on upgrade
for script in {transcrypt,clean,smudge,textconv,merge}; do
[[ ! -f "${CRYPT_DIR}/${script}" ]] || rm "${CRYPT_DIR}/${script}"
done
[[ ! -d "${GIT_DIR}/crypt" ]] || rmdir "${GIT_DIR}/crypt"
[[ ! -d "${CRYPT_DIR}" ]] || rmdir "${CRYPT_DIR}"
# rename helper hooks (don't delete, in case user has custom changes)
pre_commit_hook="${GIT_HOOKS}/pre-commit"
pre_commit_hook_installed="${GIT_HOOKS}/pre-commit-crypt"
if [[ -f "$pre_commit_hook" ]]; then
hook_md5=$("${openssl_path}" md5 -hex <"$pre_commit_hook")
installed_md5=$("${openssl_path}" md5 -hex <"$pre_commit_hook_installed")
if [[ "$hook_md5" = "$installed_md5" ]]; then
rm "$pre_commit_hook"
else
printf 'WARNING: Cannot safely disable Git pre-commit hook %s please check it yourself\n' "$pre_commit_hook"
fi
fi
[[ -f "$pre_commit_hook_installed" ]] && rm "$pre_commit_hook_installed"
# touch all encrypted files to prevent stale stat info
local encrypted_files
@ -503,23 +696,85 @@ uninstall_transcrypt() {
case $OSTYPE in
darwin*)
/usr/bin/sed -i '' '/filter=crypt diff=crypt[ \t]*$/d' "$GIT_ATTRIBUTES"
/usr/bin/sed -i '' '/filter=crypt diff=crypt merge=crypt[ \t]*$/d' "$GIT_ATTRIBUTES"
;;
linux*)
sed -i '/filter=crypt diff=crypt[ \t]*$/d' "$GIT_ATTRIBUTES"
sed -i '/filter=crypt diff=crypt merge=crypt[ \t]*$/d' "$GIT_ATTRIBUTES"
;;
esac
printf 'The transcrypt configuration has been completely removed from the repository.\n'
if [[ ! $upgrade ]]; then
printf 'The transcrypt configuration has been completely removed from the repository.\n'
fi
else
die 1 'uninstallation has been aborted'
fi
}
# uninstall and re-install transcrypt to upgrade scripts and update configuration
upgrade_transcrypt() {
CURRENT_VERSION=$(git config --get --local transcrypt.version 2>/dev/null)
if [[ $interactive ]]; then
printf 'You are about to upgrade the transcrypt scripts in your repository.\n'
printf 'Your configuration settings will not be changed.\n\n'
printf ' Current version: %s\n' "$CURRENT_VERSION"
printf 'Upgraded version: %s\n\n' "$VERSION"
printf 'Proceed with upgrade? [y/N] '
read -r answer
printf '\n'
if [[ $answer =~ $YES_REGEX ]]; then
# User confirmed, don't prompt again
interactive=''
else
# User did not confirm, exit
# Exit if user did not confirm
die 1 'upgrade has been aborted'
fi
fi
# Keep current cipher and password
cipher=$(git config --get --local transcrypt.cipher)
password=$(git config --get --local transcrypt.password)
# Keep current openssl-path, or set to default if no existing value
openssl_path=$(git config --get --local transcrypt.openssl-path 2>/dev/null || printf '%s' "$openssl_path")
# Keep contents of .gitattributes
ORIG_GITATTRIBUTES=$(cat "$GIT_ATTRIBUTES")
uninstall_transcrypt
save_configuration
# Re-instate contents of .gitattributes
echo "$ORIG_GITATTRIBUTES" >"$GIT_ATTRIBUTES"
# Update .gitattributes for transcrypt'ed files to include "merge=crypt" config
case $OSTYPE in
darwin*)
/usr/bin/sed -i '' 's/=crypt\(.*\)/=crypt diff=crypt merge=crypt/' "$GIT_ATTRIBUTES"
;;
linux*)
sed -i 's/=crypt\(.*\)/=crypt diff=crypt merge=crypt/' "$GIT_ATTRIBUTES"
;;
esac
printf 'Upgrade is complete\n'
LATEST_GITATTRIBUTES=$(cat "$GIT_ATTRIBUTES")
if [[ "$LATEST_GITATTRIBUTES" != "$ORIG_GITATTRIBUTES" ]]; then
printf '\nYour gitattributes file has been updated with the latest recommended values.\n'
printf 'Please review and commit the new values in:\n'
printf '%s\n' "$GIT_ATTRIBUTES"
fi
}
# list all of the currently encrypted files in the repository
list_files() {
if [[ $IS_BARE == 'false' ]]; then
cd "$REPO" || die 1 'could not change into the "%s" directory' "$REPO"
git ls-files | git check-attr --stdin filter | awk 'BEGIN { FS = ":" }; /crypt$/{ print $1 }'
git -c core.quotePath=false ls-files | git -c core.quotePath=false check-attr --stdin filter | awk 'BEGIN { FS = ":" }; /crypt$/{ print $1 }'
fi
}
@ -528,8 +783,8 @@ show_raw_file() {
if [[ -f $show_file ]]; then
# ensure the file is currently being tracked
local escaped_file=${show_file//\//\\\/}
if git ls-files --others -- "$show_file" | awk "/${escaped_file}/{ exit 1 }"; then
file_paths=$(git ls-tree --name-only --full-name HEAD "$show_file")
if git -c core.quotePath=false ls-files --others -- "$show_file" | awk "/${escaped_file}/{ exit 1 }"; then
file_paths=$(git -c core.quotePath=false ls-tree --name-only --full-name HEAD "$show_file")
else
die 1 'the file "%s" is not currently being tracked by git' "$show_file"
fi
@ -562,10 +817,10 @@ export_gpg() {
current_cipher=$(git config --get --local transcrypt.cipher)
local current_password
current_password=$(git config --get --local transcrypt.password)
mkdir -p "${GIT_DIR}/crypt"
mkdir -p "${CRYPT_DIR}"
local gpg_encrypt_cmd="gpg --batch --recipient $gpg_recipient --trust-model always --yes --armor --quiet --encrypt -"
printf 'password=%s\ncipher=%s\n' "$current_password" "$current_cipher" | $gpg_encrypt_cmd >"${GIT_DIR}/crypt/${gpg_recipient}.asc"
printf 'password=%s\ncipher=%s\n' "$current_password" "$current_cipher" | $gpg_encrypt_cmd >"${CRYPT_DIR}/${gpg_recipient}.asc"
printf "The transcrypt configuration has been encrypted and exported to:\n%s/crypt/%s.asc\n" "$GIT_DIR" "$gpg_recipient"
}
@ -575,10 +830,10 @@ import_gpg() {
command -v gpg >/dev/null || die 'required command "gpg" was not found'
local path
if [[ -f "${GIT_DIR}/crypt/${gpg_import_file}" ]]; then
path="${GIT_DIR}/crypt/${gpg_import_file}"
elif [[ -f "${GIT_DIR}/crypt/${gpg_import_file}.asc" ]]; then
path="${GIT_DIR}/crypt/${gpg_import_file}.asc"
if [[ -f "${CRYPT_DIR}/${gpg_import_file}" ]]; then
path="${CRYPT_DIR}/${gpg_import_file}"
elif [[ -f "${CRYPT_DIR}/${gpg_import_file}.asc" ]]; then
path="${CRYPT_DIR}/${gpg_import_file}.asc"
elif [[ ! -f $gpg_import_file ]]; then
die 1 'the file "%s" does not exist' "$gpg_import_file"
else
@ -636,6 +891,9 @@ help() {
the password to derive the key from;
defaults to 30 random base64 characters
--set-openssl-path=PATH_TO_OPENSSL
use OpenSSL at this path; defaults to 'openssl' in \$PATH
-y, --yes
assume yes and accept defaults for non-specified options
@ -657,6 +915,10 @@ help() {
remove all transcrypt configuration from the repository and
leave files in the current working copy decrypted
--upgrade
apply the latest transcrypt scripts in the repository without
changing your configuration settings
-l, --list
list all of the transparently encrypted files in the repository,
relative to the top-level directory
@ -689,12 +951,12 @@ help() {
$ transcrypt
Once a repository has been configured with transcrypt, you can trans-
parently encrypt files by applying the "crypt" filter and diff to a
pattern in the top-level .gitattributes config. If that pattern matches
a file in your repository, the file will be transparently encrypted
once you stage and commit it:
parently encrypt files by applying the "crypt" filter, diff and merge
to a pattern in the top-level .gitattributes config. If that pattern
matches a file in your repository, the file will be transparently
encrypted once you stage and commit it:
$ echo 'sensitive_file filter=crypt diff=crypt' >> .gitattributes
$ echo 'sensitive_file filter=crypt diff=crypt merge=crypt' >> .gitattributes
$ git add .gitattributes sensitive_file
$ git commit -m 'Add encrypted version of a sensitive file'
@ -722,23 +984,52 @@ help() {
# reset all variables that might be set
cipher=''
password=''
interactive='true'
display_config=''
rekey=''
flush_creds=''
uninstall=''
show_file=''
gpg_recipient=''
gpg_import_file=''
gpg_recipient=''
interactive='true'
list=''
password=''
rekey=''
show_file=''
uninstall=''
upgrade=''
openssl_path='openssl'
# used to bypass certain safety checks
requires_existing_config=''
requires_clean_repo='true'
ignore_config_status='' # Set for operations where config can exist or not
# parse command line options
while [[ "${1:-}" != '' ]]; do
case $1 in
clean)
shift
git_clean "$@"
exit $?
;;
smudge)
shift
git_smudge "$@"
exit $?
;;
textconv)
shift
git_textconv "$@"
exit $?
;;
merge)
shift
git_merge "$@"
exit $?
;;
pre_commit)
shift
git_pre_commit "$@"
exit $?
;;
-c | --cipher)
cipher=$2
shift
@ -753,6 +1044,11 @@ while [[ "${1:-}" != '' ]]; do
--password=*)
password=${1#*=}
;;
--set-openssl-path=*)
openssl_path=${1#*=}
# Immediately apply config setting
git config transcrypt.openssl-path "$openssl_path"
;;
-y | --yes)
interactive=''
;;
@ -777,9 +1073,15 @@ while [[ "${1:-}" != '' ]]; do
requires_existing_config='true'
requires_clean_repo=''
;;
--upgrade)
upgrade='true'
requires_existing_config='true'
requires_clean_repo=''
;;
-l | --list)
list_files
exit 0
list='true'
requires_clean_repo=''
ignore_config_status='true'
;;
-s | --show-raw)
show_file=$2
@ -831,14 +1133,25 @@ while [[ "${1:-}" != '' ]]; do
shift
done
gather_repo_metadata
# always run our safety checks
run_safety_checks
# regular expression used to test user input
readonly YES_REGEX='^[Yy]$'
# in order to keep behavior consistent no matter what order the options were
# specified in, we must run these here rather than in the case statement above
if [[ $uninstall ]]; then
if [[ $list ]]; then
list_files
exit 0
elif [[ $uninstall ]]; then
uninstall_transcrypt
exit 0
elif [[ $upgrade ]]; then
upgrade_transcrypt
exit 0
elif [[ $display_config ]] && [[ $flush_creds ]]; then
display_configuration
printf '\n'
@ -880,7 +1193,7 @@ fi
# ensure the git attributes file exists
if [[ ! -f $GIT_ATTRIBUTES ]]; then
mkdir -p "${GIT_ATTRIBUTES%/*}"
printf '#pattern filter=crypt diff=crypt\n' >"$GIT_ATTRIBUTES"
printf '#pattern filter=crypt diff=crypt merge=crypt\n' >"$GIT_ATTRIBUTES"
fi
printf 'The repository has been successfully configured by transcrypt.\n'