</COMMENT>
/*
	Rsa.java - Cory Goldfuss - November 05, 2000
	Program allows input of two prime numbers in order to find
	a public and private key to allow for the encryption or decrpyion
	of a letter.
	----------------------------------------------
	November 12, 2000
	Found out that by using the Math.pow() call the computer rounds the 
	large numbers when it converts into scientific notation.  Therefore I 
	implemented code that did the same thing as the Math.pow(), but within
	the constraints of the language.  I also implemented new code for 
	calculating D, where D is used in the decryption process.  D is the inverse
	of e mod phi.  Both of these new implementations were translated from code 
	obtained from Steve Harnish.
	Program now works correctly.....I've test large primes (greater than 50 billion)
	and have yet to see it work when these large primes are used.  The program 
	seems to "think" for a long time.  I have yet to discover how long it is 
	actually going to take before it arrives at an answer.
        ------------------------------------------------
        November 13, 2000
        Finished GUI and added radio buttons.  Program never finished computer when
        using large primes.
*/

import java.awt.*;
import java.applet.*;
import java.awt.event.*;


public class Rsa extends Applet implements ActionListener, ItemListener
{
    public double p; // prime one
    public double q; // prime two
    public double n; // p * q
    public double d; // a derived in A * x + B * y = 0 (from extended Euclidean)
    public double exp; // compiler doesn't like use of letter e for variable
    public double t; // object to be crypted
    public double phi;
    public double encrypted;
    public double decrypted;
    private boolean pFlag = false;
    private boolean qFlag = false;
    private boolean tFlag = false;
    private boolean eFlag = false;
  
    
	public void init()
	{
		// Take out this line if you don't use symantec.itools.net.RelativeURL or                    symantec.itools.awt.util.StatusScroller
		//symantec.itools.lang.Context.setApplet(this);
	
		// This code is automatically generated by Visual Cafe when you add
		// components to the visual environment. It instantiates and initializes
		// the components. To modify the code, only use code syntax that matches
		// what Visual Cafe can generate, or Visual Cafe may be unable to back
		// parse your Java file into its visual environment.
		//{{INIT_CONTROLS
		setLayout(null);
		setBackground(java.awt.Color.lightGray);
		setSize(426,368);
		pLbl.setText("P");
		pLbl.setAlignment(java.awt.Label.CENTER);
		add(pLbl);
		pLbl.setBackground(java.awt.Color.white);
		pLbl.setFont(new Font("Dialog", Font.BOLD, 12));
		pLbl.setBounds(12,24,33,26);
		add(pBox);
		pBox.setBounds(48,24,120,24);
		qLbl.setText("Q");
		qLbl.setAlignment(java.awt.Label.CENTER);
		add(qLbl);
		qLbl.setBackground(java.awt.Color.white);
		qLbl.setFont(new Font("Dialog", Font.BOLD, 12));
		qLbl.setBounds(12,60,33,26);
		add(qBox);
		qBox.setBounds(48,60,120,24);
		eLbl.setText("E");
		eLbl.setAlignment(java.awt.Label.CENTER);
		add(eLbl);
		eLbl.setBackground(java.awt.Color.white);
		eLbl.setFont(new Font("Dialog", Font.BOLD, 12));
		eLbl.setBounds(216,24,33,26);
		add(eBox);
		eBox.setBounds(252,24,120,24);
		tLbl.setText("T");
		tLbl.setAlignment(java.awt.Label.CENTER);
		add(tLbl);
		tLbl.setBackground(java.awt.Color.white);
		tLbl.setFont(new Font("Dialog", Font.BOLD, 12));
		tLbl.setBounds(216,60,33,26);
		add(tBox);
		tBox.setBounds(252,60,120,24);
		phiLbl.setText("PHI");
		phiLbl.setAlignment(java.awt.Label.CENTER);
		add(phiLbl);
		phiLbl.setBackground(java.awt.Color.white);
		phiLbl.setFont(new Font("Dialog", Font.BOLD, 12));
		phiLbl.setBounds(12,108,36,24);
		add(phianswerLbl);
		phianswerLbl.setBounds(48,108,84,23);
		nLbl.setText("N");
		nLbl.setAlignment(java.awt.Label.CENTER);
		add(nLbl);
		nLbl.setBackground(java.awt.Color.white);
		nLbl.setFont(new Font("Dialog", Font.BOLD, 12));
		nLbl.setBounds(12,144,33,26);
		add(nanswerLbl);
		nanswerLbl.setBounds(48,144,84,23);
		phihelpLbl.setText("PHI = (P-1) * (Q-1)");
		add(phihelpLbl);
		phihelpLbl.setBounds(132,108,108,24);
		nhelpLbl.setText("N = P * Q");
		add(nhelpLbl);
		nhelpLbl.setBounds(132,144,108,24);
		dLbl.setText("D");
		dLbl.setAlignment(java.awt.Label.CENTER);
		add(dLbl);
		dLbl.setBackground(java.awt.Color.white);
		dLbl.setFont(new Font("Dialog", Font.BOLD, 12));
		dLbl.setBounds(12,180,33,26);
		add(danswerLbl);
		danswerLbl.setBounds(48,180,84,23);
		enteredtLbl.setText("Original T:");
		enteredtLbl.setAlignment(java.awt.Label.CENTER);
		add(enteredtLbl);
		enteredtLbl.setBackground(java.awt.Color.orange);
		enteredtLbl.setBounds(12,216,84,24);
		add(tanswerLbl);
		tanswerLbl.setBackground(java.awt.Color.white);
		tanswerLbl.setBounds(108,216,108,24);
		encryptLbl.setText("Encrypted T:");
		encryptLbl.setAlignment(java.awt.Label.CENTER);
		add(encryptLbl);
		encryptLbl.setBackground(java.awt.Color.orange);
		encryptLbl.setBounds(12,264,84,24);
		encryptLbl.setVisible(false);
		add(encryptanswerLbl);
		encryptanswerLbl.setBackground(java.awt.Color.white);
		encryptanswerLbl.setBounds(108,264,108,24);
		encryptanswerLbl.setVisible(false);
		decryptLbl.setText("Decrypted T:");
		decryptLbl.setAlignment(java.awt.Label.CENTER);
		add(decryptLbl);
		decryptLbl.setBackground(java.awt.Color.orange);
		decryptLbl.setBounds(12,312,84,24);
		decryptLbl.setVisible(false);
		add(decryptanswerLbl);
		decryptanswerLbl.setBackground(java.awt.Color.white);
		decryptanswerLbl.setBounds(108,312,108,24);
		decryptanswerLbl.setVisible(false);
		rstBtn.setLabel("Reset");
		add(rstBtn);
		rstBtn.setBackground(java.awt.Color.blue);
		rstBtn.setForeground(java.awt.Color.white);
		rstBtn.setBounds(348,300,60,24);
		dhelpLbl.setText("D = (E mod PHI) ^ -1");
		add(dhelpLbl);
		dhelpLbl.setBounds(132,180,120,24);
		radioEncrypt.setCheckboxGroup(Crypto);
		radioEncrypt.setLabel("Encrypt");
		add(radioEncrypt);
		radioEncrypt.setBounds(300,132,72,28);
		radioDecrypt.setCheckboxGroup(Crypto);
		radioDecrypt.setLabel("Decrypt");
		add(radioDecrypt);
		radioDecrypt.setBounds(300,156,96,28);
		instructionsTextArea.setEditable(false);
		instructionsTextArea.setText("Process:  Enter two large primes (P and Q).T is the message block to be altered.  E is either already known or chosen to be relatively prime to N (where N = P * Q).  After these are ALL entered, select either Encrypt or Decrypt  using the radio buttons and then press the appropiate button below.  Note:  To check and see that the encrypted block is the same as the decrypted, you must first encrypt the block and then enter this value in T before selecting the Decrypt option.");
		add(instructionsTextArea);
		instructionsTextArea.setBounds(240,204,180,85);
		encryptBtn.setLabel("Encrypt");
		add(encryptBtn);
		encryptBtn.setBackground(java.awt.Color.blue);
		encryptBtn.setForeground(java.awt.Color.white);
		encryptBtn.setBounds(240,300,60,24);
		encryptBtn.setVisible(false);
		decryptBtn.setLabel("Decrypt");
		add(decryptBtn);
		decryptBtn.setBackground(java.awt.Color.blue);
		decryptBtn.setForeground(java.awt.Color.white);
		decryptBtn.setBounds(240,336,60,24);
		decryptBtn.setVisible(false);
		//}}
		pBox.addActionListener( this );
	    qBox.addActionListener( this );
	    tBox.addActionListener( this );
	    eBox.addActionListener( this );
	    rstBtn.addActionListener( this );
	    encryptBtn.addActionListener( this );
	    decryptBtn.addActionListener( this );
	    radioEncrypt.addItemListener( this );
	    radioDecrypt.addItemListener( this );
	    
	}
	
	//{{DECLARE_CONTROLS
	java.awt.Label pLbl = new java.awt.Label();
	java.awt.TextField pBox = new java.awt.TextField();
	java.awt.Label qLbl = new java.awt.Label();
	java.awt.TextField qBox = new java.awt.TextField();
	java.awt.Label eLbl = new java.awt.Label();
	java.awt.TextField eBox = new java.awt.TextField();
	java.awt.Label tLbl = new java.awt.Label();
	java.awt.TextField tBox = new java.awt.TextField();
	java.awt.Label phiLbl = new java.awt.Label();
	java.awt.Label phianswerLbl = new java.awt.Label();
	java.awt.Label nLbl = new java.awt.Label();
	java.awt.Label nanswerLbl = new java.awt.Label();
	java.awt.Label phihelpLbl = new java.awt.Label();
	java.awt.Label nhelpLbl = new java.awt.Label();
	java.awt.Label dLbl = new java.awt.Label();
	java.awt.Label danswerLbl = new java.awt.Label();
	java.awt.Label enteredtLbl = new java.awt.Label();
	java.awt.Label tanswerLbl = new java.awt.Label();
	java.awt.Label encryptLbl = new java.awt.Label();
	java.awt.Label encryptanswerLbl = new java.awt.Label();
	java.awt.Label decryptLbl = new java.awt.Label();
	java.awt.Label decryptanswerLbl = new java.awt.Label();
	java.awt.Button rstBtn = new java.awt.Button();
	java.awt.Label dhelpLbl = new java.awt.Label();
	java.awt.Checkbox radioEncrypt = new java.awt.Checkbox();
	java.awt.CheckboxGroup Crypto = new java.awt.CheckboxGroup();
	java.awt.Checkbox radioDecrypt = new java.awt.Checkbox();
	java.awt.TextArea instructionsTextArea = new         java.awt.TextArea("",0,0,TextArea.SCROLLBARS_VERTICAL_ONLY);
	java.awt.Button encryptBtn = new java.awt.Button();
	java.awt.Button decryptBtn = new java.awt.Button();
	//}}
	
	public void actionPerformed( ActionEvent e ){
	 
	if (e.getSource() == encryptBtn){ // encrypt
	   
	    /* Turn off decryption labels */
	    decryptLbl.setVisible( false );
        decryptanswerLbl.setVisible( false );
	        
	   /* Encrypt Entered T */
       encrypted = powerMod( t, exp, n );  
       encryptanswerLbl.setText(Double.toString(encrypted));
       encryptLbl.setVisible( true );
       encryptanswerLbl.setVisible( true );
	}
	
	if (e.getSource() == decryptBtn){
	    
	    /* Turn off encryption labels */
	    encryptLbl.setVisible( false );
        encryptanswerLbl.setVisible( false );
	    
	    /* Decrpyt Message */
        decrypted = powerMod( t, d, n );
        decryptLbl.setVisible( true );
        decryptanswerLbl.setVisible( true );
        decryptanswerLbl.setText(Double.toString(decrypted));
    }
	    
	    
	if (e.getSource() == rstBtn){ // reset all inputs and labels
	    encryptLbl.setVisible( false );
        encryptanswerLbl.setVisible( false );
        decryptLbl.setVisible( false );
        decryptanswerLbl.setVisible( false );
	    pBox.setText("");
	    qBox.setText("");
	    eBox.setText("");
	    tBox.setText("");
	    pFlag = false;
	    eFlag = false;
	    tFlag = false;
	    qFlag = false;
	    n = 0;
	    phi = 0;
	    exp = 0;
	    t = 0;
	    p = 0;
	    q = 0;
	    d = 0;
	    encrypted = 0;
	    decrypted = 0;
	    encryptBtn.setVisible( false );
	    decryptBtn.setVisible( false );
	    nanswerLbl.setText(Double.toString(n));
        phianswerLbl.setText(Double.toString(phi));
        danswerLbl.setText(Double.toString(d));
        tanswerLbl.setText(Double.toString(t));
        encryptanswerLbl.setText(Double.toString(encrypted));
        decryptanswerLbl.setText(Double.toString(decrypted));
        
    }
	    
	if (e.getSource() == pBox){
        p = Double.parseDouble( e.getActionCommand() );
        pFlag = true;
    }
    
    if (e.getSource() == qBox){
        q = Double.parseDouble( e.getActionCommand() );
        qFlag = true;
    }
    if (e.getSource() == tBox){
        t = Double.parseDouble( e.getActionCommand() );
        tFlag = true;
    }
    if (e.getSource() == eBox){
        exp = Double.parseDouble( e.getActionCommand() );
        eFlag = true;
    }
    
    if (pFlag && qFlag && eFlag && tFlag == true){ // received all input from user
        n = p * q;
        phi = ((p-1) * (q-1));
        d = Inverse( exp, phi);
        nanswerLbl.setText(Double.toString(n));
        phianswerLbl.setText(Double.toString(phi));
        danswerLbl.setText(Double.toString(d));
        tanswerLbl.setText(Double.toString(t));
                      
    }
    
  } // end action command
  
  public void itemStateChanged( ItemEvent e ){
      String choice = e.getItem().toString();
	   	    
	if ( choice.equalsIgnoreCase( "Encrypt" ) ){
	    decryptLbl.setVisible( false );
        decryptanswerLbl.setVisible( false );
        
	    encryptBtn.setVisible( true );
	    decryptBtn.setVisible( false );
	}
	if ( choice.equalsIgnoreCase( "Decrypt" ) ){
	    encryptLbl.setVisible( false );
        encryptanswerLbl.setVisible( false );
        
        decryptBtn.setVisible( true );
	    encryptBtn.setVisible( false );
	}
	

  } // item listener
  
  
  
  /* Both functions are used to overcome rounding error */
  
  /* To give A^B modulo M */
  
  private double powerMod( double a, double b, double m ){ 	
    double answer = 1;
	for (int i = 1; i <= b; i++){
		answer = ((a * answer) % m);
	}
	return( answer );
  }

    
    
  /* To give the inverse of X modulo M */
    
  private double Inverse( double x, double m ){  
    double answer = 0;
    
	for(int i = 1; i <= ( m - 1 ); i++){
	    if ( ( (x * i) % m ) == 1 ){
	        answer = i;
	    }
	    else{
	        continue;
	    }
	}
	return( answer );
  }

}

\