(* Version without private channels.
   Attack reconstruction succeeds *)

free c: channel.


type ksh.       
type cksh.      
type publickey.

event authorised(bitstring). 
event signed(ksh, bitstring). 
event csigned(cksh, bitstring). 


fun pk(cksh,cksh,ksh,ksh,ksh,ksh,ksh):publickey.

fun combine(bitstring, bitstring, bitstring, bitstring): bitstring.
reduc forall w:bitstring, x:bitstring, y:bitstring, z:bitstring; proj1(combine(w,x,y,z)) = w.
reduc forall w:bitstring, x:bitstring, y:bitstring, z:bitstring; proj2(combine(w,x,y,z)) = x.
reduc forall w:bitstring, x:bitstring, y:bitstring, z:bitstring; proj3(combine(w,x,y,z)) = y.
reduc forall w:bitstring, x:bitstring, y:bitstring, z:bitstring; proj4(combine(w,x,y,z)) = z.

fun sign(ksh,bitstring):bitstring.
fun csign(cksh,bitstring):bitstring.

reduc
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kA,m), sign(k1,m), sign(k2,m), sign(k3,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kA,m), sign(k1,m), sign(k2,m), sign(k4,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kA,m), sign(k1,m), sign(k2,m), sign(k5,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kA,m), sign(k1,m), sign(k3,m), sign(k4,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kA,m), sign(k1,m), sign(k3,m), sign(k5,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kA,m), sign(k1,m), sign(k4,m), sign(k5,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kA,m), sign(k2,m), sign(k3,m), sign(k4,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kA,m), sign(k2,m), sign(k3,m), sign(k5,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kA,m), sign(k2,m), sign(k4,m), sign(k5,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kA,m), sign(k3,m), sign(k4,m), sign(k5,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kB,m), sign(k1,m), sign(k2,m), sign(k3,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kB,m), sign(k1,m), sign(k2,m), sign(k4,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kB,m), sign(k1,m), sign(k2,m), sign(k5,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kB,m), sign(k1,m), sign(k3,m), sign(k4,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kB,m), sign(k1,m), sign(k3,m), sign(k5,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kB,m), sign(k1,m), sign(k4,m), sign(k5,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kB,m), sign(k2,m), sign(k3,m), sign(k4,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kB,m), sign(k2,m), sign(k3,m), sign(k5,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kB,m), sign(k2,m), sign(k4,m), sign(k5,m))) = true;
forall kA:cksh,kB:cksh,k1:ksh,k2:ksh,k3:ksh,k4:ksh,k5:ksh,m:bitstring; verify(pk(kA,kB,k1,k2,k3,k4,k5), m, combine( csign(kB,m), sign(k3,m), sign(k4,m), sign(k5,m))) = true.




query chal:bitstring; event(authorised(chal)).



let Signer(k:ksh) =
     in(c, mess:bitstring);
     let s = sign(k, mess) in
     event signed(k, mess);
     out(c, s).

let ContentfulSigner(kc:cksh) =
     in(c, mess:bitstring);
     let sc = csign(kc, mess) in
     event csigned(kc, mess);
     out(c, sc).


let RelyingParty(pubkey:publickey) =
     new challenge: bitstring;
     out(c, challenge);
     in(c, s:bitstring);
     if verify(pubkey, challenge, s) = true then
     event authorised(challenge).
  

process
     !
     new kA: cksh;
     new kB: cksh;
     new k1: ksh;
     new k2: ksh;
     new k3: ksh;
     new k4: ksh;
     new k5: ksh;
     out(c, pk(kA, kB, k1, k2, k3, k4, k5));
     (!ContentfulSigner(kA) | !ContentfulSigner(kB) | !Signer(k1) | !Signer(k2) | !Signer(k3) | !Signer(k4) | !Signer(k5) | !RelyingParty(pk(kA, kB, k1, k2, k3, k4, k5)))

(* EXPECTPV
RESULT not event(authorised(chal)) is false.
0.024s (user 0.020s + system 0.004s), max rss 9252K
END *)
