class Hkdf {

  public static byte[] computeHkdf(
      String macAlgorithm, final byte[] ikm, final byte[] salt, final byte[] info, int size)
      throws GeneralSecurityException {
    Mac mac = EngineFactory.MAC.getInstance(macAlgorithm);
    if (size > 255 * mac.getMacLength()) {
      throw new GeneralSecurityException("size too large");
    }
    if (salt == null || salt.length == 0) {
      // According to RFC 5869, Section 2.2 the salt is optional. If no salt is provided
      // then HKDF uses a salt that is an array of zeros of the same length as the hash digest.
      mac.init(new SecretKeySpec(new byte[mac.getMacLength()], macAlgorithm));
    } else {
      mac.init(new SecretKeySpec(salt, macAlgorithm));
    }
    byte[] prk = mac.doFinal(ikm);
    byte[] result = new byte[size];
    int ctr = 1;
    int pos = 0;
    mac.init(new SecretKeySpec(prk, macAlgorithm));
    byte[] digest = new byte[0];
    while (true) {
      mac.update(digest);
      mac.update(info);
      mac.update((byte) ctr);
      digest = mac.doFinal();
      if (pos + digest.length < size) {
        System.arraycopy(digest, 0, result, pos, digest.length);
        pos += digest.length;
        ctr++;
      } else {
        System.arraycopy(digest, 0, result, pos, size - pos);
        break;
      }
    }
    return result;
  }

}