generateWorkingKey method

List<List<int>> generateWorkingKey(
  1. bool forEncryption,
  2. KeyParameter params
)

Implementation

List<List<int>> generateWorkingKey(bool forEncryption, KeyParameter params) {
  var key = params.key;
  var keyLen = key.length;
  if (keyLen < 16 || keyLen > 32 || (keyLen & 7) != 0) {
    throw ArgumentError('Key length not 128/192/256 bits.');
  }

  var KC = shiftr32(keyLen, 2);
  _ROUNDS = KC +
      6; // This is not always true for the generalized Rijndael that allows larger block sizes

  var W = List.generate(
      _ROUNDS + 1,
      (int i) =>
          List<int>.filled(4, 0, growable: false)); // 4 words in a block

  switch (KC) {
    case 4:
      var col0 = unpack32(key, 0, Endian.little);
      W[0][0] = col0;
      var col1 = unpack32(key, 4, Endian.little);
      W[0][1] = col1;
      var col2 = unpack32(key, 8, Endian.little);
      W[0][2] = col2;
      var col3 = unpack32(key, 12, Endian.little);
      W[0][3] = col3;

      for (var i = 1; i <= 10; ++i) {
        var colx = _subWord(_shift(col3, 8)) ^ _rcon[i - 1];
        col0 ^= colx;
        W[i][0] = col0;
        col1 ^= col0;
        W[i][1] = col1;
        col2 ^= col1;
        W[i][2] = col2;
        col3 ^= col2;
        W[i][3] = col3;
      }
      break;
    case 6:
      var col0 = unpack32(key, 0, Endian.little);
      W[0][0] = col0;
      var col1 = unpack32(key, 4, Endian.little);
      W[0][1] = col1;
      var col2 = unpack32(key, 8, Endian.little);
      W[0][2] = col2;
      var col3 = unpack32(key, 12, Endian.little);
      W[0][3] = col3;

      var col4 = unpack32(key, 16, Endian.little);
      var col5 = unpack32(key, 20, Endian.little);

      int i = 1, rcon = 1, colx;
      for (;;) {
        W[i][0] = col4;
        W[i][1] = col5;
        colx = _subWord(_shift(col5, 8)) ^ rcon;
        rcon <<= 1;
        col0 ^= colx;
        W[i][2] = col0;
        col1 ^= col0;
        W[i][3] = col1;

        col2 ^= col1;
        W[i + 1][0] = col2;
        col3 ^= col2;
        W[i + 1][1] = col3;
        col4 ^= col3;
        W[i + 1][2] = col4;
        col5 ^= col4;
        W[i + 1][3] = col5;

        colx = _subWord(_shift(col5, 8)) ^ rcon;
        rcon <<= 1;
        col0 ^= colx;
        W[i + 2][0] = col0;
        col1 ^= col0;
        W[i + 2][1] = col1;
        col2 ^= col1;
        W[i + 2][2] = col2;
        col3 ^= col2;
        W[i + 2][3] = col3;

        if ((i += 3) >= 13) {
          break;
        }

        col4 ^= col3;
        col5 ^= col4;
      }

      break;

    case 8:
      {
        var col0 = unpack32(key, 0, Endian.little);
        W[0][0] = col0;
        var col1 = unpack32(key, 4, Endian.little);
        W[0][1] = col1;
        var col2 = unpack32(key, 8, Endian.little);
        W[0][2] = col2;
        var col3 = unpack32(key, 12, Endian.little);
        W[0][3] = col3;

        var col4 = unpack32(key, 16, Endian.little);
        W[1][0] = col4;
        var col5 = unpack32(key, 20, Endian.little);
        W[1][1] = col5;
        var col6 = unpack32(key, 24, Endian.little);
        W[1][2] = col6;
        var col7 = unpack32(key, 28, Endian.little);
        W[1][3] = col7;

        int i = 2, rcon = 1, colx;
        for (;;) {
          colx = _subWord(_shift(col7, 8)) ^ rcon;
          rcon <<= 1;
          col0 ^= colx;
          W[i][0] = col0;
          col1 ^= col0;
          W[i][1] = col1;
          col2 ^= col1;
          W[i][2] = col2;
          col3 ^= col2;
          W[i][3] = col3;
          ++i;

          if (i >= 15) {
            break;
          }

          colx = _subWord(col3);
          col4 ^= colx;
          W[i][0] = col4;
          col5 ^= col4;
          W[i][1] = col5;
          col6 ^= col5;
          W[i][2] = col6;
          col7 ^= col6;
          W[i][3] = col7;
          ++i;
        }

        break;
      }
    default:
      {
        throw StateError('Should never get here');
      }
  }

  if (!forEncryption) {
    for (var j = 1; j < _ROUNDS; j++) {
      for (var i = 0; i < 4; i++) {
        W[j][i] = _invMcol(W[j][i]);
      }
    }
  }

  return W;
}