2019-02-07 22:39:33 +01:00
|
|
|
package com.beemdevelopment.aegis.otp;
|
|
|
|
|
2019-03-31 22:15:03 +02:00
|
|
|
import com.beemdevelopment.aegis.crypto.otp.OTP;
|
2019-02-07 22:39:33 +01:00
|
|
|
import com.beemdevelopment.aegis.crypto.otp.TOTP;
|
2018-06-06 16:15:31 +02:00
|
|
|
|
|
|
|
import org.json.JSONException;
|
|
|
|
import org.json.JSONObject;
|
|
|
|
|
2019-03-25 23:51:10 +01:00
|
|
|
import java.security.InvalidKeyException;
|
|
|
|
import java.security.NoSuchAlgorithmException;
|
|
|
|
|
2018-06-06 16:15:31 +02:00
|
|
|
public class TotpInfo extends OtpInfo {
|
2019-03-31 22:15:03 +02:00
|
|
|
public static final String ID = "totp";
|
2021-01-30 16:41:25 +01:00
|
|
|
public static final int DEFAULT_PERIOD = 30;
|
2019-03-31 22:15:03 +02:00
|
|
|
|
2018-06-06 16:15:31 +02:00
|
|
|
private int _period;
|
|
|
|
|
|
|
|
public TotpInfo(byte[] secret) throws OtpInfoException {
|
|
|
|
super(secret);
|
2021-01-30 16:41:25 +01:00
|
|
|
setPeriod(DEFAULT_PERIOD);
|
2018-06-06 16:15:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public TotpInfo(byte[] secret, String algorithm, int digits, int period) throws OtpInfoException {
|
|
|
|
super(secret, algorithm, digits);
|
|
|
|
setPeriod(period);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-09-17 17:30:14 +02:00
|
|
|
public String getOtp() throws OtpInfoException {
|
|
|
|
checkSecret();
|
|
|
|
|
2019-03-25 23:51:10 +01:00
|
|
|
try {
|
2019-03-31 22:15:03 +02:00
|
|
|
OTP otp = TOTP.generateOTP(getSecret(), getAlgorithm(true), getDigits(), getPeriod());
|
|
|
|
return otp.toString();
|
2019-03-25 23:51:10 +01:00
|
|
|
} catch (InvalidKeyException | NoSuchAlgorithmException e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
2018-06-06 16:15:31 +02:00
|
|
|
}
|
|
|
|
|
2024-09-30 23:36:08 +02:00
|
|
|
public String getOtp(long time) throws OtpInfoException {
|
|
|
|
checkSecret();
|
|
|
|
|
2020-12-16 21:44:37 +01:00
|
|
|
try {
|
|
|
|
OTP otp = TOTP.generateOTP(getSecret(), getAlgorithm(true), getDigits(), getPeriod(), time);
|
|
|
|
return otp.toString();
|
|
|
|
} catch (InvalidKeyException | NoSuchAlgorithmException e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-06 16:15:31 +02:00
|
|
|
@Override
|
2021-01-24 12:53:29 +01:00
|
|
|
public String getTypeId() {
|
2019-03-31 22:15:03 +02:00
|
|
|
return ID;
|
2018-06-06 16:15:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public JSONObject toJson() {
|
|
|
|
JSONObject obj = super.toJson();
|
|
|
|
try {
|
|
|
|
obj.put("period", getPeriod());
|
|
|
|
} catch (JSONException e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getPeriod() {
|
|
|
|
return _period;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean isPeriodValid(int period) {
|
2019-08-28 19:46:47 +02:00
|
|
|
if (period <= 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check for the possibility of an overflow when converting to milliseconds
|
|
|
|
return period <= Integer.MAX_VALUE / 1000;
|
2018-06-06 16:15:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setPeriod(int period) throws OtpInfoException {
|
|
|
|
if (!isPeriodValid(period)) {
|
|
|
|
throw new OtpInfoException(String.format("bad period: %d", period));
|
|
|
|
}
|
|
|
|
_period = period;
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getMillisTillNextRotation() {
|
|
|
|
return TotpInfo.getMillisTillNextRotation(_period);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static long getMillisTillNextRotation(int period) {
|
|
|
|
long p = period * 1000;
|
|
|
|
return p - (System.currentTimeMillis() % p);
|
|
|
|
}
|
2018-09-25 19:36:56 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean equals(Object o) {
|
|
|
|
if (!(o instanceof TotpInfo)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
TotpInfo info = (TotpInfo) o;
|
|
|
|
return super.equals(o) && getPeriod() == info.getPeriod();
|
|
|
|
}
|
2018-06-06 16:15:31 +02:00
|
|
|
}
|