Skip to content

Add IsPasswordValid method #7

@NimeshDhruve

Description

@NimeshDhruve

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

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions