All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.keycloak.models.utils.TimeBasedOTP Maven / Gradle / Ivy

There is a newer version: 25.0.5
Show newest version
/*
 * Copyright 2016 Red Hat, Inc. and/or its affiliates
 * and other contributors as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.keycloak.models.utils;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

/**
 * TOTP: Time-based One-time Password Algorithm Based on http://tools.ietf.org/html/draft-mraihi-totp-timebased-06
 *
 * @author anil saldhana
 * @since Sep 20, 2010
 */
public class TimeBasedOTP extends HmacOTP {

    public static final int DEFAULT_INTERVAL_SECONDS = 30;
    public static final int DEFAULT_DELAY_WINDOW = 1;

    private Clock clock;

    public TimeBasedOTP() {
        this(DEFAULT_ALGORITHM, DEFAULT_NUMBER_DIGITS, DEFAULT_INTERVAL_SECONDS, DEFAULT_DELAY_WINDOW);
    }

    /**
     * @param algorithm the encryption algorithm
     * @param numberDigits the number of digits for tokens
     * @param timeIntervalInSeconds the number of seconds a token is valid
     * @param lookAheadWindow the number of previous intervals that should be used to validate tokens.
     */
    public TimeBasedOTP(String algorithm, int numberDigits, int timeIntervalInSeconds, int lookAheadWindow) {
        super(numberDigits, algorithm, lookAheadWindow);
        this.clock = new Clock(timeIntervalInSeconds);
    }

    /**
     * 

Generates a token.

* * @param secretKey the secret key to derive the token from. */ public String generateTOTP(String secretKey) { long T = this.clock.getCurrentInterval(); String steps = Long.toHexString(T).toUpperCase(); // Just get a 16 digit string while (steps.length() < 16) steps = "0" + steps; return generateOTP(secretKey, steps, this.numberDigits, this.algorithm); } /** *

Validates a token using a secret key.

* * @param token OTP string to validate * @param secret Shared secret * @return */ public boolean validateTOTP(String token, byte[] secret) { long currentInterval = this.clock.getCurrentInterval(); for (int i = this.lookAheadWindow; i >= 0; --i) { String steps = Long.toHexString(currentInterval - i).toUpperCase(); // Just get a 16 digit string while (steps.length() < 16) steps = "0" + steps; String candidate = generateOTP(new String(secret), steps, this.numberDigits, this.algorithm); if (candidate.equals(token)) { return true; } } return false; } public void setCalendar(Calendar calendar) { this.clock.setCalendar(calendar); } private class Clock { private final int interval; private Calendar calendar; public Clock(int interval) { this.interval = interval; } public long getCurrentInterval() { Calendar currentCalendar = this.calendar; if (currentCalendar == null) { currentCalendar = GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC")); } return (currentCalendar.getTimeInMillis() / 1000) / this.interval; } public void setCalendar(Calendar calendar) { this.calendar = calendar; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy