// Arup Guha
// A short utility program used to show how to reproduce the chart on page
// 91 of the Stinson book. Essentially, given a particular input xor, this
// chart shows which inputs correspond to which output xors.

import java.io.*;
import java.util.Vector;

public class sboxinfo {

  public static void main(String[] args) throws IOException {

    // Values in the first sbox.
    int sbox1[] = {14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7,
                   0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8,
                   4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0,
                   15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13};


    int testxor = 52; // Test value used in the text.

    // Use an array of vectors to store the chart.
    Vector table[] = new Vector[16];
    for (int i=0; i<16;i++)
      table[i] = new Vector();

    // Loop through each possible input.
    for (int i=0; i<64; i++) {

      int xori = i ^ testxor; // Calculate the corresponding pair.

      // Calculate the output of the sbox for both values.
      int ans1 = sbox(i,sbox1);
      int ans2 = sbox(xori,sbox1);

      // Calculate the output xor, and store i in the proper location in
      // the table.
      int outxor = ans1 ^ ans2;
      table[outxor].addElement(new Integer(i));
    }

    // This prints out the chart in a readable format.
    for (int i=0; i<16; i++) {

      System.out.print(i+"\t"); // Print the row number.

      int j;
      // Loop through the elements in row i.
      for (j=0; j<table[i].size()-1; j++) {
        System.out.print(binrep((Integer)table[i].elementAt(j))+", ");

        // Go to the next line so that the line isn't too long.
        if (j==7)
          System.out.print("\n\t");
      }

      // Makes sure that a comma isn't outputted for the last row value.
      if (table[i].size() != 0)
        System.out.print(binrep((Integer)table[i].elementAt(j)));
      System.out.println();
    }
  }

  // Given the input value and the appropriate sbox stored in an array
  // of size 64, the appropriate s-box output value is returned.
  public static int sbox(int input, int[] box) {
    int row = 2*(input/32)+input%2;
    int col = (input/2)%16;
    return box[row*16+col];
  }

  // Outputs the Integer n in a six-bit binary representation.
  public static String binrep(Integer n) {
    int nval = n.intValue();
    String temp = new String();
    for (int i=0; i<6; i++) {
      if (nval%2 == 1)
        temp = "1" + temp;
      else
        temp = "0" + temp;
      nval /= 2;
    }
    return temp;
  }
}
