Example #1
0
 /** diagnostic trace of static tables. */
 public static void trace_static() {
   int i, j;
   System.out.print("AES Static Tablesn");
   System.out.print("S[] = n");
   for (i = 0; i < 16; i++) {
     for (j = 0; j < 16; j++) System.out.print(Util.toHEX1(S[i * 16 + j]) + ", ");
     System.out.println();
   }
   System.out.print("Si[] = n");
   for (i = 0; i < 16; i++) {
     for (j = 0; j < 16; j++) System.out.print(Util.toHEX1(Si[i * 16 + j]) + ", ");
     System.out.println();
   }
   System.out.print("rcon[] = n");
   for (i = 0; i < 5; i++) {
     for (j = 0; j < 6; j++) System.out.print(Util.toHEX1(rcon[i * 6 + j]) + ", ");
     System.out.println();
   }
   System.out.print("log[] = n");
   for (i = 0; i < 32; i++) {
     for (j = 0; j < 8; j++) System.out.print(Util.toHEX1(log[i * 8 + j]) + ", ");
     System.out.println();
   }
   System.out.print("alog[] = n");
   for (i = 0; i < 32; i++) {
     for (j = 0; j < 8; j++) System.out.print(Util.toHEX1(alog[i * 8 + j]) + ", ");
     System.out.println();
   }
 }
Example #2
0
  /**
   * Expand a user-supplied key material into a session key.
   *
   * <p>See FIPS-197 Section 5.3 Fig 11 for details of the key expansion.
   *
   * <p>Session keys will be saved in Ke and Kd instance variables, along with numRounds being the
   * number of rounds for this sized key.
   *
   * @param key The 128/192/256-bit AES key to use.
   */
  @SuppressWarnings("unused")
  public void setKey(byte[] key) {
    // assorted internal constants
    final int BC = BLOCK_SIZE / 4;
    final int Klen = key.length;
    final int Nk = Klen / 4;

    int i, j, r;

    traceInfo = ""; // reset trace info
    if (traceLevel > 0) traceInfo = "setKey(" + Util.toHEX1(key) + ")n";

    // check for bad arguments
    if (key == null) throw new IllegalArgumentException("Empty key");
    if (!(key.length == 16 || key.length == 24 || key.length == 32))
      throw new IllegalArgumentException("Incorrect key length");

    // set master number of rounds given size of this key
    numRounds = getRounds(Klen);
    final int ROUND_KEY_COUNT = (numRounds + 1) * BC;

    // allocate 4 arrays of bytes to hold the session key values
    // each array holds 1 of the 4 bytes [b0 b1 b2 b3] in each word w
    byte[] w0 = new byte[ROUND_KEY_COUNT];
    byte[] w1 = new byte[ROUND_KEY_COUNT];
    byte[] w2 = new byte[ROUND_KEY_COUNT];
    byte[] w3 = new byte[ROUND_KEY_COUNT];

    // allocate arrays to hold en/decrypt session keys (by byte rather than word)
    Ke = new byte[numRounds + 1][BLOCK_SIZE]; // encryption round keys
    Kd = new byte[numRounds + 1][BLOCK_SIZE]; // decryption round keys

    // copy key into start of session array (by word, each byte in own array)
    for (i = 0, j = 0; i < Nk; i++) {
      w0[i] = key[j++];
      w1[i] = key[j++];
      w2[i] = key[j++];
      w3[i] = key[j++];
    }

    // implement key expansion algorithm
    byte t0, t1, t2, t3, old0; // temp byte values for each word
    for (i = Nk; i < ROUND_KEY_COUNT; i++) {
      t0 = w0[i - 1];
      t1 = w1[i - 1];
      t2 = w2[i - 1];
      t3 = w3[i - 1]; // temp = w[i-1]
      if (i % Nk == 0) {
        // temp = SubWord(RotWord(temp)) ^ Rcon[i/Nk]
        old0 = t0; // save old 1st byte value for t3 calc
        t0 = (byte) (S[t1 & 0xFF] ^ rcon[i / Nk]); // nb. constant XOR 1st byte only
        t1 = (byte) (S[t2 & 0xFF]);
        t2 = (byte) (S[t3 & 0xFF]); // nb. RotWord done by reordering bytes used
        t3 = (byte) (S[old0 & 0xFF]);
      } else if ((Nk > 6) && (i % Nk == 4)) {
        // temp = SubWord(temp)
        t0 = S[t0 & 0xFF];
        t1 = S[t1 & 0xFF];
        t2 = S[t2 & 0xFF];
        t3 = S[t3 & 0xFF];
      }
      // w[i] = w[i-Nk] ^ temp
      w0[i] = (byte) (w0[i - Nk] ^ t0);
      w1[i] = (byte) (w1[i - Nk] ^ t1);
      w2[i] = (byte) (w2[i - Nk] ^ t2);
      w3[i] = (byte) (w3[i - Nk] ^ t3);
    }

    // now copy values into en/decrypt session arrays by round & byte in round
    for (r = 0, i = 0; r < numRounds + 1; r++) { // for each round
      for (j = 0; j < BC; j++) { // for each word in round
        Ke[r][4 * j] = w0[i];
        Ke[r][4 * j + 1] = w1[i];
        Ke[r][4 * j + 2] = w2[i];
        Ke[r][4 * j + 3] = w3[i];
        Kd[numRounds - r][4 * j] = w0[i];
        Kd[numRounds - r][4 * j + 1] = w1[i];
        Kd[numRounds - r][4 * j + 2] = w2[i];
        Kd[numRounds - r][4 * j + 3] = w3[i];
        i++;
      }
    }

    // create trace info if needed
    if (traceLevel > 3) {
      traceInfo += "  Encrypt Round keys:n";
      for (r = 0; r < numRounds + 1; r++)
        traceInfo += "  R" + r + "t = " + Util.toHEX1(Ke[r]) + "n";
      traceInfo += "  Decrypt Round keys:n";
      for (r = 0; r < numRounds + 1; r++)
        traceInfo += "  R" + r + "t = " + Util.toHEX1(Kd[r]) + "n";
    }
  }
Example #3
0
  /**
   * AES decrypt 128-bit ciphertext using key previously set.
   *
   * <p>Follows cipher specification given in FIPS-197 section 5.3 See pseudo code in Fig 5, and
   * details in this section.
   *
   * @param cipher the 128-bit ciphertext value to decrypt.
   * @return the decrypted 128-bit plaintext value.
   */
  public byte[] decrypt(byte[] cipher) {
    // define working variables
    byte[] a = new byte[BLOCK_SIZE]; // AES state variable
    byte[] ta = new byte[BLOCK_SIZE]; // AES temp state variable
    byte[] Kdr; // encrypt keys for current round
    int i, k, row, col;

    traceInfo = ""; // reset trace info
    if (traceLevel > 0) traceInfo = "decryptAES(" + Util.toHEX1(cipher) + ")";

    // check for bad arguments
    if (cipher == null) throw new IllegalArgumentException("Empty ciphertext");
    if (cipher.length != BLOCK_SIZE)
      throw new IllegalArgumentException("Incorrect ciphertext length");

    // copy ciphertext bytes into state and do initial AddRoundKey(state)
    Kdr = Kd[0];
    for (i = 0; i < BLOCK_SIZE; i++) a[i] = (byte) (cipher[i] ^ Kdr[i]);
    if (traceLevel > 2)
      traceInfo += "n  R0 (Key = " + Util.toHEX1(Kdr) + ")nt AK = " + Util.toHEX1(a);
    else if (traceLevel > 1)
      traceInfo += "n  R0 (Key = " + Util.toHEX1(Kdr) + ")t = " + Util.toHEX1(a);

    // for each round except last, apply round transforms
    for (int r = 1; r < numRounds; r++) {
      Kdr = Kd[r]; // get session keys for this round
      if (traceLevel > 1) traceInfo += "n  R" + r + " (Key = " + Util.toHEX1(Kdr) + ")t";

      // InvShiftRows(state) into ta (nb. same shift as encrypt but subtract)
      for (i = 0; i < BLOCK_SIZE; i++) {
        row = i % COL_SIZE;
        // get shifted byte index
        k = (i + BLOCK_SIZE - (row_shift[row] * COL_SIZE)) % BLOCK_SIZE;
        ta[i] = a[k];
      }
      if (traceLevel > 2) traceInfo += "ntISR = " + Util.toHEX1(ta);

      // InvSubBytes(state) into a using inverse S-box Si
      for (i = 0; i < BLOCK_SIZE; i++) a[i] = Si[ta[i] & 0xFF];
      if (traceLevel > 2) traceInfo += "ntISB = " + Util.toHEX1(a);

      // AddRoundKey(state) into ta
      for (i = 0; i < BLOCK_SIZE; i++) ta[i] = (byte) (a[i] ^ Kdr[i]);
      if (traceLevel > 2) traceInfo += "nt AK = " + Util.toHEX1(ta);

      // InvMixColumns(state) into a
      //   implemented by expanding matrix mult for each column
      //   see FIPS-197 section 5.3.3
      for (col = 0; col < NUM_COLS; col++) {
        i = col * COL_SIZE; // start index for this col
        a[i] =
            (byte)
                (mul(0x0e, ta[i])
                    ^ mul(0x0b, ta[i + 1])
                    ^ mul(0x0d, ta[i + 2])
                    ^ mul(0x09, ta[i + 3]));
        a[i + 1] =
            (byte)
                (mul(0x09, ta[i])
                    ^ mul(0x0e, ta[i + 1])
                    ^ mul(0x0b, ta[i + 2])
                    ^ mul(0x0d, ta[i + 3]));
        a[i + 2] =
            (byte)
                (mul(0x0d, ta[i])
                    ^ mul(0x09, ta[i + 1])
                    ^ mul(0x0e, ta[i + 2])
                    ^ mul(0x0b, ta[i + 3]));
        a[i + 3] =
            (byte)
                (mul(0x0b, ta[i])
                    ^ mul(0x0d, ta[i + 1])
                    ^ mul(0x09, ta[i + 2])
                    ^ mul(0x0e, ta[i + 3]));
      }
      if (traceLevel > 2) traceInfo += "ntIMC";
      if (traceLevel > 1) traceInfo += " = " + Util.toHEX1(a);
    }

    // last round is special - only has InvShiftRows, InvSubBytes and AddRoundKey
    Kdr = Kd[numRounds]; // get session keys for final round
    if (traceLevel > 1) traceInfo += "n  R" + numRounds + " (Key = " + Util.toHEX1(Kdr) + ")t";

    // InvShiftRows(state) into ta
    for (i = 0; i < BLOCK_SIZE; i++) {
      row = i % COL_SIZE;
      // get shifted byte index
      k = (i + BLOCK_SIZE - (row_shift[row] * COL_SIZE)) % BLOCK_SIZE;
      ta[i] = a[k];
    }
    if (traceLevel > 2) traceInfo += "ntISR = " + Util.toHEX1(a);

    // InvSubBytes(state) into ta using inverse S-box Si
    for (i = 0; i < BLOCK_SIZE; i++) ta[i] = Si[ta[i] & 0xFF];
    if (traceLevel > 2) traceInfo += "ntISB = " + Util.toHEX1(a);

    // AddRoundKey(state) into a
    for (i = 0; i < BLOCK_SIZE; i++) a[i] = (byte) (ta[i] ^ Kdr[i]);
    if (traceLevel > 2) traceInfo += "nt AK";
    if (traceLevel > 1) traceInfo += " = " + Util.toHEX1(a) + "n";
    if (traceLevel > 0) traceInfo += " = " + Util.toHEX1(a) + "n";
    return (a);
  }
Example #4
0
  /**
   * AES encrypt 128-bit plaintext using key previously set.
   *
   * <p>Follows cipher specification given in FIPS-197 section 5.1 See pseudo code in Fig 5, and
   * details in this section.
   *
   * @param plain the 128-bit plaintext value to encrypt.
   * @return the encrypted 128-bit ciphertext value.
   */
  public byte[] encrypt(byte[] plain) {
    // define working variables
    byte[] a = new byte[BLOCK_SIZE]; // AES state variable
    byte[] ta = new byte[BLOCK_SIZE]; // AES temp state variable
    byte[] Ker; // encrypt keys for current round
    int i, k, row, col;

    traceInfo = ""; // reset trace info
    if (traceLevel > 0) traceInfo = "encryptAES(" + Util.toHEX1(plain) + ")";

    // check for bad arguments
    if (plain == null) throw new IllegalArgumentException("Empty plaintext");
    if (plain.length != BLOCK_SIZE)
      throw new IllegalArgumentException("Incorrect plaintext length");

    // copy plaintext bytes into state and do initial AddRoundKey(state)
    Ker = Ke[0];
    for (i = 0; i < BLOCK_SIZE; i++) a[i] = (byte) (plain[i] ^ Ker[i]);
    if (traceLevel > 2)
      traceInfo += "n  R0 (Key = " + Util.toHEX1(Ker) + ")ntAK = " + Util.toHEX1(a);
    else if (traceLevel > 1)
      traceInfo += "n  R0 (Key = " + Util.toHEX1(Ker) + ")t = " + Util.toHEX1(a);

    // for each round except last, apply round transforms
    for (int r = 1; r < numRounds; r++) {
      Ker = Ke[r]; // get session keys for this round
      if (traceLevel > 1) traceInfo += "n  R" + r + " (Key = " + Util.toHEX1(Ker) + ")t";

      // SubBytes(state) into ta using S-Box S
      for (i = 0; i < BLOCK_SIZE; i++) ta[i] = S[a[i] & 0xFF];
      if (traceLevel > 2) traceInfo += "ntSB = " + Util.toHEX1(ta);

      // ShiftRows(state) into a
      for (i = 0; i < BLOCK_SIZE; i++) {
        row = i % COL_SIZE;
        k = (i + (row_shift[row] * COL_SIZE)) % BLOCK_SIZE; // get shifted byte index
        a[i] = ta[k];
      }
      if (traceLevel > 2) traceInfo += "ntSR = " + Util.toHEX1(a);

      // MixColumns(state) into ta
      //   implemented by expanding matrix mult for each column
      //   see FIPS-197 section 5.1.3
      for (col = 0; col < NUM_COLS; col++) {
        i = col * COL_SIZE; // start index for this col
        ta[i] = (byte) (mul(2, a[i]) ^ mul(3, a[i + 1]) ^ a[i + 2] ^ a[i + 3]);
        ta[i + 1] = (byte) (a[i] ^ mul(2, a[i + 1]) ^ mul(3, a[i + 2]) ^ a[i + 3]);
        ta[i + 2] = (byte) (a[i] ^ a[i + 1] ^ mul(2, a[i + 2]) ^ mul(3, a[i + 3]));
        ta[i + 3] = (byte) (mul(3, a[i]) ^ a[i + 1] ^ a[i + 2] ^ mul(2, a[i + 3]));
      }
      if (traceLevel > 2) traceInfo += "ntMC = " + Util.toHEX1(ta);

      // AddRoundKey(state) into a
      for (i = 0; i < BLOCK_SIZE; i++) a[i] = (byte) (ta[i] ^ Ker[i]);
      if (traceLevel > 2) traceInfo += "ntAK";
      if (traceLevel > 1) traceInfo += " = " + Util.toHEX1(a);
    }

    // last round is special - only has SubBytes, ShiftRows and AddRoundKey
    Ker = Ke[numRounds]; // get session keys for final round
    if (traceLevel > 1) traceInfo += "n  R" + numRounds + " (Key = " + Util.toHEX1(Ker) + ")t";

    // SubBytes(state) into a using S-Box S
    for (i = 0; i < BLOCK_SIZE; i++) a[i] = S[a[i] & 0xFF];
    if (traceLevel > 2) traceInfo += "ntSB = " + Util.toHEX1(a);

    // ShiftRows(state) into ta
    for (i = 0; i < BLOCK_SIZE; i++) {
      row = i % COL_SIZE;
      k = (i + (row_shift[row] * COL_SIZE)) % BLOCK_SIZE; // get shifted byte index
      ta[i] = a[k];
    }
    if (traceLevel > 2) traceInfo += "ntSR = " + Util.toHEX1(a);

    // AddRoundKey(state) into a
    for (i = 0; i < BLOCK_SIZE; i++) a[i] = (byte) (ta[i] ^ Ker[i]);
    if (traceLevel > 2) traceInfo += "ntAK";
    if (traceLevel > 1) traceInfo += " = " + Util.toHEX1(a) + "n";
    if (traceLevel > 0) traceInfo += " = " + Util.toHEX1(a) + "n";
    return (a);
  }