Otp.NET
Otp.NET copied to clipboard
TOTP window start
We have Totp.RemainingSecods()
which however does not indicate when the current time window started. There is no way to find out the steps that the Totp
was created with (#45) so developers cannot even calculate it manually given an instance of Totp
.
How about adding Totp.ElapsedSeconds()
?
We have
Totp.RemainingSecods()
which however does not indicate when the current time window started. There is no way to find out the steps that theTotp
was created with (#45) so developers cannot even calculate it manually given an instance ofTotp
.How about adding
Totp.ElapsedSeconds()
?
Why not use the totp.RemainingSeconds()
method to get the remaining seconds and then subtracting it from DateTime.UtcNow
to get the elapsed seconds?
That doesn't give you any meaningful information, does it? If the remaining seconds is 5 and UtcNow is 12:34:56, then subtracting gives you 12:34:51, regardless of when the window actually started..
The step time (window) should already be known when creating your TOTP object, so you will need a reference to that value to do the calculation. Maybe this snippet will help point you in the right direction:
var window = 30;
var totp = new OtpNet.Totp(
step: window,
secretKey: xxxxxxx)
...
var dtNow = DateTime.UtcNow;
var remainingSeconds = totp.RemainingSeconds();
Console.WriteLine($"Window: {window} seconds");
Console.WriteLine($"Remaining: {remainingSeconds}");
Console.WriteLine($"Now: {dtNow.ToLocalTime()}");
Console.WriteLine($"Window start: {dtNow.AddSeconds(remainingSeconds - window).ToLocalTime()}");
Thank you @damiarnold I understand that, but I cannot do that if I am not the one who created the Totp object. And when I have several Totp objects I created, I have to keep a table of the objects and their windows, while the Totp object already has all the information needed.
Fair enough - I agree that convenience properties would help in many of these cases - especially if you are not the one creating the objects and do not have access to their initial constructor argument values.
Short of submitting a pull request, you could always (as a last resort) use reflection on the private members, but this may be a non-starter for your use case, and is certainly not my go-to solution unless there is no other reasonable choice.
@kspearrin any thoughts on merits of providing public property wrappers for private members such as the Totp members _step, _totpSize, _correctedTime as well as the Otp _hashMode member? There may be a couple in the Hotp class I haven't peeked into yet, but if this seems reasonable, I could possibly work on a pull request in the next week or so for "convenience properties" for reasonable members that are currently private/protected, as the workarounds many of us use now do have some limitations.
I did #49. I also looked into ElapsedSeconds()
and since RemainingSeconds()
returns integral value (as opposed to TimeSpan
or double
), I don't find enough value in ElapsedSeconds()
if #49 is merged since you will have acces to the Step
property and can calculate that easily (RemainingSeconds()
in practice already calculates Step - ElapsedSeconds()
).
For people who are looking for actual elapsed or remaining time (e.g. to update the OTP displayed in UI), it would be more useful to have the window start as DateTime
available.
so developers cannot even calculate it manually given an instance of Totp
You can calculate the step manually from only RemainingSeconds()
, but it would take up to step + 2
seconds to do so.
And when I have several Totp objects I created, I have to keep a table of the objects and their windows, while the Totp object already has all the information needed.
The only reason for a table would be if each object had a unique step value.
The RemainingSeconds()
and window start times will be identical for all instances using the same step, time source and time correction offset.
Note: the delay parameter
or step
is ignored on some authenticator apps and hardcoded to 30 seconds.
The following methods return the start of the window for a given step. The period
parameter calculates the start of the next window(s) value can be negative for previous windows.
A period of 1 would give just past the end time of the current window.
DateTimeOffset GetCurrentWindowStart(long step = 30, int period = 0)
{
return DateTimeOffset.FromUnixTimeSeconds((
DateTimeOffset.UtcNow().ToUnixTimeSeconds()
/ step + period ) * step);
}
Or if you want the value in the local time zone:
DateTimeOffset GetCurrentWindowStartLocal(long step = 30, int period = 0)
{
return ConvertTime(DateTimeOffset.FromUnixTimeSeconds((
DateTimeOffset.UtcNow().ToUnixTimeSeconds()
/ step + period) * step), TimeZoneInfo.Local);
}
Or just the Time Parameter:
long GetCurrentWindowStart(long step = 30, long period = 0)
{
return (DateTimeOffset.UtcNow().ToUnixTimeSeconds() / step + period ) * step;
}