-
Notifications
You must be signed in to change notification settings - Fork 4
Open
Description
It would be great if you can also provide method to validate password for both HOTP and TOTP.
I took a crack at it by implementing this inside Totp.cs but wasn't able to get it working as expected
public bool IsPasswordValid(string password)
{
long givenUnixTime = UnixTime.GetUnixTime();
return IsValidPassword(password, givenUnixTime);
}
public bool IsValidPassword(string password, DateTime dateTime)
{
long givenUnixTime = UnixTime.GetUnixTime(dateTime);
return IsValidPassword(password, givenUnixTime);
}
public override bool IsValidPassword(string password, long timeCounter)
{
var currentPassword = GeneratePassword(timeCounter);
return currentPassword == password;
}
Code for testing this change:
Random _random = new Random();
char GetRandomLetter()
{
// This method returns a random lowercase letter.
// ... Between 'a' and 'z' inclusize.
int num = _random.Next(0, 26); // Zero to 25
char let = (char)('a' + num);
return let;
}
string GetRandomSecretKey()
{
var firstSet = new string(new char[] { GetRandomLetter(), GetRandomLetter(), GetRandomLetter(), GetRandomLetter() });
var secondSet = new string(new char[] { GetRandomLetter(), GetRandomLetter(), GetRandomLetter(), GetRandomLetter() });
var thridSet = new string(new char[] { GetRandomLetter(), GetRandomLetter(), GetRandomLetter(), GetRandomLetter() });
var fourthSet = new string(new char[] { GetRandomLetter(), GetRandomLetter(), GetRandomLetter(), GetRandomLetter() });
return string.Join(" ", firstSet, secondSet, thridSet, fourthSet);
}
private async void TestMeghod()
{
int passwordSize = 6;
for (int timeStep = 30; timeStep < 200; timeStep++) /*Loop for various time steps starting with 30 seconds*/
{
var secretKey = GetRandomSecretKey(); /*Create separate random key for each time step*/
byte[] secret = System.Text.Encoding.ASCII.GetBytes(secretKey);
var otpGenerator = new Totp(secret, passwordSize) { TimeInterval = timeStep };
var sp = Stopwatch.StartNew();
Debug.WriteLine($"TimeStep: {timeStep}, Key: {secretKey}, Started: {DateTime.Now.ToString("hh:mm:ss.fff")}");
//Generate password
var code = otpGenerator.GeneratePassword();
//And now verify this password for timeStep + some buffer to ensure it is working correctly.
for (int i = 0; i < timeStep + 60; i++)
{
await Task.Delay(1000); /*Wait for 1 second and then try to validate the password*/
var otpVerfier = new Totp(secret, passwordSize) { TimeInterval = timeStep }; /*Create a new instance as in production environment Server and client both will have different instances.*/
var isCodeValid = otpVerfier.IsPasswordValid(code); /*Now verify it for given time.*/
var wrongResult = (sp.Elapsed.TotalSeconds > timeStep) && isCodeValid;
//Print some details of this attempt
Debug.WriteLine($"ValidCode: {isCodeValid}, {sp.Elapsed}{(wrongResult ? $", Not good {timeStep}" : "")}{(isCodeValid ? "":$", {timeStep}")}");
if (isCodeValid == false) /*As soon as code is invalid move on, no need to sleep further*/
break;
}
Debug.WriteLine($"TimeStep: {timeStep}, Key: {secretKey}, Ended: {DateTime.Now.ToString("hh:mm:ss.fff")}");
}
}
Metadata
Metadata
Assignees
Labels
No labels