kspearrin / Otp.NET

A .NET implementation of TOTP and HOTP for things like two-factor authentication codes.
https://www.nuget.org/packages/Otp.NET
MIT License
1.09k stars 164 forks source link

How to match the code with a flutter library? #44

Open tareq2 opened 1 year ago

tareq2 commented 1 year ago

Hello everyone, I am using the library dart-otp in a flutter app that generate the code and i need to validate this code in c# but i couldn't validate this code nor generate the same code from the two libraries. The code in flutter/dart is

var now = DateTime.now();
      now = DateTime(2023, 04, 26, 10, 10, 10);

      var code = OTP.generateTOTPCodeString(
          'DDXFM42476476545', now.millisecondsSinceEpoch,
          algorithm: Algorithm.SHA256, isGoogle: false);

      print(code);  // Out 667099

In C# the code is

string skey = "DDXFM42476476545";

            var  now = new DateTime(2023, 04, 26, 10, 10, 10);
            var totp = new Totp(Base32Encoding.ToBytes(skey),30,OtpHashMode.Sha256);
            var code = totp.ComputeTotp(now);
 //code = 734057

Can anyone help to figure this difference?

exelix11 commented 1 year ago

I just encountered this myself and had to investigate since i needed interoperability. The problem is that dart-otp has a different behavior due to the isGoogle flag. When it is false it does two weird things as seen here https://github.com/daegalus/dart-otp/blob/09597cd5277d3d602de2bb715102a07c7f387088/lib/otp.dart#L96-L105

However this library hardcodes a zero-extension padding and always extends the key to a multiple of 16 bytes here: https://github.com/kspearrin/Otp.NET/blob/0ac3c315d3d64aa7a89361167fe2e8be8b512ff7/src/Otp.NET/InMemoryKey.cs#L71-L74

in OP's case the fix is to set isGoogle to true, then dart produces the expected 734057 value. If like me you need compatibility with an isGoogle = false app then you'll have to do some convincing to get this library to work:

This produces the OTP value 500288 which is different from what OP claims but i get the same result when running the first dart snippet, not sure why.

As i don't know the RFC standard i can't tell which library is wrong here, i can say that i also tested a nodejs library and with no additional tweaking it seems to agree with otp-dart, making this implementation the odd one out (at least as far as defaults go)

mcessna commented 9 months ago

@tareq2 Is the DateTime value passed to ComputeTotp in UTC format? It should be a UTC DateTime value.