class OTPUtil {

    private static final Logger log = LoggerFactory.getLogger(OTPUtil.class);

    //sizes to generate OTP secret
    private static final int SECRET_SIZE = 10;
    private static final int NUM_SCRATCH_CODES = 5;
    private static final int SCRATCH_CODE_SIZE = 4;

    //token window in near future or past
    private static final int TOKEN_WINDOW = 3;

    //interval for validation token change
    private static final int CHANGE_INTERVAL = 30;

    private OTPUtil() {
    }


    /**
     * generates OPT secret
     *
     * @return String shared secret
     */
    public static String generateSecret() {
        byte[] buffer = new byte[(NUM_SCRATCH_CODES * SCRATCH_CODE_SIZE) + SECRET_SIZE];
        new SecureRandom().nextBytes(buffer);

        byte[] secret = Arrays.copyOf(buffer, SECRET_SIZE);

        return new String(new Base32().encode(secret));

    }

    /**
     * verifies code for OTP secret
     *
     * @param secret shared secret
     * @param token  verification token
     * @return true if success
     */
    public static boolean verifyToken(String secret, long token) {

        //check token in near future or past
        int window = TOKEN_WINDOW;
        for (int i = window; i >= -window; i--) {

            long time = (new Date().getTime() / TimeUnit.SECONDS.toMillis(CHANGE_INTERVAL)) + i;

            if (verifyToken(secret, token, time)) {
                return true;
            }
        }

        return false;

    }

    /**
     * verifies code for OTP secret per time interval
     *
     * @param secret shared secret
     * @param token  verification token
     * @param time   time representation to calculate OTP
     * @return true if success
     */
    private static boolean verifyToken(String secret, long token, long time) {<FILL_FUNCTION_BODY>}

}


        long calculated = -1;

        byte[] key = new Base32().decode(secret);

        SecretKeySpec secretKey = new SecretKeySpec(key, "HmacSHA1");

        try {
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(secretKey);
            byte[] hash = mac.doFinal(ByteBuffer.allocate(8).putLong(time).array());

            int offset = hash[hash.length - 1] & 0xF;
            for (int i = 0; i < 4; ++i) {
                calculated <<= 8;
                calculated |= (hash[offset + i] & 0xFF);
            }

            calculated &= 0x7FFFFFFF;
            calculated %= 1000000;
        } catch (Exception ex) {
            log.error(ex.toString(), ex);
        }


        return (calculated != -1 && calculated == token);


    
<no_super_class>