daegalus / dart-otp Goto Github PK
View Code? Open in Web Editor NEWRFC6238 Time-Based One-Time Password / Google Authenticator Library
License: MIT License
RFC6238 Time-Based One-Time Password / Google Authenticator Library
License: MIT License
Is it an expected behavior that both methods for OTP generation keep generating the same value even when we set a time interval?
First thank you very much for the library. I seem to be running into an issue with your TOTP generator which I hope you can help. (Looking at the change log you seem to be fighting here alot with Base32).
So basically I have this TOTP:
otpauth://totp/test?secret=kzvvz2s2ylhdmxzk&algorithm=SHA1&digits=6&period=30
Yet when I do a:
OTP.generateTOTPCodeString(
"kzvvz2s2ylhdmxzk",
1678614973232,
algorithm: Algorithm.SHA1,
interval: 30,
length: 6,
isGoogle: true,
)
I get a "FormatException: Invalid Base32 characters". If I set "isGoogle=false" I get a result, but an incorrect one. At least not the same as Google Authenticator. I am using the otp version 3.1.3, so the latest available one.
Google Authenticator, same as https://totp.danhersam.com/ (which uses https://www.npmjs.com/package/otpauth) accept the QR code without issues.
The packages generates invalid codes
I used this site https://totp.danhersam.com to validate the codes but the site generated code and the package code are not the same.
Also I tried this pub package https://pub.dev/packages/dart_dash_otp and it works will.
So if you can fix your package it will be great because it toke a long time to find another working solution as your package is suggested first.
Seems to not work with many websites.... authy and the website listed bellow are able to give the right codes, my app never was able to no matter what I tried (changing letters to caps lock, using padding, etc etc"
I have been trying to understand more of TOTP codes for the last month and a half and try to solve a big issue i've been having.
I have my app which is supposed to work like the "authy" authentication app. giving you the totp codes for the application you have registered into.
However.... for some reason it seems to refuse to work with certain types of codes, let me explain.
when I try this website: https://rootprojects.org/authenticator/
which I found in the google authenticator github (deemed pretty helpful to enable me to understand totp codes better)
however. after trying every single algorithm it offers me, and even trying to convert between different bases, I could never understand why the codes generated by that "authenticator" website work, but other websites like discord and such dont.
example of a code from that website:
"FDPP6JSAGB23SSLHIK4F7JCSI5TQLS3W"
while a code from discord for example, refuses to work:
"A2YFU5QBOLOWZAXP"
I havent been able to wrap my head over this for the last month... all my research has been unable to figure out why.
I only have one more month to finish the app and all the other things I have to do for my whole project... and Im really getting stressed out over this.... i cant understand whats going on.
app's github to generate the codes: https://github.com/skygamer125/PAP_Unnamed_Keyboard_PhoneApp/blob/main/lib/screens/2fa_setup/components/screens/done/components/main_body.dart
I've noticed that from time to time, the generated TOTP code length doesn't match the input I provide to the generator.
For example: I have a URL that has a length parameter of 8 digits. Most of the time it displays the correct 8 digits, but sometimes it'll display 6 or 7 digits.
Have not been able to narrow down what's causing this so far, but it tends to happen more often at the beginning of an app launch, rather than later on.
Here's the URL I used to generate the codes in the screenshot:
otpauth://totp/fake%40fake.com?secret=asdfasdfasdfasdf&issuer=Google&algorithm=SHA1&digits=8&period=20
so this is a replacement for Google authenticator ?
Just was not sure if its designed to work with it or not...
I updated a commercial project to v3.1.0 and this broke the unit tests.
It's not a problem because the tests were checking the subtle differences between isGoogle:true
and isGoogle:false
. Before v3.1.0, those differences were relevant only for short secrets, but there was no difference when the secrets had the correct length.
Nevertheless, you are now potentially breaking any app that was relying on the isGoogle:false
behaviour while using Base32.
My suggestion is that this change in behaviour should be properly documented (particularly since this is happening in a minor version change).
Thanks for your amazing work with this plugin.
Read your documentation and is validating input.
Does not generate the same code as Google Authenticator or https://totp.danhersam.com for example.
Using version otp: ^3.0.2
String _generateTotp(String? secretKey) {
if (_validateSecretKey(secretKey) == null) {
final sk = secretKey!.toUpperCase();
developer.log(sk);
return OTP.generateTOTPCodeString(
sk, DateTime.now().millisecondsSinceEpoch,
length: 6,
interval: 30,
algorithm: Algorithm.SHA256,
isGoogle: false);
// return OTP.generateTOTPCodeString("JBSWY3DPEHPK3PXP", 1362302550000);
} else {
_percentRemaining = 0.0;
_remainingSeconds = 0;
return '';
}
}
String? _validateSecretKey(String? b32str,
{Encoding encoding = Encoding.standardRFC4648}) {
var regex = EncodingUtils.getRegex(encoding);
if (b32str == null || b32str.isEmpty) {
return 'Secret key cannot be empty';
}
if (b32str.length % 8 != 0) {
return 'Secret key must be a multiple of 8';
}
if (!regex.hasMatch(b32str.toUpperCase())) {
return 'Secret key must be a valid base32 string';
// return 'Only ABCDEFGHIJKLMNOPQRSTUVWXYZ234567= characters are allowed';
}
return null;
}
It's been more than 2 months now that quick_log moved to version >= 1.0.0
Can you update the dependencies, or remove the upper limits?
This is a feature request. I would find it helpful to also get one time password verification functions.
Hi
The TOTP created for Instagram two factor authentication is not valid. I also checked with google authenticator which is working perfectly. I have used all algorithm provided by the library.
Please look into the issue
Hi,
We've spent quite some time today looking around to find potential issue with the input we've provided to generateTOTPCodeString
but eventually failed. All the test passes, but seems that the generated codes do not match. We did the comparison against https://github.com/bellstrand/totp-generator/blob/master/test/index.spec.js#L6 .
The readme here, here and here state the following:
OTP.generateTOTPCode(String secret, int currentTime, {int length: 6, int interval: 30, Algorithm algorithm: Algorithm.SHA1, bool isGoogle: true})
and
OTP.generateTOTPCodeString(String secret, int currentTime, {int length: 6, int interval: 30, Algorithm algorithm: Algorithm.SHA1, bool isGoogle: true})
The default value for isGoogle
is supposed to be true
but in the code, it is actually set to false
.
See:
https://github.com/Daegalus/dart-otp/blob/9617cce0bf8268c93826f88eac24733808376370/lib/otp.dart#L22
and
https://github.com/Daegalus/dart-otp/blob/9617cce0bf8268c93826f88eac24733808376370/lib/otp.dart#L36
I do not know which is the intended value, so I just leave this here.
/Users/qlinksoftware/Documents/FlutterSdk/flutter/bin/flutter --no-color pub get
Running "flutter pub get" in my-table-flutter-master...
The current Dart SDK version is 2.10.4.
Because test >=1.16.0-nullsafety <1.16.0-nullsafety.5 requires SDK version >=2.10.0-0 <2.10.0 and test >=1.16.0-nullsafety.5 <1.16.0-nullsafety.8 depends on pedantic >=1.10.0-nullsafety <1.10.0, test >=1.16.0-nullsafety <1.16.0-nullsafety.8 requires pedantic >=1.10.0-nullsafety <1.10.0.
And because test >=1.16.0-nullsafety.8 requires SDK version >=2.12.0-0 <3.0.0 and test >=0.12.0-beta.3 <1.3.0 requires SDK version >=1.8.0 <2.0.0-∞, test >=0.12.0-beta.3 <1.3.0-∞ or >=1.16.0-nullsafety requires pedantic >=1.10.0-nullsafety <1.10.0.
And because test >=1.3.0 <1.12.0 depends on boolean_selector ^1.0.0 and test >=1.12.0 <1.13.0 depends on test_api 0.2.14, test >=0.12.0-beta.3 <1.13.0-∞ or >=1.16.0-nullsafety requires pedantic >=1.10.0-nullsafety <1.10.0 or boolean_selector ^1.0.0 or test_api 0.2.14.
And because test >=1.13.0 <1.14.5 depends on test_api 0.2.15 and test >=1.14.5 <1.15.0 depends on test_api 0.2.16, test >=0.12.0-beta.3 <1.15.0-∞ or >=1.16.0-nullsafety requires pedantic >=1.10.0-nullsafety <1.10.0 or boolean_selector ^1.0.0 or test_api 0.2.14 or 0.2.15 or 0.2.16.
And because test >=1.15.0 <1.15.3 depends on test_api 0.2.17 and test >=1.15.3 <1.15.5 depends on test_api 0.2.18, test >=0.12.0-beta.3 <1.15.5-∞ or >=1.16.0-nullsafety requires pedantic >=1.10.0-nullsafety <1.10.0 or boolean_selector ^1.0.0 or test_api 0.2.14 or 0.2.15 or 0.2.16 or 0.2.17 or 0.2.18.
And because test >=1.15.5 <1.16.0-nullsafety depends on test_api 0.2.18+1 and every version of flutter_test from sdk depends on boolean_selector 2.1.0-nullsafety.1, if test >=0.12.0-beta.3 and flutter_test any from sdk then test_api 0.2.14 or 0.2.15 or 0.2.16 or 0.2.17 or 0.2.18 or 0.2.18+1 or pedantic >=1.10.0-nullsafety <1.10.0.
(1) So, because every version of flutter_test from sdk depends on test_api 0.2.19-nullsafety.2 and every version of no_bloc depends on test ^1.0.0, if flutter_test any from sdk and no_bloc any then pedantic >=1.10.0-nullsafety <1.10.0.
Because quick_log >=1.1.0 <1.1.1 depends on no_bloc ^0.2.3 and quick_log >=1.0.0 <1.1.0 depends on no_bloc ^0.2.0, quick_log >=1.0.0 <1.1.1 requires no_bloc ^0.2.0.
And because quick_log ^1.1.1 depends on no_bloc >=0.3.4 <2.0.0, quick_log ^1.0.0 requires no_bloc ^0.2.0 or >=0.3.4 <2.0.0.
And because if flutter_test any from sdk and no_bloc any then pedantic >=1.10.0-nullsafety <1.10.0 (1), if flutter_test any from sdk and quick_log ^1.0.0 then pedantic >=1.10.0-nullsafety <1.10.0.
(2) So, because otp >=2.2.2 depends on quick_log ^1.0.0 and syncfusion_flutter_core >=18.2.54 depends on pedantic >=1.9.0 <1.9.9, one of flutter_test any from sdk or otp >=2.2.2 or syncfusion_flutter_core >=18.2.54 must be false.
Because no versions of syncfusion_flutter_datepicker match >18.3.44-beta <18.3.47-beta and syncfusion_flutter_datepicker >=18.3.47-beta <18.3.48-beta depends on syncfusion_flutter_core ^18.3.47, syncfusion_flutter_datepicker >18.3.44-beta <18.3.48-beta requires syncfusion_flutter_core ^18.3.47.
And because syncfusion_flutter_datepicker >=18.3.48-beta <18.3.50-beta depends on syncfusion_flutter_core ^18.3.48 and syncfusion_flutter_datepicker >=18.3.50-beta <18.3.51-beta depends on syncfusion_flutter_core ^18.3.50, syncfusion_flutter_datepicker >18.3.44-beta <18.3.51-beta requires syncfusion_flutter_core ^18.3.47.
And because syncfusion_flutter_datepicker >=18.3.51-beta depends on syncfusion_flutter_core ^18.3.51 and syncfusion_flutter_datepicker 18.3.44-beta depends on syncfusion_flutter_core ^18.3.44, syncfusion_flutter_datepicker >=18.3.44-beta requires syncfusion_flutter_core ^18.3.44.
And because one of flutter_test any from sdk or otp >=2.2.2 or syncfusion_flutter_core >=18.2.54 must be false (2), one of flutter_test any from sdk or otp >=2.2.2 or syncfusion_flutter_datepicker >=18.3.44-beta must be false.
And because mytableqatar depends on syncfusion_flutter_datepicker ^18.3.44-beta, flutter_test from sdk is incompatible with otp >=2.2.2.
So, because mytableqatar depends on both otp ^2.2.3 and flutter_test any from sdk, version solving failed.
pub get failed (1; So, because mytableqatar depends on both otp ^2.2.3 and flutter_test any from sdk, version solving failed.)
Process finished with exit code 1
I'm trying to implement hotp generate function to my app (for totp it works well). And I'm using this site to test my tokens. For this secret: NBQWQYLIEBXWMIDZMFQSAOSE and counter = 0 values, Google Authenticator generates: "253 778" test token. But OTP.generateHOTPCodeString("NBQWQYLIEBXWMIDZMFQSAOSE", 0, algorithm: Algorithm.SHA1)
function generates "392731" token.
What could be the problem causing this issue?
Hi, i am getting 5 digits instead of 6 in cases such as the following.
millisecondsSinceEpoch: 1634663272444
Base32 code: ZB43UA3ZK4JT6B3HT5VC63VFLP57V2ZZB4XCNGEZI72TGPYEJ6JHVERLYJRCPAFMBAIFW3WAQS5CA6LAUTXJHUQIS6GD6EXITL3ZIAAW7FRFSAOSUAV7NSHP4VPU7XXSJICPOAASWJBQMTNUYWGR4SCQAG6S2I4H6F7SJYY3DGB4GVRD4PX2G3IJYHLS27SZZZDNPBDPQJ46FIL45L46ZNTPUBU2RAQZ5BGN4UC3SM52PQI27262JJ5WFAO5OBBK
TOTP code: 47763
Programming code:
int ms = DateTime.now().millisecondsSinceEpoch;
var res = OTP.generateTOTPCode(otpToken, ms,algorithm: Algorithm.SHA1,interval: 30,isGoogle: true);
print("OTP Response: "+res.toString());
I am using version 1.0 of the library.
Thanks
Hello,
the recent update enforces crypto
to at least 3.0.2
. I assume that the actual requirement could be ^3.0.0
as there are probably no changes in 3.0.1 or 3.0.2 which are relevant to otp?
by having a less strict dependency it would allow users to update one dependency at a time.. right now I can't update because flutter_driver
depends on crypto 3.0.1
:
Because every version of flutter_driver from sdk depends on crypto 3.0.1 and otp >=3.1.0 depends on crypto ^3.0.2, flutter_driver from sdk is incompatible with otp >=3.1.0.
So, because authpass depends on both otp ^3.1.0 and flutter_driver from sdk, version solving failed.
pub get failed (1; So, because authpass depends on both otp ^3.1.0 and flutter_driver from sdk, version solving failed.)
thanks,
Herbert
I tested the package with the following page: https://2fas.com/check-token/
The generated secret is '2FASTEST'. Weirdly, the Package only generates the right OTP if I set isGoogle to true even if it's not a Google OTP
Hi,
thanks for your library. I try to understand how exactly totp generation works because i've got a user report about problems with some tokens.. authpass/authpass#67
What i don't understand is the padding, which is documented as "TOTP style padding", but i haven't found any mention of it in the actual RFC 6238 .. it only mentions:
Keys SHOULD be of the length of the HMAC output to facilitate
interoperability.
but not really how to deal with keys which are not the right length.. and if i'm not completely missing something, it also seems to do no padding in the reference implementation: https://tools.ietf.org/html/rfc6238#appendix-A
Maybe you could point me to the TOTP style padding spec? I just try to understand how it should work.
the only padding i've found whas that of the SHA-2 algorithms, which works quite differently
Pre-processing (Padding):
begin with the original message of length L bits
append a single '1' bit
append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512
append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bits
thanks,
Herbert
Version 3.0.0-nullsafety.0
wasn't published on pub, could you publish it please? I am getting constrain issues for the logging library that was removed.
static Uint8List _padSecret(Uint8List secret, int length) {
if (secret.length == length) return secret;
// ignore: prefer_collection_literals
final newList = <int>[];
for (var i = 0; i * secret.length < length; i++) {
newList.addAll(secret);
}
return Uint8List.fromList(newList.sublist(0, length));
}
{
uri: otpauth: //totp/sdfsdf: sdfsdf?secret=sdfsdf&issuer=sdfsdf&algorithm=sha1&digits=6&period=30,
secret: sdfsdf,
digits: 6,
period: 30,
lastUsedCounter: 0,
algorithm: sha1,
issuer: sdfsdf,
accountName: sdfsdf,
isTimerBased: true,
isArchive: false)
}
this function runs infinite
If the code starts with 0 it doesn't appear.
In readme and code's comment it is
OTP.generateTOTPCode(String secret, int currentTime, {int length: 6, int interval: 30, Algorithm algorithm: Algorithm.SHA1, bool isGoogle: false})
OTP.generateTOTPCodeString(String secret, int currentTime, {int length: 6, int interval: 30, Algorithm algorithm: Algorithm.SHA1, bool isGoogle: false})
/// Optional parameters to change the length of the code provided (default 6), interval (default 30), and hashing algorithm (default SHA1)
/// These settings are defaulted to the RFC standard but can be changed.
But actually it is SHA256:
static int generateTOTPCode(String secret, int time,
{int length = 6, int interval = 30, Algorithm algorithm = Algorithm.SHA256, bool isGoogle = false}) {
static int generateTOTPCodeString(String secret, int time,
{int length = 6, int interval = 30, Algorithm algorithm = Algorithm.SHA256, bool isGoogle = false}) {
Hello, I don't know if it's used correctly. I tried generate TOTPCodeString using the plugin, but it does not match the result of GoogleAuthenticator
@daegalus nice work with the plugin, it's really good!
That's not a issue, I'd like support for accessing the interval between changing one code to another.
I tried to create a timer to show the code expiry time, however, the plugin starts counting before the layout, so my timer is not accurate.
I had some problem about using android device in flutter
The following FormatException was thrown building Builder:
Invalid Base32 characters
Can I use this package on flutter ?
Pointycastle is great but crypto is even better.
Dart's native crypto library should be used for better maintained code and probably some performance fast paths to native code, also security guarantee.
crypto: https://pub.dev/packages/crypto
Using OTP 3.0.1
// secret = 'HBRGMMJWMQ3GKOLFHE2DOZRTHA2TSNBRGI2TGZRVMQ2TCZRXG5TDQNTEGBRDSZJT'
var topt = OTP.generateTOTPCodeString(secret, DateTime.now().millisecondsSinceEpoch, algorithm: Algorithm.SHA1);
684917
The TOTP is generated and immediately posted to the NodeJS server which takes the same secret and issues a call to a TOTP library (I tried these two libraries). Their TOTP outputs differ from the one generated by dart-otp. I did a time check on both server and app and the timestamps are within the same 30 second time period. Also tried the different algorithms (SHA256, SHA512) and DateTime.now().millisecond
NodeJS
// otplib 12.0.1 - defaults, SHA1, 30 sec interval
// https://www.npmjs.com/package/otplib
// secret = 'HBRGMMJWMQ3GKOLFHE2DOZRTHA2TSNBRGI2TGZRVMQ2TCZRXG5TDQNTEGBRDSZJT'
otplib.totp.generate(secret);
391142
// notp 2.0.3 - default algorithm unspecified but believe it is SHA1, 30 sec interval
// https://www.npmjs.com/package/notp
// secret = 'HBRGMMJWMQ3GKOLFHE2DOZRTHA2TSNBRGI2TGZRVMQ2TCZRXG5TDQNTEGBRDSZJT'
notp.totp.gen(secret));
391142
Note: the secret is just an example. It's a randomly generated 20 byte string in hex, text encoded (RFC4648) and then base32 encoded
Thanks first for making such great and clean OTP library, I've used this lib for a long time working pretty well, until recently, after upgrading to 2.1.0, exception occur when calling generateTOTPCodeString(secret, timeSinceEpochInMilliseconds, algorithm: Algorithm.SHA1)
Int64 accessor not supported by dart2js.
My environment config as below:
$ flutter --version
Flutter 1.17.0-3.3.pre • channel beta • https://github.com/flutter/flutter.git
Framework • revision 0da1ab0922 (4 days ago) • 2020-04-28 11:02:34 -0700
Engine • revision 376ad6a64b
Tools • Dart 2.8.0
Downgrading to 2.0.3 solved this issue.
So I guess this issue may be introduced by commit like 915b04f
Hello,
I'm trying to set up a app that receives a secret from a Node.js server that is using otplib. On their docs, the secret is a "base32 encoded hex secret key".
My problem is that when I create a HOTP
OTP.generateHOTPCode(_secret, _counter, algorithm: Algorithm.SHA256)
it generates a key, but it's different from the one on the server so it fails to verify it.
So I thought that maybe the secret is decoded differently on the 2 packages. How should I encode the secret on the server-side so that both packages produce the same output?
Due to the discovered collission of SHA-1, I think SHA-256 (which is used by Google Authenticator) should be the default algorithm for generating OTPs.
Also you might consider adding a function for constant time verification of OTPs. Otherwise many people just use standard comparison which opens up timing attacks.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.