daegalus / dart-otp

RFC6238 Time-Based One-Time Password / Google Authenticator Library
MIT License
100 stars 25 forks source link

TOTP generated codes are not the same generated by other Authenticators. #37

Closed joepoe closed 2 years ago

joepoe commented 2 years ago

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;
  }
daegalus commented 2 years ago

Algorithm needs to be SHA1 and isGoogle needs to be true for Google authenticator compatibility.

Google authenticator does not follow the RFC spec accurately.

joepoe commented 2 years ago

You're a star! I should have known. Thanks a million.

tjalilpour commented 1 year ago

thanks a lot for solution, it works by adding isGoogle true