/*
 * WideMouthFrog.java
 * INCORRECT MODEL
 * Created on 16 November 2005, 11:13
 *
 */
import java.util.Vector;
import javax.crypto.*;
/**
 *
 * @author Nicholas O'Shea
 */
public class WideMouthFrog3 extends KeyGenerationClass {
    public static void main(String[] args) {      
        
        // Set Up Principal Classes
        Network net = new Network();
        A3 a = new A3(net);
        net.register("A", a);
        B3 b = new B3(net);
        net.register("B", b);
        S3 s = new S3(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 A3 extends ComClass {
    Network net;
    
    
    public A3 (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");       
        
       
        // Message to S
        Vector v = new Vector();
        v.add("A");
        v.add("B");
        v.add(sendKey(keyAB));
        
        // 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 B3 extends ComClass {
    Network net;
    
    public B3 (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), "S");
                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 S3 extends ComClass {
    Network e;
    
    public S3 (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 four elements of message
                assert check(v.elementAt(0), "A");
                assert check(v.elementAt(1), "S");
                assert check(v.elementAt(2), "A");
                assert check(v.elementAt(3), "B"); 
                //Assign fourth element of string
                String keyRepresentation = v.elementAt(4);
                
                //------------------------------------------------------------
                // 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++;
    }
}