首页 > 解决方案 > Flutter:如何同步 TOTP 代码?

问题描述

我正在编写一个非常简单的 2FA 应用程序,它为给定的密钥、数字、间隔和算法生成 TOTP 代码。

但是,我对数学有困难,我不知道如何构造生成 TOTP 代码的算法

我正在使用 Flutter BLoC 库以 BLoC 模式编写整个应用程序。

看看这个视频,应用程序会生成一个间隔为 30 秒的代码,但是进度指示器不是从 0 秒开始,而是从每 30 秒的一个时间开始,例如:13:00:00 和当 30 秒过去 (13:00:30) 时,它会生成另一个代码。

视频:https ://streamable.com/u7vhcg

现在,当涉及到我的应用程序时,它会生成代码,但它们没有同步。我该怎么做,它会生成代码,但每个代码都是同步的?

我的应用程序视频:https ://streamable.com/zn3pnf

如您所见,TOTP 代码未同步。我该怎么做才能同步它们?

如果您想查看更多代码,请告诉我。

代码

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');
        }
      }
    }
  }
}

标签: flutterdartbloc

解决方案


这不是订阅 Timer.periodic 的问题吗?

你所在集团之外的东西应该:

  1. 从系统时钟(日期时间)读取当前秒数(您将拥有计数器的起始位置)

  2. 订阅 Timer.periodic(Duration(seconds: 1), (Timer t) => _handleClocksTick());

  3. _handleClocksTick() - 检查递增的计数器是否可以被 30 整除?

3.1。如果是,则 _bloc.add(GetNewCodeEvent); 重置(计数器);

嗯...我认为您的柜台应该由您的集团处理。这将是更好的解决方案。

像这种情况下的第一个解决方案在颤动上显示运行时钟


推荐阅读