otp_uri.dart 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import 'otpauth_migration.dart';
  2. import 'totp_algorithm.dart';
  3. import 'totp_item.dart' show TotpItem;
  4. /// Parses TOTP key URI into TOTPItems.
  5. ///
  6. /// Reference:
  7. /// * https://github.com/google/google-authenticator/wiki/Key-Uri-Format
  8. class OtpUri {
  9. /// Parses a TOTP key URI and returns a TOTP object
  10. static TotpItem fromUri(String uri) {
  11. // Use dart-core/Uri to parse
  12. var parsed = Uri.parse(uri);
  13. // Check scheme
  14. if (parsed.scheme != "otpauth") {
  15. try {
  16. final otp_auth_parser = OtpAuthMigration();
  17. List<String> parseds = otp_auth_parser.decode(uri);
  18. parsed = Uri.parse(parseds.first);
  19. } catch (e) {
  20. throw FormatException("Not OTP URI");
  21. }
  22. }
  23. if (parsed.authority != "totp" && parsed.authority != "hotp") {
  24. throw FormatException("Unsupported authority");
  25. }
  26. // Extract issuer/account name
  27. if (parsed.pathSegments.length > 1) {
  28. throw FormatException("Should have more than 1 path segment");
  29. }
  30. var pathSplit = parsed.pathSegments[0].split(':');
  31. var issuer = pathSplit[0];
  32. var accountName = pathSplit.length > 1 ? pathSplit[1] : '';
  33. // Extract algorithm, digits, period and secret
  34. var algorithm = "sha1";
  35. var digits = 6;
  36. var period = 30;
  37. var secret = "";
  38. if (!parsed.queryParameters.containsKey("secret")) {
  39. throw FormatException("Query parameter does not contain secret");
  40. }
  41. secret = parsed.queryParameters["secret"]!;
  42. if (parsed.queryParameters.containsKey("algorithm")) {
  43. algorithm = parsed.queryParameters["algorithm"]!.toLowerCase();
  44. if (algorithm != "sha1" &&
  45. algorithm != "sha256" &&
  46. algorithm != "sha512") {
  47. throw FormatException("Unrecognised algorithm");
  48. }
  49. }
  50. if (parsed.queryParameters.containsKey("digits")) {
  51. digits = int.parse(parsed.queryParameters["digits"]!);
  52. }
  53. if (parsed.queryParameters.containsKey("period")) {
  54. period = int.parse(parsed.queryParameters["period"]!);
  55. }
  56. try {
  57. return TotpItem.newTotpItem(secret, digits, period,
  58. OtpHashAlgorithm.fromString(algorithm), issuer, accountName);
  59. } catch (error) {
  60. throw FormatException("Incorrect parameters");
  61. }
  62. }
  63. }