protected byte calculateByte(byte b) {
    if (counter > 0 && counter % 1024 == 0) {
      BlockCipher base = cfbEngine.getUnderlyingCipher();

      base.init(false, key);

      byte[] nextKey = new byte[32];

      base.processBlock(C, 0, nextKey, 0);
      base.processBlock(C, 8, nextKey, 8);
      base.processBlock(C, 16, nextKey, 16);
      base.processBlock(C, 24, nextKey, 24);

      key = new KeyParameter(nextKey);

      base.init(true, key);

      byte[] iv = cfbEngine.getCurrentIV();

      base.processBlock(iv, 0, iv, 0);

      cfbEngine.init(forEncryption, new ParametersWithIV(key, iv));
    }

    counter++;

    return cfbEngine.calculateByte(b);
  }
  public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException {
    counter = 0;
    cfbEngine.init(forEncryption, params);

    this.forEncryption = forEncryption;

    if (params instanceof ParametersWithIV) {
      params = ((ParametersWithIV) params).getParameters();
    }

    if (params instanceof ParametersWithRandom) {
      params = ((ParametersWithRandom) params).getParameters();
    }

    if (params instanceof ParametersWithSBox) {
      params = ((ParametersWithSBox) params).getParameters();
    }

    key = (KeyParameter) params;
  }
  public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
      throws DataLengthException, IllegalStateException {
    this.processBytes(in, inOff, cfbEngine.getBlockSize(), out, outOff);

    return cfbEngine.getBlockSize();
  }
 public int getBlockSize() {
   return cfbEngine.getBlockSize();
 }
 public String getAlgorithmName() {
   String name = cfbEngine.getAlgorithmName();
   return name.substring(0, name.indexOf('/')) + "/G" + name.substring(name.indexOf('/') + 1);
 }
 public void reset() {
   counter = 0;
   cfbEngine.reset();
 }