Encryption 如何使用NuSMV见证中间人攻击(李约瑟-施罗德协议)?

Encryption 如何使用NuSMV见证中间人攻击(李约瑟-施罗德协议)?,encryption,model-checking,nusmv,Encryption,Model Checking,Nusmv,我有以下简化的公钥Needham Schroeder协议: A→ B:{Na,A}Kb B→ 答:{Na,Nb}Ka A→ B:{Nb}Kb 其中,Na,Nb是A,B和Ka,Kb分别是A,B的公钥 由参与方公钥加密的消息只能由参与方解密 在步骤(1),A通过向B发送nonce及其标识(由B的公钥加密)来启动协议。使用其私钥,B破译消息并获取A的身份 在步骤(2),B将A及其当前值(由A的公钥加密)发送回A。使用其私钥,A对消息进行解码,并检查其当前值是否返回 在步骤(3),A将B的当前值(由B的

我有以下简化的公钥Needham Schroeder协议:

  • A→ B:{Na,A}Kb
  • B→ 答:{Na,Nb}Ka
  • A→ B:{Nb}Kb
  • 其中,
    Na
    Nb
    A
    B
    Ka
    Kb
    分别是
    A
    B
    的公钥

    由参与方公钥加密的消息只能由参与方解密

    在步骤(1),
    A
    通过向
    B
    发送nonce及其标识(由
    B
    的公钥加密)来启动协议。使用其私钥,
    B
    破译消息并获取
    A
    的身份

    在步骤(2),
    B
    A
    及其当前值(由
    A
    的公钥加密)发送回
    A
    。使用其私钥,
    A
    对消息进行解码,并检查其当前值是否返回

    在步骤(3),
    A
    B
    的当前值(由
    B
    的公钥加密)返回到
    B

    以下是对上述简化协议的中间主攻击:

    • (1A)
      A→ E:{Na,A}Ke
      A
      想和
      E
      谈谈)
    • (1B)
      E→ B:{Na,A}Kb
      E
      想说服
      B
      它是
      A
    • (2B)
      B→ E:{Na,Nb}Ka
      B
      返回由
      Ka
      加密的nonce)
    • (2A)
      E→ A:{Na,Nb}Ka
      E
      将加密消息转发给
      A
    • (3A)
      A→ E:{Nb}Ke
      A
      确认它正在与
      E
      通话)
    • (3B)
      E→ B:{Nb}Kb
      E
      返回
      B
      的nonce-back)
    我希望当发现攻击时,会提出一个修复方案来防止攻击(
    B
    将其标识和nonce一起发送回
    a
    ):

  • A→ B:{Na,A}Kb
  • B→ A:{Na,Nb,B}Ka
    B
    将其标识和nonce一起发送回
    A
  • A→ B:{Nb}Kb
  • 问题是:

  • 如何编写LTL公式和NuSMV模块
    eve
    来模拟攻击者并见证中间人攻击
  • 如何防止攻击
  • 艾丽斯的过程(A):

    bob的过程(B):

    主要流程:

    非常感谢

    (注意:使用其他工具(如或)对您心目中的系统进行建模和验证要简单得多。)


    爱丽丝和鲍勃。

    在这里,我们对以诚实、透明的方式行事的
    用户类型进行建模,并且在您的用例中可以实例化为
    Alice
    Bob

    作为简化,我硬编码了这样一个事实:如果
    用户
    Alice
    ,那么它将通过尝试联系其他实体来启动协议

    输入的
    my\u nonce
    my\u id
    my\u key
    定义了
    用户的身份,而
    other\u key
    other\u id
    表示我们想要联系的另一
    用户的公开信息。_1
    中的
    、_2
    中的
    和_k
    中的
    输入与代码示例中的输入相同,而_3
    中的
    保留用于交换协议的修补版本中使用的第三个值

    用户可以处于以下五种状态之一:

    • IDLE
      :初始状态,
      Alice
      将启动协议,而
      Bob
      等待一些请求
    • WAIT\u RESPONSE
      :当
      Alice
      等待响应她的
      请求时
    • 等待确认
      :当
      鲍勃
      等待确认他的
      响应时
    • OK
      :当
      Alice
      Bob
      握手成功时
    • 错误
      :当握手出现错误时(例如意外输入)
    用户可以执行以下操作之一:

    • 发送请求
      {Na,IA}Kb
    • SEND_RESPONSE
      {Na,Nb}Ka
    • 发送确认信息
      {Nb}Kb
    作为一种简化,与您自己的模型类似,我使输出值在几个转换期间保持不变,而不是立即将它们放回
    NONE
    。这样,在重置输入值之前,我不必添加额外的变量来跟踪输入值

    MODULE user(patched, my_nonce, my_id, my_key, other_key, other_id, in_1, in_2, in_3, in_k)
    VAR
        state  : { IDLE, WAIT_RESPONSE, WAIT_CONFIRMATION, OK, ERROR };
        action : { NONE, SEND_REQUEST, SEND_RESPONSE, SEND_CONFIRMATION };
        out_1  : { NONE, NA, NB, NE, IA, IB, IE };
        out_2  : { NONE, NA, NB, NE, IA, IB, IE };
        out_3  : { NONE, NA, NB, NE, IA, IB, IE };
        out_k  : { NONE, KA, KB, KE };
    
    INIT
        state = IDLE & action = NONE & out_1 = NONE
        & out_2 = NONE & out_3 = NONE & out_k = NONE;
    
    -- protocol actions defining outputs
    TRANS
        next(action) = SEND_REQUEST -> (
            next(out_1) = my_nonce & next(out_2) = my_id &
            next(out_3) = NONE     & next(out_k) = other_key
        );
    
    TRANS
        ((next(action) = SEND_RESPONSE) & patched) -> (
            next(out_1) = in_1     & next(out_2) = my_nonce &
            next(out_3) = my_id    & next(out_k) = other_key
        );
    
    TRANS
        ((next(action) = SEND_RESPONSE) & !patched) -> (
            next(out_1) = in_1     & next(out_2) = my_nonce &
            next(out_3) = NONE     & next(out_k) = other_key
        );
    
    TRANS
        next(action) = SEND_CONFIRMATION -> (
            next(out_1) = in_2     & next(out_2) = NONE &
            next(out_3) = NONE     & next(out_k) = other_key
        );
    
    -- outputs stabilization: easier modeling
    TRANS
        next(action) = NONE -> (
            next(out_1) = out_1    & next(out_2) = out_2 &
            next(out_3) = out_3    & next(out_k) = out_k
        );
    
    -- protocol life-cycle
    TRANS
    case
        -- protocol: end-positions
        (action = NONE &
         state = ERROR)
                            : next(action) = NONE &
                              next(state) = ERROR;
        (action = NONE &
         state = OK)
                            : next(action) = NONE &
                              next(state) = OK;
    
        -- protocol: send request
        (action = NONE &
         state = IDLE &
         my_id = IA)
                            : next(action) = SEND_REQUEST &
                              next(state) = WAIT_RESPONSE;
    
        -- protocol: handle request
        (action = NONE &
         state = IDLE &
         in_k = my_key)
                            : next(action) = SEND_RESPONSE &
                              next(state) = WAIT_CONFIRMATION;
    
        -- protocol: handle response
        -- without patch
        (action = NONE &
         state = WAIT_RESPONSE &
         in_k = my_key &
         in_1 = my_nonce &
         !patched)
                            : next(action) = SEND_CONFIRMATION &
                              next(state) = OK;
        -- with patch
        (action = NONE &
         state = WAIT_RESPONSE &
         in_k = my_key &
         in_1 = my_nonce &
         in_3 = other_id &
         patched)
                            : next(action) = SEND_CONFIRMATION &
                              next(state) = OK;
    
        -- protocol: handle confirmation
        (action = NONE &
         state = WAIT_CONFIRMATION &
         in_k = my_key &
         in_1 = my_nonce)
                            : next(action) = NONE &
                              next(state) = OK;
    
        -- protocol: no change state while performing action
        (action != NONE)
                            : next(action) = NONE &
                              next(state) = state;
    
        -- protocol: no state change if no valid input
        (action = NONE &
         in_k != my_key)
                            : next(action) = NONE &
                              next(state) = state;
    
        -- sink error condition for malformed inputs
        TRUE
                            : next(action) = NONE &
                              next(state) = ERROR;
    esac;
    
    我们添加了一个非常简单的
    main
    模块和一个简单的
    CTL
    属性,以检查
    Alice
    Bob
    是否以预期的方式工作,并能够在正常情况下完成握手:

    MODULE main
    VAR
        a1 : process user(FALSE, NA, IA, KA, KB, IB, b1.out_1, b1.out_2, b1.out_3, b1.out_k);
        b1 : process user(FALSE, NB, IB, KB, KA, IA, a1.out_1, a1.out_2, a1.out_3, a1.out_k);
    
    FAIRNESS running;
    
    
    CTLSPEC ! EF (a1.state = OK & b1.state = OK);
    
    输出如下所示:

    NuSMV > reset; read_model -i ns01.smv ; go ; check_property             
    ...
    -- specification !(EF (a1.state = OK & b1.state = OK))  is false
    -- as demonstrated by the following execution sequence
    Trace Description: CTL Counterexample 
    Trace Type: Counterexample 
      -> State: 1.1 <-
        a1.state = IDLE
        a1.action = NONE
        a1.out_1 = NONE
        a1.out_2 = NONE
        a1.out_3 = NONE
        a1.out_k = NONE
        b1.state = IDLE
        b1.action = NONE
        b1.out_1 = NONE
        b1.out_2 = NONE
        b1.out_3 = NONE
        b1.out_k = NONE
      -> Input: 1.2 <-
        _process_selector_ = main
        running = TRUE
        b1.running = FALSE
        a1.running = FALSE
      -> State: 1.2 <-
        a1.state = WAIT_RESPONSE
        a1.action = SEND_REQUEST
        a1.out_1 = NA
        a1.out_2 = IA
        a1.out_k = KB
      -> Input: 1.3 <-
      -> State: 1.3 <-
        a1.action = NONE
        b1.state = WAIT_CONFIRMATION
        b1.action = SEND_RESPONSE
        b1.out_1 = NA
        b1.out_2 = NB
        b1.out_k = KA
      -> Input: 1.4 <-
      -> State: 1.4 <-
        a1.state = OK
        a1.action = SEND_CONFIRMATION
        a1.out_1 = NB
        a1.out_2 = NONE
        b1.action = NONE
      -> Input: 1.5 <-
      -> State: 1.5 <-
        a1.action = NONE
        b1.state = OK
    
    同样,我们添加了一个非常简单的
    main
    模块和一个简单的
    CTL
    属性来检查
    Eve
    是否能够成功攻击
    Alice
    Bob
    。。最后,
    Alice
    认为是在和
    Eve
    (实际上)说话,
    Bob
    认为是在和
    Alice
    说话,而实际上是在和
    Eve
    说话

    MODULE main
    VAR
        a2 : process user(FALSE, NA, IA, KA, KE, IE, e2.aout_1, e2.aout_2, e2.aout_3, e2.aout_k);
        b2 : process user(FALSE, NB, IB, KB, KA, IA, e2.bout_1, e2.bout_2, e2.bout_3, e2.bout_k);
        e2 : process attacker(NE, IE, KE, KA, KB,
                              a2.out_1, a2.out_2, a2.out_3, a2.out_k,
                              b2.out_1, b2.out_2, b2.out_3, b2.out_k);
    
    FAIRNESS running;
    
    
    CTLSPEC ! EF (a2.state = OK & b2.state = OK & e2.state = OK);
    
    结果如下:

    NuSMV > reset; read_model -i ns02.smv ; go ; check_property
    ...
    -- specification !(EF ((a2.state = OK & b2.state = OK) & e2.state = OK))  is false
    -- as demonstrated by the following execution sequence
    Trace Description: CTL Counterexample 
    Trace Type: Counterexample 
      -> State: 1.1 <-
        a2.state = IDLE
        a2.action = NONE
        a2.out_1 = NONE
        a2.out_2 = NONE
        a2.out_3 = NONE
        a2.out_k = NONE
        b2.state = IDLE
        b2.action = NONE
        b2.out_1 = NONE
        b2.out_2 = NONE
        b2.out_3 = NONE
        b2.out_k = NONE
        e2.state = IDLE
        e2.action = NONE
        e2.aout_1 = NONE
        e2.aout_2 = NONE
        e2.aout_3 = NONE
        e2.aout_k = NONE
        e2.bout_1 = NONE
        e2.bout_2 = NONE
        e2.bout_3 = NONE
        e2.bout_k = NONE
      -> Input: 1.2 <-
        _process_selector_ = main
        running = TRUE
        e2.running = FALSE
        b2.running = FALSE
        a2.running = FALSE
      -> State: 1.2 <-
        a2.state = WAIT_RESPONSE
        a2.action = SEND_REQUEST
        a2.out_1 = NA
        a2.out_2 = IA
        a2.out_k = KE
      -> Input: 1.3 <-
      -> State: 1.3 <-
        a2.action = NONE
        e2.state = WAIT_RESPONSE
        e2.action = SEND_REQUEST
        e2.bout_1 = NA
        e2.bout_2 = IA
        e2.bout_k = KB
      -> Input: 1.4 <-
      -> State: 1.4 <-
        b2.state = WAIT_CONFIRMATION
        b2.action = SEND_RESPONSE
        b2.out_1 = NA
        b2.out_2 = NB
        b2.out_k = KA
        e2.action = NONE
      -> Input: 1.5 <-
      -> State: 1.5 <-
        b2.action = NONE
        e2.state = WAIT_CONFIRMATION
        e2.action = SEND_RESPONSE
        e2.aout_1 = NA
        e2.aout_2 = NB
        e2.aout_k = KA
        e2.bout_1 = NONE
        e2.bout_2 = NONE
        e2.bout_k = NONE
      -> Input: 1.6 <-
      -> State: 1.6 <-
        a2.state = OK
        a2.action = SEND_CONFIRMATION
        a2.out_1 = NB
        a2.out_2 = NONE
        e2.action = NONE
      -> Input: 1.7 <-
      -> State: 1.7 <-
        a2.action = NONE
        e2.state = OK
        e2.action = SEND_CONFIRMATION
        e2.aout_1 = NONE
        e2.aout_2 = NONE
        e2.aout_k = NONE
        e2.bout_1 = NB
        e2.bout_k = KB
      -> Input: 1.8 <-
      -> State: 1.8 <-
        b2.state = OK
        e2.action = NONE
    
    NuSMV > reset; read_model -i ns03.smv ; go ; check_property             
    ...
    -- specification !(EF ((a3.state = OK & b3.state = OK) & e3.state = OK))  is true
    -- specification !(EF (a3.state = ERROR & b3.state = ERROR))  is false
    -- as demonstrated by the following execution sequence
    Trace Description: CTL Counterexample 
    Trace Type: Counterexample 
      -> State: 1.1 <-
        a3.state = IDLE
        a3.action = NONE
        a3.out_1 = NONE
        a3.out_2 = NONE
        a3.out_3 = NONE
        a3.out_k = NONE
        b3.state = IDLE
        b3.action = NONE
        b3.out_1 = NONE
        b3.out_2 = NONE
        b3.out_3 = NONE
        b3.out_k = NONE
        e3.state = IDLE
        e3.action = NONE
        e3.aout_1 = NONE
        e3.aout_2 = NONE
        e3.aout_3 = NONE
        e3.aout_k = NONE
        e3.bout_1 = NONE
        e3.bout_2 = NONE
        e3.bout_3 = NONE
        e3.bout_k = NONE
      -> Input: 1.2 <-
        _process_selector_ = main
        running = TRUE
        e3.running = FALSE
        b3.running = FALSE
        a3.running = FALSE
      -> State: 1.2 <-
        a3.state = WAIT_RESPONSE
        a3.action = SEND_REQUEST
        a3.out_1 = NA
        a3.out_2 = IA
        a3.out_k = KE
      -> Input: 1.3 <-
      -> State: 1.3 <-
        a3.action = NONE
        e3.state = WAIT_RESPONSE
        e3.action = SEND_REQUEST
        e3.bout_1 = NA
        e3.bout_2 = IA
        e3.bout_k = KB
      -> Input: 1.4 <-
      -> State: 1.4 <-
        b3.state = WAIT_CONFIRMATION
        b3.action = SEND_RESPONSE
        b3.out_1 = NA
        b3.out_2 = NB
        b3.out_3 = IB
        b3.out_k = KA
        e3.action = NONE
      -> Input: 1.5 <-
      -> State: 1.5 <-
        b3.action = NONE
        e3.state = WAIT_CONFIRMATION
        e3.action = SEND_RESPONSE
        e3.aout_1 = NA
        e3.aout_2 = NB
        e3.aout_3 = IB
        e3.aout_k = KA
        e3.bout_1 = NONE
        e3.bout_2 = NONE
        e3.bout_k = NONE
      -> Input: 1.6 <-
      -> State: 1.6 <-
        a3.state = ERROR
        e3.action = NONE
      -> Input: 1.7 <-
      -> State: 1.7 <-
        e3.state = OK
        e3.action = SEND_CONFIRMATION
        e3.aout_1 = NONE
        e3.aout_2 = NONE
        e3.aout_3 = NONE
        e3.aout_k = NONE
        e3.bout_1 = NA
        e3.bout_k = KB
      -> Input: 1.8 <-
      -> State: 1.8 <-a
        b3.state = ERROR
        e3.action = NONE
    
    结果如下:

    NuSMV > reset; read_model -i ns02.smv ; go ; check_property
    ...
    -- specification !(EF ((a2.state = OK & b2.state = OK) & e2.state = OK))  is false
    -- as demonstrated by the following execution sequence
    Trace Description: CTL Counterexample 
    Trace Type: Counterexample 
      -> State: 1.1 <-
        a2.state = IDLE
        a2.action = NONE
        a2.out_1 = NONE
        a2.out_2 = NONE
        a2.out_3 = NONE
        a2.out_k = NONE
        b2.state = IDLE
        b2.action = NONE
        b2.out_1 = NONE
        b2.out_2 = NONE
        b2.out_3 = NONE
        b2.out_k = NONE
        e2.state = IDLE
        e2.action = NONE
        e2.aout_1 = NONE
        e2.aout_2 = NONE
        e2.aout_3 = NONE
        e2.aout_k = NONE
        e2.bout_1 = NONE
        e2.bout_2 = NONE
        e2.bout_3 = NONE
        e2.bout_k = NONE
      -> Input: 1.2 <-
        _process_selector_ = main
        running = TRUE
        e2.running = FALSE
        b2.running = FALSE
        a2.running = FALSE
      -> State: 1.2 <-
        a2.state = WAIT_RESPONSE
        a2.action = SEND_REQUEST
        a2.out_1 = NA
        a2.out_2 = IA
        a2.out_k = KE
      -> Input: 1.3 <-
      -> State: 1.3 <-
        a2.action = NONE
        e2.state = WAIT_RESPONSE
        e2.action = SEND_REQUEST
        e2.bout_1 = NA
        e2.bout_2 = IA
        e2.bout_k = KB
      -> Input: 1.4 <-
      -> State: 1.4 <-
        b2.state = WAIT_CONFIRMATION
        b2.action = SEND_RESPONSE
        b2.out_1 = NA
        b2.out_2 = NB
        b2.out_k = KA
        e2.action = NONE
      -> Input: 1.5 <-
      -> State: 1.5 <-
        b2.action = NONE
        e2.state = WAIT_CONFIRMATION
        e2.action = SEND_RESPONSE
        e2.aout_1 = NA
        e2.aout_2 = NB
        e2.aout_k = KA
        e2.bout_1 = NONE
        e2.bout_2 = NONE
        e2.bout_k = NONE
      -> Input: 1.6 <-
      -> State: 1.6 <-
        a2.state = OK
        a2.action = SEND_CONFIRMATION
        a2.out_1 = NB
        a2.out_2 = NONE
        e2.action = NONE
      -> Input: 1.7 <-
      -> State: 1.7 <-
        a2.action = NONE
        e2.state = OK
        e2.action = SEND_CONFIRMATION
        e2.aout_1 = NONE
        e2.aout_2 = NONE
        e2.aout_k = NONE
        e2.bout_1 = NB
        e2.bout_k = KB
      -> Input: 1.8 <-
      -> State: 1.8 <-
        b2.state = OK
        e2.action = NONE
    
    NuSMV > reset; read_model -i ns03.smv ; go ; check_property             
    ...
    -- specification !(EF ((a3.state = OK & b3.state = OK) & e3.state = OK))  is true
    -- specification !(EF (a3.state = ERROR & b3.state = ERROR))  is false
    -- as demonstrated by the following execution sequence
    Trace Description: CTL Counterexample 
    Trace Type: Counterexample 
      -> State: 1.1 <-
        a3.state = IDLE
        a3.action = NONE
        a3.out_1 = NONE
        a3.out_2 = NONE
        a3.out_3 = NONE
        a3.out_k = NONE
        b3.state = IDLE
        b3.action = NONE
        b3.out_1 = NONE
        b3.out_2 = NONE
        b3.out_3 = NONE
        b3.out_k = NONE
        e3.state = IDLE
        e3.action = NONE
        e3.aout_1 = NONE
        e3.aout_2 = NONE
        e3.aout_3 = NONE
        e3.aout_k = NONE
        e3.bout_1 = NONE
        e3.bout_2 = NONE
        e3.bout_3 = NONE
        e3.bout_k = NONE
      -> Input: 1.2 <-
        _process_selector_ = main
        running = TRUE
        e3.running = FALSE
        b3.running = FALSE
        a3.running = FALSE
      -> State: 1.2 <-
        a3.state = WAIT_RESPONSE
        a3.action = SEND_REQUEST
        a3.out_1 = NA
        a3.out_2 = IA
        a3.out_k = KE
      -> Input: 1.3 <-
      -> State: 1.3 <-
        a3.action = NONE
        e3.state = WAIT_RESPONSE
        e3.action = SEND_REQUEST
        e3.bout_1 = NA
        e3.bout_2 = IA
        e3.bout_k = KB
      -> Input: 1.4 <-
      -> State: 1.4 <-
        b3.state = WAIT_CONFIRMATION
        b3.action = SEND_RESPONSE
        b3.out_1 = NA
        b3.out_2 = NB
        b3.out_3 = IB
        b3.out_k = KA
        e3.action = NONE
      -> Input: 1.5 <-
      -> State: 1.5 <-
        b3.action = NONE
        e3.state = WAIT_CONFIRMATION
        e3.action = SEND_RESPONSE
        e3.aout_1 = NA
        e3.aout_2 = NB
        e3.aout_3 = IB
        e3.aout_k = KA
        e3.bout_1 = NONE
        e3.bout_2 = NONE
        e3.bout_k = NONE
      -> Input: 1.6 <-
      -> State: 1.6 <-
        a3.state = ERROR
        e3.action = NONE
      -> Input: 1.7 <-
      -> State: 1.7 <-
        e3.state = OK
        e3.action = SEND_CONFIRMATION
        e3.aout_1 = NONE
        e3.aout_2 = NONE
        e3.aout_3 = NONE
        e3.aout_k = NONE
        e3.bout_1 = NA
        e3.bout_k = KB
      -> Input: 1.8 <-
      -> State: 1.8 <-a
        b3.state = ERROR
        e3.action = NONE
    
    NuSMV>reset;read_model-i ns03.smv;去;检查属性
    ...
    --规格!(EF((a3.state=OK&b3.state=OK)和e3.state=OK))为真
    --规格!(EF(a3.state=ERROR&b3.state=ERROR))为false
    --如下面的执行顺序所示
    跟踪描述:CTL反例
    跟踪类型:计数器示例
    
    NuSMV > reset; read_model -i ns02.smv ; go ; check_property
    ...
    -- specification !(EF ((a2.state = OK & b2.state = OK) & e2.state = OK))  is false
    -- as demonstrated by the following execution sequence
    Trace Description: CTL Counterexample 
    Trace Type: Counterexample 
      -> State: 1.1 <-
        a2.state = IDLE
        a2.action = NONE
        a2.out_1 = NONE
        a2.out_2 = NONE
        a2.out_3 = NONE
        a2.out_k = NONE
        b2.state = IDLE
        b2.action = NONE
        b2.out_1 = NONE
        b2.out_2 = NONE
        b2.out_3 = NONE
        b2.out_k = NONE
        e2.state = IDLE
        e2.action = NONE
        e2.aout_1 = NONE
        e2.aout_2 = NONE
        e2.aout_3 = NONE
        e2.aout_k = NONE
        e2.bout_1 = NONE
        e2.bout_2 = NONE
        e2.bout_3 = NONE
        e2.bout_k = NONE
      -> Input: 1.2 <-
        _process_selector_ = main
        running = TRUE
        e2.running = FALSE
        b2.running = FALSE
        a2.running = FALSE
      -> State: 1.2 <-
        a2.state = WAIT_RESPONSE
        a2.action = SEND_REQUEST
        a2.out_1 = NA
        a2.out_2 = IA
        a2.out_k = KE
      -> Input: 1.3 <-
      -> State: 1.3 <-
        a2.action = NONE
        e2.state = WAIT_RESPONSE
        e2.action = SEND_REQUEST
        e2.bout_1 = NA
        e2.bout_2 = IA
        e2.bout_k = KB
      -> Input: 1.4 <-
      -> State: 1.4 <-
        b2.state = WAIT_CONFIRMATION
        b2.action = SEND_RESPONSE
        b2.out_1 = NA
        b2.out_2 = NB
        b2.out_k = KA
        e2.action = NONE
      -> Input: 1.5 <-
      -> State: 1.5 <-
        b2.action = NONE
        e2.state = WAIT_CONFIRMATION
        e2.action = SEND_RESPONSE
        e2.aout_1 = NA
        e2.aout_2 = NB
        e2.aout_k = KA
        e2.bout_1 = NONE
        e2.bout_2 = NONE
        e2.bout_k = NONE
      -> Input: 1.6 <-
      -> State: 1.6 <-
        a2.state = OK
        a2.action = SEND_CONFIRMATION
        a2.out_1 = NB
        a2.out_2 = NONE
        e2.action = NONE
      -> Input: 1.7 <-
      -> State: 1.7 <-
        a2.action = NONE
        e2.state = OK
        e2.action = SEND_CONFIRMATION
        e2.aout_1 = NONE
        e2.aout_2 = NONE
        e2.aout_k = NONE
        e2.bout_1 = NB
        e2.bout_k = KB
      -> Input: 1.8 <-
      -> State: 1.8 <-
        b2.state = OK
        e2.action = NONE
    
    MODULE main
    VAR
        a3 : process user(TRUE, NA, IA, KA, KE, IE, e3.aout_1, e3.aout_2, e3.aout_3, e3.aout_k);
        b3 : process user(TRUE, NB, IB, KB, KA, IA, e3.bout_1, e3.bout_2, e3.bout_3, e3.bout_k);
        e3 : process attacker(NE, IE, KE, KA, KB,
                              a3.out_1, a3.out_2, a3.out_3, a3.out_k,
                              b3.out_1, b3.out_2, b3.out_3, b3.out_k);
    
    FAIRNESS running;
    
    
    CTLSPEC ! EF (a3.state = OK & b3.state = OK & e3.state = OK);
    CTLSPEC ! EF (a3.state = ERROR & b3.state = ERROR);
    
    NuSMV > reset; read_model -i ns03.smv ; go ; check_property             
    ...
    -- specification !(EF ((a3.state = OK & b3.state = OK) & e3.state = OK))  is true
    -- specification !(EF (a3.state = ERROR & b3.state = ERROR))  is false
    -- as demonstrated by the following execution sequence
    Trace Description: CTL Counterexample 
    Trace Type: Counterexample 
      -> State: 1.1 <-
        a3.state = IDLE
        a3.action = NONE
        a3.out_1 = NONE
        a3.out_2 = NONE
        a3.out_3 = NONE
        a3.out_k = NONE
        b3.state = IDLE
        b3.action = NONE
        b3.out_1 = NONE
        b3.out_2 = NONE
        b3.out_3 = NONE
        b3.out_k = NONE
        e3.state = IDLE
        e3.action = NONE
        e3.aout_1 = NONE
        e3.aout_2 = NONE
        e3.aout_3 = NONE
        e3.aout_k = NONE
        e3.bout_1 = NONE
        e3.bout_2 = NONE
        e3.bout_3 = NONE
        e3.bout_k = NONE
      -> Input: 1.2 <-
        _process_selector_ = main
        running = TRUE
        e3.running = FALSE
        b3.running = FALSE
        a3.running = FALSE
      -> State: 1.2 <-
        a3.state = WAIT_RESPONSE
        a3.action = SEND_REQUEST
        a3.out_1 = NA
        a3.out_2 = IA
        a3.out_k = KE
      -> Input: 1.3 <-
      -> State: 1.3 <-
        a3.action = NONE
        e3.state = WAIT_RESPONSE
        e3.action = SEND_REQUEST
        e3.bout_1 = NA
        e3.bout_2 = IA
        e3.bout_k = KB
      -> Input: 1.4 <-
      -> State: 1.4 <-
        b3.state = WAIT_CONFIRMATION
        b3.action = SEND_RESPONSE
        b3.out_1 = NA
        b3.out_2 = NB
        b3.out_3 = IB
        b3.out_k = KA
        e3.action = NONE
      -> Input: 1.5 <-
      -> State: 1.5 <-
        b3.action = NONE
        e3.state = WAIT_CONFIRMATION
        e3.action = SEND_RESPONSE
        e3.aout_1 = NA
        e3.aout_2 = NB
        e3.aout_3 = IB
        e3.aout_k = KA
        e3.bout_1 = NONE
        e3.bout_2 = NONE
        e3.bout_k = NONE
      -> Input: 1.6 <-
      -> State: 1.6 <-
        a3.state = ERROR
        e3.action = NONE
      -> Input: 1.7 <-
      -> State: 1.7 <-
        e3.state = OK
        e3.action = SEND_CONFIRMATION
        e3.aout_1 = NONE
        e3.aout_2 = NONE
        e3.aout_3 = NONE
        e3.aout_k = NONE
        e3.bout_1 = NA
        e3.bout_k = KB
      -> Input: 1.8 <-
      -> State: 1.8 <-a
        b3.state = ERROR
        e3.action = NONE