// Arup Guha
// 6/23/04
// A class that manages polynomial operations in the field used in AES.
// Only those operations necessary for AES are supported.

import java.io.*;

public class AESpoly {

  private int value;

  // Creates an AES poly object, byte unsigns if necessary.
  public AESpoly(int v) {
    value = v;
    if (value < 0) value+=256;
  }

  // Uses only the first two characters. Defaults to 00.
  public AESpoly(String hex) {
    value = 16*AES.hexVal(hex.charAt(0))+AES.hexVal(hex.charAt(1));    
  }

  // Takes the current object and multiplies it by x, and returns the 
  // resulting AES poly.
  public AESpoly multX() {

    int newval; // Stores the value of the new AESpoly.

    // Take care of the easy case.
    if (value < 128)
      newval = 2*value;

    // This is the case where the msb = 1.
    else
      newval = (2*(value & 127)) ^ 27;

    return new AESpoly(newval); // Return the answer.
  }

  // Multiply the current AES poly by x^n.
  public AESpoly multXPow(int n) {

    AESpoly temp = new AESpoly(value); // Store the answer in temp.

    // Multiply temp by x n times and store the answer in temp
    for (int i=0; i<n; i++)
      temp = temp.multX();

    return temp; // Return the answer.
  }

  // Multiply the current object by p and return the result.
  public AESpoly mult(AESpoly p) {

    AESpoly ans = new AESpoly(0); // Store the answer here.

    int pval = p.value; // Store the int value of p here.

    // Multiply each appropriate power of x by the current object and
    // add that into ans.
    int exp=0;
    while (pval > 0) {

      if (pval%2 == 1) // Checks to see if that power of x is in p.
        ans = ans.add(multXPow(exp));

      pval /= 2; // Advance to the next higher bit of p.

      exp++; // Keep track of the current exponent.
    } 
    return ans; // Return the answer.
  }

  // Adds p to the current object and returns the answer.
  public AESpoly add(AESpoly p) {
    return new AESpoly(value ^ p.value);
  }
 
  // Returns a String representation of the current object.
  public String toString() {
    char[] vals = new char[2];
    vals[0] = AES.convToHex(value/16);
    vals[1] = AES.convToHex(value%16);
    return new String(vals);
  }

  // Returns the integer value of the current object.
  public int getVal() {
    return value;
  }

}
