code: public byte[] doFinal(byte[] input){
  		byte[] main = update(input);
  		byte[] out;
  		//if buffer isn't empty add a padding indicator to the end of data
  		if(bufferIndex != 0){
  			
  			buffer[bufferIndex] = 0x69;
  			bufferIndex++;
  			//System.out.println(Misc.bytesToHex(buffer));
  			buffer = cryptBlock();
  			//add buffer to end of main
  			out = new byte[main.length + buffer.length];
  			System.arraycopy(main, 0, out, 0, main.length);
  			System.arraycopy(buffer, 0, out, main.length, buffer.length);
  		}else{
  			//remove padding
  			int endIndex = main.length-1 ;
  			while(main[endIndex] == 0 || main[endIndex] == 0x69){
  				endIndex --;
  				if(endIndex != 0 && main[endIndex] == 0x69){ //TODO removing padding needs fixing
  					endIndex--;
  					break;
  				}
  			}
  			//System.out.println("endindex " + endIndex);
  			out = new byte[endIndex + 1];
  			System.arraycopy(main, 0, out, 0, endIndex+1);
  		}
  				
  		blockNo = 0;
  		IV = null;
  		key = null;
  		cfg = false;
  		bufferIndex = 0;
  		
  		return out;
  	}
docs: Encrypts or decrypts data in a single-part operation, or finishes a multiple-part operation.
  The bytes in the input buffer, and any input bytes that may have been buffered during a previous update operation, are processed, with padding (if requested) being applied.
  
  Upon finishing, this method resets this cipher object to the state it was in before initialized via a call to init. That is, the object is reset and needs to be re-initialized before it is available to encrypt or decrypt more data.
  @param input the input buffer
  @return the new buffer with the result