public static byte[] derive(String P, String S, int c, int dkLen) {
        Preconditions.checkArgument(c > 0, () -> "count must be greater than zero");
        Preconditions.checkArgument(dkLen > 0, () -> "derived key length must be greater than zero");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        // The algorithm in RFC 2898 section 5.2, says to check `dkLen` is not greater than (2^32 - 1) * `H_LEN`
        // But that is not possible given `dkLen` is an `int` argument, so we omit the check.
        try {
            int l = (dkLen + H_LEN - 1) / H_LEN;    // Divide by H_LEN with rounding up
            // int r = dkLen - (l-1)*hLen;

            for (int i = 1; i <= l; i++) {
                byte[] T = F(P, S, c, i);
                baos.write(T);
            }
        } catch (IOException | NoSuchAlgorithmException | InvalidKeyException e) {
            throw new RuntimeException(e);
        }

        byte[] baDerived = new byte[dkLen];
        System.arraycopy(baos.toByteArray(), 0, baDerived, 0, baDerived.length);

        return baDerived;
    }
@Test
    @Parameters(method = "testVectors")
    public void derive(String p, String s, Integer c, Integer dkLen, String result) {
        byte[] output = PBKDF2SHA512.derive(p, s, c, dkLen);
        assertEquals(result, new HexFormat().formatHex(output));
    }