totp_util.dart 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import 'package:ente_auth/models/code.dart';
  2. import 'package:flutter/foundation.dart';
  3. import 'package:otp/otp.dart' as otp;
  4. import 'package:steam_totp/steam_totp.dart';
  5. String getOTP(Code code) {
  6. if (code.type == Type.steam) {
  7. return _getSteamCode(code);
  8. }
  9. if (code.type == Type.hotp) {
  10. return _getHOTPCode(code);
  11. }
  12. return otp.OTP.generateTOTPCodeString(
  13. getSanitizedSecret(code.secret),
  14. DateTime.now().millisecondsSinceEpoch,
  15. length: code.digits,
  16. interval: code.period,
  17. algorithm: _getAlgorithm(code),
  18. isGoogle: true,
  19. );
  20. }
  21. String _getHOTPCode(Code code) {
  22. return otp.OTP.generateHOTPCodeString(
  23. getSanitizedSecret(code.secret),
  24. code.counter,
  25. length: code.digits,
  26. algorithm: _getAlgorithm(code),
  27. isGoogle: true,
  28. );
  29. }
  30. String _getSteamCode(Code code, [bool isNext = false]) {
  31. final SteamTOTP steamtotp = SteamTOTP(secret: code.secret);
  32. return steamtotp.generate(
  33. DateTime.now().millisecondsSinceEpoch ~/ 1000 + (isNext ? code.period : 0),
  34. );
  35. }
  36. String getNextTotp(Code code) {
  37. if (code.type == Type.steam) {
  38. return _getSteamCode(code, true);
  39. }
  40. return otp.OTP.generateTOTPCodeString(
  41. getSanitizedSecret(code.secret),
  42. DateTime.now().millisecondsSinceEpoch + code.period * 1000,
  43. length: code.digits,
  44. interval: code.period,
  45. algorithm: _getAlgorithm(code),
  46. isGoogle: true,
  47. );
  48. }
  49. otp.Algorithm _getAlgorithm(Code code) {
  50. switch (code.algorithm) {
  51. case Algorithm.sha256:
  52. return otp.Algorithm.SHA256;
  53. case Algorithm.sha512:
  54. return otp.Algorithm.SHA512;
  55. default:
  56. return otp.Algorithm.SHA1;
  57. }
  58. }
  59. String getSanitizedSecret(String secret) {
  60. return secret.toUpperCase().trim().replaceAll(' ', '');
  61. }
  62. String safeDecode(String value) {
  63. try {
  64. return Uri.decodeComponent(value);
  65. } catch (e) {
  66. // note: don't log the value, it might contain sensitive information
  67. debugPrint("Failed to decode $e");
  68. return value;
  69. }
  70. }