Для тех, кто заинтересован, я нашел способ встроить срок действия в свой одноразовый пароль. Подход заключается в том, чтобы использовать созданное время с точностью до минуты (игнорируя секунды, миллисекунды и т. Д.). Получив это значение, используйте тики DateTime в качестве счетчика или переменную C.
otpLifespan
- моя продолжительность жизни HOTP в минутах.
DateTime current = new DateTime(DateTime.Now.Year, DateTime.Now.Month,
DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, 0);
for (int x = 0; x <= otpLifespan; x++)
{
var result = NumericHOTP.Validate(hotp, key,
current.AddMinutes(-1 * x).Ticks);
//return valid state if validation succeeded
//return invalid state if the passed in value is invalid
// (length, non-numeric, checksum invalid)
}
//return expired state
Мой истекающий HOTP происходит от моего числового HOTP, который имеет метод статической проверки, который проверяет длину, проверяет ее числовость, проверяет контрольную сумму, если она используется, и, наконец, сравнивает переданную горячую подсказку с сгенерированной.
Единственным недостатком этого является то, что каждый раз, когда вы проверяете истекающий hotp, ваш худший сценарий - это проверка n + 1 значений HOTP, где n - продолжительность жизни в минутах.
Пример кода Java в документе, описывающем RFC 4226, был очень простым переходом на C #. Единственное, что мне действительно пришлось приложить для переписывания, это метод хеширования.
private static byte[] HashHMACSHA1(byte[] keyBytes, byte[] text)
{
HMAC alg = new HMACSHA1(keyBytes);
return alg.ComputeHash(text);
}
Надеюсь, это поможет любому, кто попытается сгенерировать одноразовые пароли.