And of the rest of the patches also....

Den mån 4 nov. 2019 kl 17:06 skrev Carl Michael Skog <[email protected]>:

> When encrypting with a gpg key that has multiple encryption subkeys ONLY
> the newest encryption subkey is used when encrypting.
> This leads to potential problems in pass when using such a key.
>
> Consider this scenario:
> Let's say we are using a key K with encryption subkey A.
> We set up two password stores(S1 and S2) plus a git repository(G) with
> this key.
> All fine so far.
> Let's say now that S1 adds a encryption subkey(B) to K.
> S2 is still unchanged.
> S1 then adds a new password P, and pushes this to G, which S2 then pulls.
> When S2 tries to read password P it will get an error message from gpg:
> "gpg: decryption failed: No secret key".
> Even more dangerous: if S1 after adding the key does a "pass init" with K,
> S2 will not be able to read a single password, if it pulls this change.
>
> Patch 1,2,3 is just some tests exposing the problem.
> The actual fix is in patch 4.
>
>
From ef36e1734a01dcf38f11f35f469abf714aec6861 Mon Sep 17 00:00:00 2001
From: Carl Michael Skog <cm@äger.com>
Date: Tue, 8 Oct 2019 00:19:15 +0200
Subject: [PATCH 2/4] Test for multisubkey group reinit
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Add a test for reencryption with a group with a key with multiple
subkeys.

Signed-off-by: Carl Michael Skog <cm@äger.com>
---
 tests/gnupg/gpg.conf        | 1 +
 tests/t0300-reencryption.sh | 5 +++++
 2 files changed, 6 insertions(+)

diff --git a/tests/gnupg/gpg.conf b/tests/gnupg/gpg.conf
index 60ece49..27db56f 100644
--- a/tests/gnupg/gpg.conf
+++ b/tests/gnupg/gpg.conf
@@ -1,3 +1,4 @@
 group group1 = E4691410 D774A374
 group group2 = E4691410
 group big group = CF90C77B D774A374 EB7D54A8 E4691410 39E5020C
+group multiplesubkeysgroup = B25B8FEE
diff --git a/tests/t0300-reencryption.sh b/tests/t0300-reencryption.sh
index e61d796..0379be7 100755
--- a/tests/t0300-reencryption.sh
+++ b/tests/t0300-reencryption.sh
@@ -78,6 +78,11 @@ test_expect_success 'Reencryption root group to identical individual with no fil
 	test_cmp "$PASSWORD_STORE_DIR/folder/cred1.gpg" "$oldfile"
 '
 
+test_expect_success 'Reencryption with group with key that has multiple subkeys' '
+	"$PASS" init multiplesubkeysgroup &&
+	[[ $(gpg_keys_from_group multiplesubkeysgroup) == "$(gpg_keys_from_encrypted_file "$PASSWORD_STORE_DIR/folder/cred1.gpg")" ]]
+'
+
 test_expect_success 'Reencryption subfolder multiple keys, copy' '
 	"$PASS" init -p anotherfolder $KEY3 $KEY1 &&
 	"$PASS" cp folder/cred1 anotherfolder/ &&
-- 
2.23.0

From a57558736387a9a2768fc7d069f257fe89d8e992 Mon Sep 17 00:00:00 2001
From: Carl Michael Skog <cm@äger.com>
Date: Wed, 16 Oct 2019 17:05:45 +0200
Subject: [PATCH 3/4] Add a test for init'ing with multiple subkey key
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This test simulates the scenario where we have two pass repositories
using the same key, and one of them adds a subkey to the key, and does
an init, and then does a 'pass git push'.
If the other repository does an 'pass git pull', it will not be able to
read its passwords, because the password file is encrypted with a subkey
it does not have.
The error message is: "gpg: decryption failed: No secret key".

Signed-off-by: Carl Michael Skog <cm@äger.com>
---
 ...06EFA1387A43F03768F13E6B25D345AD342F5386.key | Bin 0 -> 978 bytes
 ...0E3D633B6519FCE7187F66277EEE66F174BECFA0.key | Bin 0 -> 978 bytes
 ...A5745D43D2A2AF9D646DEC73F62109861A59C5E7.key | Bin 0 -> 978 bytes
 tests/oldmultiplesubkeygnupg/pubring.kbx        | Bin 0 -> 1433 bytes
 tests/oldmultiplesubkeygnupg/pubring.kbx~       | Bin 0 -> 2058 bytes
 tests/oldmultiplesubkeygnupg/tofu.db            | Bin 0 -> 49152 bytes
 tests/oldmultiplesubkeygnupg/trustdb.gpg        | Bin 0 -> 1200 bytes
 tests/setup.sh                                  |   1 +
 tests/t0300-reencryption.sh                     |   9 +++++++++
 9 files changed, 10 insertions(+)
 create mode 100644 tests/oldmultiplesubkeygnupg/private-keys-v1.d/06EFA1387A43F03768F13E6B25D345AD342F5386.key
 create mode 100644 tests/oldmultiplesubkeygnupg/private-keys-v1.d/0E3D633B6519FCE7187F66277EEE66F174BECFA0.key
 create mode 100644 tests/oldmultiplesubkeygnupg/private-keys-v1.d/A5745D43D2A2AF9D646DEC73F62109861A59C5E7.key
 create mode 100644 tests/oldmultiplesubkeygnupg/pubring.kbx
 create mode 100644 tests/oldmultiplesubkeygnupg/pubring.kbx~
 create mode 100644 tests/oldmultiplesubkeygnupg/tofu.db
 create mode 100644 tests/oldmultiplesubkeygnupg/trustdb.gpg

diff --git a/tests/oldmultiplesubkeygnupg/private-keys-v1.d/06EFA1387A43F03768F13E6B25D345AD342F5386.key b/tests/oldmultiplesubkeygnupg/private-keys-v1.d/06EFA1387A43F03768F13E6B25D345AD342F5386.key
new file mode 100644
index 0000000000000000000000000000000000000000..daf876b26e23c3098f0c859872d15e21a370d3c0
GIT binary patch
literal 978
zcmV;@11<b0F)=!Da%py9bY(4TWqBwwI&yPiC^0&2GBr0k0Jl%1i{Z4)IDl$4RYS@|
zz}1p@yLvT6m>Vmb!6e*#rk*hAdFwk=GqJ+tpX7NJbn8~JjV?Q499#`HTk^Z?bo4F4
zU@+JMR~FeaqJkgS&mKo^=hC91-%8U<LJJ|YIw<|Q89EsV9Nj7bqp&YJSQ?pU+_;u_
z+aj<<Q32hvfAAs+5=`A9BJz|%3YzMh2=+3<qb0h`MSf#%aT7)eZwi@CZac`8)^jk&
z?}0~dZ(R9DybW6eX60V03qJYJhVb$GbY@a(RUDJr<K+RF>&f^x4umh)GZC?ObmQgh
ziO7Tp&&29N2{W2zMUL_;C^JRQM#XM+K7@VDBFu@2<0&XHI%P9D0RRChC^0%@GBq|j
z6BetBS92806L35IFa&v-T?7_F6b(fbd`r{0&ZSu+o|t$~mQ%#WXHDd>)4*CFB|DE?
zq{2~3qq$0cQ?3UF{J>!w)G9(iAY^#8+;|0OkA5G?>oC25%#mp(RP$=?^#aPu8aFN#
zmta2dburD+3*ZW+JmHFOLsIy>;YD3y8FftIZ>e++gkiH$HTLAB<x=L0i}>W^1o^xx
z>~!9ThUT>_N!YM1{^EAun&bWsqBTJdko@0ja2`2IarsAL`40tMy}tR*H9W?k<x*}Y
zMOj_mO@|Zah)gQx{QC*Zx^C-`=B9umu^Q^GPzG(_mo=Q47BYhF)`)I1`_PdYDJU^I
za4|ADIsnK!MKPZF(<X!&WwU;B?otS0Ro3I5hGJe9lfH)#jbSY(RhQr;<nH@$_wJt-
ziy|cLmiTEqXH4P~DSDRPs-A}G;KO1kEGfgWb^hC&@1E3xZ^|l&`66?Ky^{1^gz*4R
z^0OreKm!6pJ>gscl{Y+|q(|SXueZ8bOFD+>@;fOgF*<QEGC4W`>Rs)D%8}+p&Y~|l
z<;gqx{@W@HBknL)0cB0|=t?Gc{US?1N_4msuaSr<VQqbe@Rs&gH=2{tj;`P7`#D&%
z&PPuNjZ(D~!*BtxAjJsH=kr`H(ttaikGY}H6`DSINIt18l49FLWv?qTIkcW1!Jkj~
z6YwuczX)tcYn5bqDJU^IbultIIsmGiAWJKNoL``&>8ULd$B|#Wh_@H!eZ_k3<nqZs
z$$U5++J-jAX`yLQlm8)RlVIL(;7+&$R#SL<={rRRhx6eqeUtrMt32J3V}p$XW{`Tx
z))0rIKD5FnfemUmV}#gj=A173wjvcbdz|d6>=#^hyWZ3q=c@QX!*0WsaBL|lDOsV?
Ap8x;=

literal 0
HcmV?d00001

diff --git a/tests/oldmultiplesubkeygnupg/private-keys-v1.d/0E3D633B6519FCE7187F66277EEE66F174BECFA0.key b/tests/oldmultiplesubkeygnupg/private-keys-v1.d/0E3D633B6519FCE7187F66277EEE66F174BECFA0.key
new file mode 100644
index 0000000000000000000000000000000000000000..666aa3140be551125cfb6c4ce2c98862aa4747ed
GIT binary patch
literal 978
zcmV;@11<b0F)=!Da%py9bY(4TWqBwwI&yPiC^0&2GBr0k0NSs`DP_(82b_XfD`n47
z{fy5$q~#mKUHcxemMk0}_&Zs^PTAj8Kn?z##(3f^3y>0DZN<6@oT+n`TO_)ELk-6Q
z)C#}Lz+0!*G&j21)yT0#35`_x?h<`F2eUpr`*LONF8E_CBT;7Ico_+3xUCloikem0
z$A3d2$sNot<2Kf*`P~`gX6N$v`6m4N<Q~wRPGV$y0%#tj6j#TnaS3a(-*Wl)_aLX;
zxYU7-Nu~W_1{9bVM*N>iHy*PY>_Rek_iZ>=uOg93W-mknefpW+tVHbFxkea1-gQ?{
z^ggLi#U9ojKLhJ@S&>kcpP48}kb@=$LX}kk6>e>^&nYM|I%P9D0RRChC^0%@GBq|j
zAIsEZY_7<S{cIRQ6~X&S2!*Z1kH}DSd5VimT^1=EdlOZ9L4;&C^@d0I!@6yR1&VX2
z?#Qo=Pz_jtwFx`&(nBiK@XXaZUXGE}U3>#|%>m!o#|XCWyh3;q>R<{M*F<zq(%Mnr
zYPzu9W0f)_K8k}wv3jL5mwPgv7pvXx9PV@q6Ukx`;ItPa=`4c3(pJd&1t4ev(rve4
zeF06_oy1j?@+XI=3EG8sJmT5gb(>Sl?vlU?qxcQ|&*T6V^A?-^KJs6U9m?$0NT`&k
z^B+aeGkT1FW(1w;X}C8dho17?Yy(VU<pAdl+`5xuk>N^5kR%)#3HZ^u+_!wWDJU^I
za4|ADIsoO9i$%?f$F2IFzv$%cHV(^+15*nCEn}sd264x2uvRMag?Q2<HmMA5;>hq{
z8Dc*EW(`k+`dzFer5sJD50?4mg&R-d??O?I25P}>V5&X-Cx@#x67iapfff{1#p0W7
zyW0U#MnTjPhT;tiXTsYYohPORtvNjv#CJFHI9VwuF*<QEGC4W`^V?iQ{d?X7n(+A3
zXE8W0OY75Z-W<%-W-v_+?uNFu5Wc`3|76itYpN~<95kiY(v|`|>nb^uU-GUSU9%yq
z1DazfjIx?PepgIslOA)<92civbLS8hQXLvAMceRs@e{cN<#%Oj;OTuUXB+A!>1%V8
zmFK2r&_mRFFOXknDJU^IbultIIsn`Ng)k$`-f4x73LkVY&u&zTIT{`!3+~lb!ffx(
zvX#FIj8O2XrY7=Z8o{o>^Ub3+bXFx>UZUcfZ;yh;xK1lvzN1et(8iC>NXB>v;kvJZ
zaTFQfTP&34Ns!-I+mh#fFkmsWNvK!{PC5>dgVQ|BSP<SQ?tOJ89+&}(IoT;GDZ*6C
AtpET3

literal 0
HcmV?d00001

diff --git a/tests/oldmultiplesubkeygnupg/private-keys-v1.d/A5745D43D2A2AF9D646DEC73F62109861A59C5E7.key b/tests/oldmultiplesubkeygnupg/private-keys-v1.d/A5745D43D2A2AF9D646DEC73F62109861A59C5E7.key
new file mode 100644
index 0000000000000000000000000000000000000000..30a660c226359e850a4eb1f68ccba91a5693ac51
GIT binary patch
literal 978
zcmV;@11<b0F)=!Da%py9bY(4TWqBwwI&yPiC^0&2GBr0k0LqD*4kYD?JuHa)n)S1T
zhd^dVwMLX=0hwapxhC`q_`gkdm@pn`uA0Iz`}p}T{;gh}*yH&YLn)e!2dOmB>Qk^I
zBB`9pumu2amQsU2j%I#QiA69?cs!F*i3>1borl*9Syyi6U?6@YuI<d^$)fSc_^+eo
z-tHFXvT}2!l7E<au0qRAPzeZ)?$yuk^&AtSoMCIl7FrH>##Fbj2x#*XmiN1T#*$#T
zc;j6ERt37Y<S*Y`h30>$V>+Mb;gZ?moMAql+xS&<zU!X=N3666+8Qc<0~?}ayXwV0
zgP((7{sERp1*P7D);oR?#XAE=Xa;GVn&Kg5l*MQLr70*eI%P9D0RRChC^0%@GBq|j
z8_>TeH=zJ>lF_qca<}&>)rr<mA_USQI2aJc%-A|Zgg#cey6y^8jPrY%-^>*ZtMRcK
z?%*&J1U)g^0eySznw7Vel$Nk<aT;iqqk3E%(ru}<0Qn2TrVA5{H>s+#C(Ar)ZmbX9
zhR56uv!U*f)SZC&q2Z7D$XEmQ32WhknCl;ph+0RI9E?)5%=g+aTHBLynC_pbKWqgg
zD!&yuT@(4L{9ZmjPv8uf4*`j*plTMaI%)Za_X0F1`P~^#Af;Q7hTtELvaMhJASQED
z!~GRx-td@t?c~vh_P)t6VhxI@gBBG}rC$oy>*j~T{&t%!2uJ{$N0^}O-Kei|DJU^I
za4|ADIsnv=;p>QjZ5yhl+U<PAMU%T&XXbdc!KcEmB-L^C%wim3C=vZ@;jZ%Mx&a^Y
zj<EG@0h)Z8(W<2z#v|&f!V17htr88kF7tWMUt#>}Ye&e8lWq4_VNP)lYS-Ig*faaS
zI}UcUGZXIEsDV*k1U^a-bhH8dgEk}RK79KJnEfdzF*<QEGC4W`^Xw&KFv)Sas?y!O
zwbElaT&^MxFI5e@VuA4xQGOS;7b{Px(-BF^kzR3+4k|C>(g`;c@Xz$`ldG&Wi^=$-
z5_anZ(KHr(0jN^#b^YN(QT>#3ax(}*RA)bdr+!_4(;bTF2GaM-AcGl8rbG-AY6C%1
z!W9b}aIGl>dA1A5DJU^IbultIIsnsf$<A;QEF2#SXAVxLDJ)TOlo9Y6f}T4c*ma`0
zY=7>(4E{~0P2*$!%R9BQ=;P5l1MfF@l1q`Se7DqDP1bBeXR+O2R$IXJqAqdmP;%fV
zC4nBPsG**VAR{L-1w1LxQ4CgQCnS`u?xUU;oDT9(>*_1MKdPw8Ez1eDF@Y&5DM)|S
AT>t<8

literal 0
HcmV?d00001

diff --git a/tests/oldmultiplesubkeygnupg/pubring.kbx b/tests/oldmultiplesubkeygnupg/pubring.kbx
new file mode 100644
index 0000000000000000000000000000000000000000..368084bb192dafbe80077a2c16a8ec2132d03a2b
GIT binary patch
literal 1433
zcmZQzU{GLWWMJ}kib!Jsg4pF6hd~&`h5*(|CPpx;j)8&YIRg`e%<0ctm8~{d<|Xa?
zy`E=rrsbyS{&zqX3LsTKYR+wq`1EX%x{rfYZJt=~<EJ;T0)=frazMbyzyl=a0a^TD
zJ`)2Am_{RFmuuF8gl01Gvcyh(_KcB(;Z)~rK9#4PwmKbuW_{h<-0qO(w$*J)3ggVA
z2RqfiaQ)ctTQ<W$E_2<iLx#V9{M7rmHg4{X$3MlKHD~p(uQa*vDtLpk(#kofHn1|}
zO$%yv=u4{$>~uBot+1IK)X8m-Ft`0WPh@!Bvjl}Y<#lh*JUO}O<MAKs7eBrCPVD)n
zqT;2K>St80b2{xCz{%13?&|q>UuA?B&PmKZDi+08ek^4BdX9|GLeswQu01v>VMoQ|
znEzp{yS6>izaP{3tbS#()%@oVC*6EFC(&;1?H{2f`(Dpya9^{9<Cc_GJ+t(p<lV21
z+BMH_PWZ<-&7F1Wz2<Ayb%IB&ncXtjGUv>Cq?k74X!_r!41$adj2nQVmtK$#i4TS?
z`~``{#R?^<#U%>asg(+5P-!MeXm&FCu?Pc0&O%I)1zVJ{GJ%4YNt&6Jo0Ef`iA|J?
zlY^UyMU07=kx7n`NxXr9i&Fp=zmHrv7~0-{-h52?%&j+$3BhUS3!igrWnek7@dK;w
zohuSocl=#mFERO3(B`vM+nJYsJ9dI6^2XeV^w<iC9lM$Lw{k~qHj-Ra6BNF7=gO9E
zzqD`P-_s-<l3IA`;gY%XAC`Sx{xw1FR_yXwl{<EuuhgC(rawjK$C<OdT>_=2o*fF2
z{^Xs`@#)iP1CRCjJZ?81wN3q^l+=;OyM12VA+I{m%F`!hOmlh7bMH^pSx|n^X2vSE
zM?MjDH3whGn^nghJ$=1BcU`w(P@mpX!E)_4p4$swPq<}qIAYNwHMOH!rQ5n53Ve!b
z)9raCG;L|U@aM(%>{#u3IS=k$!aKzvs$kcduxr<UwKhA%ZD3<y28KSvPDHBQ?!Tn_
z;g&NN4OwQP&Zk@sT%A<8yUNschP3wVgDQ7wmd!JGS^3&J#CYSOC-a|Fik7?%+t{mT
zog@>(YZm=!_nVS0x`z@BZZL(5-85R%B!B(9oO|B$ON$oY_qy!u#I3m5O5^WNNh?VX
znY&tyi#O<7MM%v|zq4an#cibxu7QkqH`jkq;uP|^tEBX4iWAqYSF<_3868@zy6cQ<
zU2=Y*up37{*G#`W>l0J26&oCX-{_u~AM?|F4{tPc+S9mI+;%_Dw|)5dyCf|rJ5*-!
zt;bIpXTCo9!<?^0|GKf@#`2QKPv3N&XkkBp<dqYr@vJo0zE3(D#;)hwj^>rwwbY(b
zI@8(t7@R6Q8O>NEfC){3Ktkg|PEhp+feFev(R1-<;r9pDUz$?%;>|C{DJPB;Px@z(
ze=3AuEw^#C@aANj)wwHjl=^CCdj!3hZ`ZqXR+@&%wAB_X&BTozEju+X8ZEu!_x+-|
z?Un~6yZ$Sk{H$McNa*B^{Xb*%c>hm4)^57f_R1CB?<y;WV$(AUn<mAqF8RLiXa2Jl
z1$XAHFl$-SdrxuJo)Zrbb{t%jD|_%jmFDfN`X-4guMc;vEk&F^o;+$>%UHeaP~M$B
zo|Em2LZ5F3uDud|%k}>4Nv=Xi*6PW+2nIInf9K&etJUV1V(-!u|MWkX>#FoFi>aN-
zA+|zh^_%_wB&N)NSQ)!^y4kPfLy=F-7s&qI&azql+H=`6a<ByT+RkJB1hvO|zi)V9
N7wIxbpZ(Xqw*YWubvOV3

literal 0
HcmV?d00001

diff --git a/tests/oldmultiplesubkeygnupg/pubring.kbx~ b/tests/oldmultiplesubkeygnupg/pubring.kbx~
new file mode 100644
index 0000000000000000000000000000000000000000..4db9241099f83a1b1a19961d5b5d85a94f3e7f20
GIT binary patch
literal 2058
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
GfB!o#V4q|F

literal 0
HcmV?d00001

diff --git a/tests/oldmultiplesubkeygnupg/tofu.db b/tests/oldmultiplesubkeygnupg/tofu.db
new file mode 100644
index 0000000000000000000000000000000000000000..ae1acde5dc13307516982f61266bcaf315235dfb
GIT binary patch
literal 49152
zcmeI&!Ef4D9KdlqZ6P5^*-k!GXul{ItXf+$x>FA=O}z}2Qc8)`oGc2D$SRl=o2s0q
zRO|n+`~HVXyX-I9Vb5R(du`ThWqqw6p5J@^J-^TICnU>x`J(MdO2)JKbP!3y_{K0z
z<B^DA7^eR0=}&s>=*G?TM1RNQUph?V`}?wg`=ha2=^E9)E8XhH+l~Fd_Q!j({iD6@
z-9M_eFNI(n0R#|0009ILK;UZ@_|V-dTeX_`TNn*qPt<Ea82Q0@n10_l?zzprEB)r<
zwkv6GMd~wuB&|;0J#l-|?X{jYduQ_0J(K2X|9PvUuX^To`c6e;ti!4K#oP}f>ASD`
zj;QItpCs)?sOFvywH}H5sY;{9*Ivvf{&1Q0$nh`k@l&ZMy?!9|BS(I8q~XYYM}D&H
z_?qD?80)JddD-u^IwyL$@mLKb|DE#w6Yh!obMv&_mwRd8PiDqT+;ikJt1JTl?LtXC
zv%6$twmqzrtj3}FtEN=%RWO_{FCu>ygkHjz>Do<rTb(EFE6EI`b7dA}yQQAQu+>i4
zIy^Klzg?v*b7iJk$t5o{a24i?w)4C%ozr&P5y>XOzI<3NTL%Z`ht_JH&_53b(PFN`
zO=~;1%BElbZxubw8~NudOp8KhbN^g>uL~g_&fbTUyDNQ@x}K(k`BL7f<<&BdY@#|z
zJlk$;m#mWm(^zFAd^^!kPu^e=%~t2$=61cKO?&4>sbtwT^UZ2fTJ_$laMQDLE_G?|
zdQP0Rv`6Zz%k1~J%2u;xUVfL4nJJ)r{L<&+e=@(4Uo1187G(Ek$+~;jJX>dQEf6YQ
zzQIr>AnEC?d@l2I>%m~E96i;p{%QRFHU6lLcT3iT2c}x>bTQEtG>Ft>=|%HJ7^#t`
zt0laqdoQ>1YbHruNAO4X4>wBIaqYUAN;B^rrLFiWd^-kvWR|Qucal`RQ}a;&E+k)D
zxf@72rJgpD-&%WLM=`7a82XO`0R#|0009ILKmY**5I_I{1PUmyWp3@n&;R<RKL-K`
zAb<b@2q1s}0tg_000IaUSfCQ`jpzRYXPB)afB*srAb<b@2q1s}0tg^r7`*?d3J^d5
z0R#|0009ILKmY**5GcL?@BfRRV|IuD0tg_000IagfB*srAb<eR|I`2i2q1s}0tg_0
z00IagfB*u;7vTT@i=Sh5hyVfzAb<b@2q1s}0tg_00Pp{)0R#|0009ILKmY**5I_I{
z1d1=f`~TwSm>nX300IagfB*srAb<b@2q3`we`){$1Q0*~0R#|0009ILKmdW_3-JEG
Z_&H{W2q1s}0tg_000IagfB*sr{0ng9!36*S

literal 0
HcmV?d00001

diff --git a/tests/oldmultiplesubkeygnupg/trustdb.gpg b/tests/oldmultiplesubkeygnupg/trustdb.gpg
new file mode 100644
index 0000000000000000000000000000000000000000..ebfaf7b95379618f1028fb59f4705e6cfe7db061
GIT binary patch
literal 1200
zcmZQfFGy!*W@Ke#Vql0}u5p+FJ7DC(E{-8OstzMazyhP;G8!(R5ExAdl%)dz!iof8

literal 0
HcmV?d00001

diff --git a/tests/setup.sh b/tests/setup.sh
index e49d8cc..6452cf9 100644
--- a/tests/setup.sh
+++ b/tests/setup.sh
@@ -51,6 +51,7 @@ fi
 # Note: the assumption is the test key is unencrypted.
 export GNUPGHOME="$TEST_HOME/gnupg/"
 chmod 700 "$GNUPGHOME"
+chmod 700 "$TEST_HOME/oldmultiplesubkeygnupg/"
 GPG="gpg"
 which gpg2 &>/dev/null && GPG="gpg2"
 
diff --git a/tests/t0300-reencryption.sh b/tests/t0300-reencryption.sh
index 0379be7..dae895f 100755
--- a/tests/t0300-reencryption.sh
+++ b/tests/t0300-reencryption.sh
@@ -50,6 +50,15 @@ test_expect_success 'Reencryption root single key with multiple subkeys' '
 	[[ $(canonicalize_gpg_keys "$KEY6") == "$(gpg_keys_from_encrypted_file "$PASSWORD_STORE_DIR/folder/cred1.gpg")" ]]
 '
 
+# When init'ing with a key with multiple encryption subkeys(as in the test before), this test will fail
+# This test simulates the scenario where we have two pass repositories using the same key, and one of them adds a subkey to the key,
+# and does an init, and then does a 'pass git push'. If the other repository does an 'pass git pull', it will not be able to read
+# its passwords, because the password file is encrypted with a subkey it does not have. The error message is:
+# "gpg: decryption failed: No secret key".
+test_expect_success 'Simulates pass show after reencryption with key with multiple subkeys' '
+	GNUPGHOME="$TEST_HOME/oldmultiplesubkeygnupg/" "$PASS" show folder/cred1
+'
+
 test_expect_success 'Reencryption root group' '
 	"$PASS" init group1 &&
 	[[ $(gpg_keys_from_group group1) == "$(gpg_keys_from_encrypted_file "$PASSWORD_STORE_DIR/folder/cred1.gpg")" ]]
-- 
2.23.0

From b994217878d269b9973873bfb8be46ebe13bc872 Mon Sep 17 00:00:00 2001
From: Carl Michael Skog <cm@äger.com>
Date: Wed, 16 Oct 2019 17:24:17 +0200
Subject: [PATCH 4/4] Fixes for having keys with multiple subkeys
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When an init is done with a key with multiple subkeys, the password
file is only encrypted with the most recently created subkey.
This gives the following possible scenario:
Let's say have two pass repositories using the same (main)key, and one
repository adds a subkey, does a 'pass init' with the same key, and does
a 'pass git push'.
Assuming the other repository does not update the key, and does a 'pass
git pull', then it can not read any of the passwords.
'pass show' will give the error message "gpg: decryption failed: No
secret key".

Fix by explicitly enumerate all encryption subkeys and append an
ampersand to each subkey keyid.

Signed-off-by: Carl Michael Skog <cm@äger.com>
---
 src/password-store.sh | 101 +++++++++++++++++++++++++-----------------
 1 file changed, 60 insertions(+), 41 deletions(-)

diff --git a/src/password-store.sh b/src/password-store.sh
index 1d119f2..ecffb81 100755
--- a/src/password-store.sh
+++ b/src/password-store.sh
@@ -67,46 +67,75 @@ verify_file() {
 	[[ $found -eq 1 ]] || die "Signature for $1 is invalid."
 }
 set_gpg_recipients() {
-	GPG_RECIPIENT_ARGS=( )
-	GPG_RECIPIENTS=( )
+	local ids=()
 
 	if [[ -n $PASSWORD_STORE_KEY ]]; then
 		for gpg_id in $PASSWORD_STORE_KEY; do
-			GPG_RECIPIENT_ARGS+=( "-r" "$gpg_id" )
-			GPG_RECIPIENTS+=( "$gpg_id" )
+			ids+=( "$gpg_id" )
 		done
-		return
-	fi
+	else
+		local current="$PREFIX/$1"
+		while [[ $current != "$PREFIX" && ! -f $current/.gpg-id ]]; do
+			current="${current%/*}"
+		done
+		current="$current/.gpg-id"
 
-	local current="$PREFIX/$1"
-	while [[ $current != "$PREFIX" && ! -f $current/.gpg-id ]]; do
-		current="${current%/*}"
-	done
-	current="$current/.gpg-id"
+		if [[ ! -f $current ]]; then
+			cat >&2 <<-_EOF
+			Error: You must run:
+			    $PROGRAM init your-gpg-id
+			before you may use the password store.
 
-	if [[ ! -f $current ]]; then
-		cat >&2 <<-_EOF
-		Error: You must run:
-		    $PROGRAM init your-gpg-id
-		before you may use the password store.
+			_EOF
+			cmd_usage
+			exit 1
+		fi
 
-		_EOF
-		cmd_usage
-		exit 1
-	fi
+		# Cache the lookup of subkeys.
+		# This is only used by reencrypt_path,
+		# where current_gpgid is also defined
+		if [ "$current" = "$current_gpgid" ]; then
+			return
+		fi
+		current_gpgid="$current"
+		verify_file "$current"
 
-	verify_file "$current"
+		local gpg_id
 
-	local gpg_id
-	while read -r gpg_id; do
-		GPG_RECIPIENT_ARGS+=( "-r" "$gpg_id" )
-		GPG_RECIPIENTS+=( "$gpg_id" )
-	done < "$current"
+		while read -r gpg_id; do
+			ids+=( "$gpg_id" )
+		done < "$current"
+	fi
+
+	GPG_RECIPIENT_ARGS=( )
+	GPG_RECIPIENTS=( )
+	GPG_RECIPIENTS=( $(lookup_subkeys "${ids[@]}") )
+	for recipient in ${GPG_RECIPIENTS[@]}; do
+		GPG_RECIPIENT_ARGS+=( "-r" "$recipient" )
+	done
 }
+lookup_subkeys() {
+	local IFS=";"
+	local keyids=()
+	for akeyid; do
+		local group_keys=( $(gpg --list-config --with-colons | sed -n "s/^cfg:group:$akeyid:\\(.*\\)/\\1/p" | head -n 1) )
+
+		# We picked up a group name with some key ids
+		if [[ ${#group_keys} > 0 ]]; then
+			keyids+=( "${group_keys[@]}" )
+		else
+			# If not, it must be a name representing a keyid, uid, etc
+			keyids+=( "$akeyid" )
+		fi
+	done
 
+	$GPG $PASSWORD_STORE_GPG_OPTS --list-keys --with-colons "${keyids[@]}" \
+		| sed -n 's/^sub:[^idr:]*:[^:]*:[^:]*:\([^:]*\):[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[a-zA-Z]*e[a-zA-Z]*:.*/\1\!/p' \
+		| LC_ALL=C sort -u
+}
 reencrypt_path() {
-	local prev_gpg_recipients="" gpg_keys="" current_keys="" index passfile
-	local groups="$($GPG $PASSWORD_STORE_GPG_OPTS --list-config --with-colons | grep "^cfg:group:.*")"
+	local current_keys="" passfile
+	local current_gpgid # Cache the active gpgid file; This is set by set_gpg_recipients
 	while read -r -d "" passfile; do
 		[[ -L $passfile ]] && continue
 		local passfile_dir="${passfile%/*}"
@@ -117,23 +146,13 @@ reencrypt_path() {
 		local passfile_temp="${passfile}.tmp.${RANDOM}.${RANDOM}.${RANDOM}.${RANDOM}.--"
 
 		set_gpg_recipients "$passfile_dir"
-		if [[ $prev_gpg_recipients != "${GPG_RECIPIENTS[*]}" ]]; then
-			for index in "${!GPG_RECIPIENTS[@]}"; do
-				local group="$(sed -n "s/^cfg:group:$(sed 's/[\/&]/\\&/g' <<<"${GPG_RECIPIENTS[$index]}"):\\(.*\\)\$/\\1/p" <<<"$groups" | head -n 1)"
-				[[ -z $group ]] && continue
-				IFS=";" eval 'GPG_RECIPIENTS+=( $group )' # http://unix.stackexchange.com/a/92190
-				unset "GPG_RECIPIENTS[$index]"
-			done
-			gpg_keys="$($GPG $PASSWORD_STORE_GPG_OPTS --list-keys --with-colons "${GPG_RECIPIENTS[@]}" | sed -n 's/^sub:[^idr:]*:[^:]*:[^:]*:\([^:]*\):[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[a-zA-Z]*e[a-zA-Z]*:.*/\1/p' | LC_ALL=C sort -u)"
-		fi
-		current_keys="$(LC_ALL=C $GPG $PASSWORD_STORE_GPG_OPTS -v --no-secmem-warning --no-permission-warning --decrypt --list-only --keyid-format long "$passfile" 2>&1 | sed -n 's/^gpg: public key is \([A-F0-9]\+\)$/\1/p' | LC_ALL=C sort -u)"
+		current_keys=( $(LC_ALL=C $GPG $PASSWORD_STORE_GPG_OPTS -v --no-secmem-warning --no-permission-warning --decrypt --list-only --keyid-format long "$passfile" 2>&1 | sed -n 's/^gpg: public key is \([A-F0-9]\+\)$/\1\!/p' | LC_ALL=C sort -u) )
 
-		if [[ $gpg_keys != "$current_keys" ]]; then
-			echo "$passfile_display: reencrypting to ${gpg_keys//$'\n'/ }"
+		if [[ "${GPG_RECIPIENTS[*]}" != "${current_keys[*]}" ]]; then
+			echo "$passfile_display: reencrypting with encryption subkeys ${GPG_RECIPIENTS[*]%!}"
 			$GPG -d "${GPG_OPTS[@]}" "$passfile" | $GPG -e "${GPG_RECIPIENT_ARGS[@]}" -o "$passfile_temp" "${GPG_OPTS[@]}" &&
 			mv "$passfile_temp" "$passfile" || rm -f "$passfile_temp"
 		fi
-		prev_gpg_recipients="${GPG_RECIPIENTS[*]}"
 	done < <(find "$1" -path '*/.git' -prune -o -iname '*.gpg' -print0)
 }
 check_sneaky_paths() {
-- 
2.23.0

_______________________________________________
Password-Store mailing list
[email protected]
https://lists.zx2c4.com/mailman/listinfo/password-store

Reply via email to