进程宏
进程宏(Process Macros)用来定义子进程,因为在用ProVerif对协议进行建模时,直接一个大的主进程比较混乱,进程宏的形式为:
let R(x1:t1,...,xn:tn)=P.
其中 R 是宏的名字, P是子进程, x 1 , . . . , x n x_1,…,x_n x1,…,xn是 P 里面的free变量,当使用这个宏时(原文叫macro expansion)就把使用时的参数传进去了。
例子
(*process macrocs*)
free c:channel.
free Cocks:bitstring [private].
free RSA:bitstring [private].
query attacker(Cocks).
let R(x:bitstring)=out(c,x);0.
let R'(y:bitstring)=0.
process R(RSA)|R'(Cocks)
let R(x:bitstring)=out(c,x);0.
let R’(y:bitstring)=0.
定义了两个过程宏R和R’,R将参数x从通道c输出,R’什么都不做。
process R(RSA) | R’(Cocks)
macro expansion,分别将定义的两个free变量作为参数传入,两个进程并发执行。
P ∣ Q表示进程P和进程 Q的并发组合执行。
!P表示无限个 P进程的并发组合执行。
new n:t;P表示绑定进程 P中类型为 t的name n
let x=M in P else Q是项求值,如果 M能执行成功,它的值会赋给 x ( x进行自动类型推导,和 M 的类型一致),然后执行 P。如果 M 执行失败,那么执行 Q 。
对于构造器和析构器,没有什么类型上的限制,只要是标识符就行。标识符是用字母、数字、下划线、单引号组成的序列,区分大小写,避开保留字,且必须以字母开头。注释是用(* 和 *)括起来的部分,不支持嵌套注释。
例子:握手协议
free c:channel.
free s:bitstring [private].
query attacker(s).
type key.
type skey.
type pkey.
type sskey.
type spkey.
fun senc(bitstring,key):bitstring.
fun pk(skey):pkey.
fun aenc(bitstring,pkey):bitstring.
fun spk(sskey):spkey.
fun sign(bitstring,sskey):bitstring.
reduc forall m:bitstring,k:key;sdec(senc(m,k),k)=m.
reduc forall m:bitstring,k:skey;adec(aenc(m,pk(k)),k)=m.
reduc forall m:bitstring,k:sskey;getmess(sign(m,k))=m.
reduc forall m:bitstring,k:sskey;checksign(sign(m,k),spk(k))=m.
let clientA(pkA:pkey,skA:skey,pkB:spkey)=
out(c,pkA);
in(c,x:bitstring);
let y=adec(x,skA) in
let (=pkB,k:key)=checksign(y,pkB) in
out(c,senc(s,k)).
let serverB(pkB:spkey,skB:sskey)=
in(c,pkX:pkey);
new k:key;
out(c,aenc(sign((pkB,k),skB),pkX));
in(c,x:bitstring);
let z=sdec(x,k) in
0.
process
new skA:skey;
new skB:sskey;
let pkA=pk(skA) in out(c,pkA);
let pkB=spk(skB) in out(c,pkB);
((!clientA(pkA,skA,pkB))|(!serverB(pkB,skB)))
process开始进程,new一个非对称加密的私钥(给A用),new一个签名的私钥(给B),然后通过pk(skA)生成A的公钥,利用spk(skB)生成B的公钥,把这两个公钥通过公开信道发送出去。调用两个进程宏clientA和serverB,两个进程并发执行,用 !实现无限数量会话并发执行。
整个协议流程:
- A先把自己公钥pkA公开信道发送出去。
- B接收公钥pkX,new一个对称的会话密钥k,和自己的公钥pkB组成(pkB,k),然后用自己的私钥skB签名,之后用收到的公钥pkA加密,发送出去。
- A接收到发来的bitstring类型数据,用自己的私钥解密,得到y;用B的公钥验证签名,如果验证通过,那么第一项就是pkB(这里用了=pkB进行匹配),第二项是会话密钥k;A用这个会话密钥k发送消息s。
- B收到bitstring消息,用会话密钥k解密得到z。