I'm writing a very simple 2FA application, which generates TOTP codes for a given secret key, digits, interval and algorithm.
However, I have a hard time with maths, and I do not know how to construct the algorithm for generating the TOTP code
I'm writing the whole app in BLoC pattern using the Flutter BLoC library.
Have a look at this video, the app generates a code which has an interval of 30 seconds, however the progress indicator doesn't start from 0 seconds, but it starts from a time every 30 seconds for example: 13:00:00 and when 30 seconds pass (13:00:30), it generates another code.
Video: https://streamable.com/u7vhcg
Now, when it comes to my application, it generates codes, but they're not synced. How do I do it like that, that it generates codes, but every code is synced?
Vide of my app: https://streamable.com/zn3pnf
As you see, the TOTP codes are not synced. How do I do that, so they will be synced?
Let me know if you want to see more code.
Code
totp_generator_bloc.dart
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:dart_otp/dart_otp.dart';
import 'package:duckie/models/code/code_model.dart';
import 'package:hive/hive.dart';
import 'package:meta/meta.dart';
part 'totp_generator_event.dart';
part 'totp_generator_state.dart';
class TotpGeneratorBloc extends Bloc<TotpGeneratorEvent, TotpGeneratorState> {
TotpGeneratorBloc() : super(TotpGeneratorInitial());
@override
Stream<TotpGeneratorState> mapEventToState(
TotpGeneratorEvent event,
) async* {
if (event is GetTotpItemsEvent) {
Box box = Hive.box('totpmodel');
List totpItems = [];
for (var totpItem in box.values) {
final String secret = totpItem.secret;
final int digits = int.parse(totpItem.digits);
final int interval = int.parse(totpItem.interval);
final String algorithmString = totpItem.algorithm;
final String accountName = totpItem.accountName;
int timeStamp = totpItem.timeStamp;
OTPAlgorithm algorithm = OTPAlgorithm.SHA1;
switch (algorithmString) {
case 'sha1':
algorithm = OTPAlgorithm.SHA1;
break;
case 'sha256':
algorithm = OTPAlgorithm.SHA256;
break;
case 'sha384':
algorithm = OTPAlgorithm.SHA384;
break;
case 'sha512':
algorithm = OTPAlgorithm.SHA512;
break;
}
final TOTP totp = TOTP(
secret: secret,
digits: digits,
interval: interval,
algorithm: algorithm,
);
try {
final String otp =
totp.value(date: DateTime.fromMillisecondsSinceEpoch(timeStamp));
totpItems.add(CodeModel(otp, interval, 0, accountName));
yield TotpGeneratorFinal(totpItems);
} catch (error) {
yield TotpGeneratorError('totp-fail-title', 'totp-fail-content');
}
}
}
}
}