Otp.NET
Otp.NET copied to clipboard
How to match the code with a flutter library?
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?
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
- First, it willl decode the secret as unicode bytes rather than as base32
- Secondly, it will pad the secret by repeating it using a fixed key length, key padding code. algorithm key lengths
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:
- Use
Encoding.ASCII.GetBytesinstead ofBase32Encoding.ToBytes - Maunally extend the secret string to the right length, in OP''s case sh256 uses 32 bytes so the key would be
DDXFM42476476545DDXFM42476476545
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)
@tareq2 Is the DateTime value passed to ComputeTotp in UTC format? It should be a UTC DateTime value.