/*
 * WideMouthFrog2.java
 * FAILS AT PATTERN-MATCHING
 * Created on 16 November 2005, 11:13
 *
 */
import java.util.Vector;
import javax.crypto.*;
/**
 *
 * @author Nicholas O'Shea
 */
public class WideMouthFrog2 extends KeyGenerationClass {
    public static void main(String[] args) {      
        
        // Set Up Principal Classes
        Network net = new Network();
        A2 a = new A2(net);
        net.register("A", a);
        B2 b = new B2(net);
        net.register("B", b);
        S2 s = new S2(net);
        net.register("S", s);
                        
        // Share Keys
        SecretKey keyA = generateSharedKey();
        SecretKey keyB = generateSharedKey();
        
        a.shareKey(keyA, "KAS");
        s.shareKey(keyA, "KAS");
        b.shareKey(keyB, "KBS");
        s.shareKey(keyB, "KBS");
        
        // Start Principals
        a.start();
        b.start();
        s.start();
    }
}

class A2 extends ComClass {
    Network net;
    
    
    public A2 (Network net){
        this.net = net;
    }
    
    public void  run(){
        
        //Generate key for communication between A and B
        SecretKey keyAB = generateSharedKey();
        SecretKey keyAS = (SecretKey) keys.get("KAS");
        registerKey(keyAB, "K");       
        
        //Encoded part of message to S
        Vector vEncoded = new Vector();
        vEncoded.add("B");
        vEncoded.add(sendKey(keyAB));
        
        // Message to S
        Vector v = new Vector();
        v.add("A");
        v.add(encrypt(vEncoded, keyAS, "a1", "s1"));
        
        // Send message to S
        net.send(this, "S", v);
        
        //------------------------------------------------------------------
        
        // Encoded part of message to B
        Vector vBEncoded = new Vector();
        String msg1 = generateMessage("FIRST BIT OF MESSAGE");
        String msg2 = generateMessage("SECOND BIT OF MESSAGE");
        vBEncoded.add(msg1);
        vBEncoded.add(msg2);
        
        // Message to B
        Vector vB = new Vector();
        vB.add(encrypt(vBEncoded, keyAB, "a2", "b2"));
        net.send(this, "B", vB);

    }
    
    public void processIncoming(Vector v){
        switch (receivedNum) {
            case 0 :
                // Nothing needed, A never receives a message
        }
    }
    
}
class B2 extends ComClass {
    Network net;
    
    public B2 (Network e){
        this.e = e;
    }  
    
    public void processIncoming(Vector<String> v){
        switch (receivedNum) {
            case 0:
                // Retrieve  key for decryption of message
                SecretKey key = (SecretKey) keys.get("KBS");
                
                // check first & second elements of message
                assert check(v.elementAt(0), "FAILUREHERE");
                assert check(v.elementAt(1), "B");
                
                 // assign third element of message
                String msgToBeDecoded = v.elementAt(2);
                // Decrypt string
                Vector<String> decode = decrypt(msgToBeDecoded, key, "b1", "s2");
                
                // Check first element of decrypted message
                assert check(decode.elementAt(0), "A");
                // Assign second element as a secret key
                SecretKey keyAB = receiveSecretKey(decode.elementAt(1));
                registerKey(keyAB, "KAB");
                
                break;
           case 1:
                // Retrieve  key for decryption of message
                SecretKey key2 = (SecretKey)keys.get("KAB");
               
                // check first & second elements of message
                assert check(v.elementAt(0), "A");
                assert check(v.elementAt(1), "B");
                
                // assign third element of message
                String msgToBeDecoded2 = v.elementAt(2);
                // Decrypt string
                Vector<String> decode2 = decrypt(msgToBeDecoded2, key2, "b2", "a2");

                // Assign first 2 elements of decrypted message and print them to console
                String msg1 = decode2.elementAt(0);
                String msg2 = decode2.elementAt(1);
                theLogger.info(msg1);
                theLogger.info(msg2);
        }
        receivedNum++;
    }
}
class S2 extends ComClass {
    Network e;
    
    public S2 (Network e){
        this.e = e;
    }  
    
    public void processIncoming(Vector<String> v){
        switch (receivedNum) {
            case 0:
                // Retrieve  key for decryption of message
                SecretKey key = (SecretKey) keys.get("KAS");
                
                // check first three elements of message
                assert check(v.elementAt(0), "A");
                assert check(v.elementAt(1), "S");
                assert check(v.elementAt(2), "A");
                
                //Assign fourth element of string
                String msgToBeDecoded = v.elementAt(3);
                
                //Descrypt string
                Vector<String> decode = decrypt(msgToBeDecoded, key, "s1", "a1");
                
                //check first element of decrypted message
                assert check(decode.elementAt(0), "B");
                //assign second of element of decrypted message
                String keyRepresentation = decode.elementAt(1);
                
                //------------------------------------------------------------
                // Generate encrypted portion of message to B
                Vector vToBEnc = new Vector();
                vToBEnc.add("A");
                vToBEnc.add(keyRepresentation);
                
                // Message to B
                Vector vToB = new Vector();
                SecretKey key2 = (SecretKey) keys.get("KBS");
                vToB.add(encrypt(vToBEnc, key2, "s2", "b1"));
                e.send(this, "B", vToB);
                
                break;
        }
        receivedNum++;
    }
}