public static Authenticator FromOtpAuthMigrationAuthenticator(OtpAuthMigration.Authenticator input) { string issuer; string username; // Google Auth may not have an issuer, just use the username instead if (String.IsNullOrEmpty(input.Issuer)) { issuer = input.Username.Trim().Truncate(32); username = null; } else { issuer = input.Issuer.Trim().Truncate(32); // For some odd reason the username field always follows a '[issuer]: [username]' format username = input.Username.Replace($"{input.Issuer}: ", "").Trim().Truncate(40); } var type = input.Type switch { OtpAuthMigration.Type.Totp => AuthenticatorType.Totp, OtpAuthMigration.Type.Hotp => AuthenticatorType.Hotp, _ => throw new InvalidAuthenticatorException() }; var algorithm = input.Algorithm switch { OtpAuthMigration.Algorithm.Sha1 => OtpHashMode.Sha1, _ => throw new InvalidAuthenticatorException() }; string secret; try { secret = Base32Encoding.ToString(input.Secret); secret = CleanSecret(secret); } catch { throw new InvalidAuthenticatorException(); } var auth = new Authenticator() { Issuer = issuer, Username = username, Algorithm = algorithm, Type = type, Secret = secret, Counter = input.Counter, Digits = DefaultDigits, Period = DefaultPeriod, Icon = Shared.Data.Icon.FindServiceKeyByName(issuer) }; auth.Validate(); return(auth); }
public static Authenticator FromOtpAuthUri(string uri) { var uriMatch = Regex.Match(Uri.UnescapeDataString(uri), @"^otpauth:\/\/([a-z]+)\/(.*)\?(.*)$"); if (!uriMatch.Success) { throw new ArgumentException("URI is not valid"); } var type = uriMatch.Groups[1].Value switch { "totp" => AuthenticatorType.Totp, "hotp" => AuthenticatorType.Hotp, _ => throw new InvalidAuthenticatorException() }; // Get the issuer and username if possible const string issuerNameExpr = @"^(.*):(.*)$"; var issuerName = Regex.Match(uriMatch.Groups[2].Value, issuerNameExpr); string issuer; string username; if (issuerName.Success) { issuer = issuerName.Groups[1].Value; username = issuerName.Groups[2].Value; } else { issuer = uriMatch.Groups[2].Value; username = ""; } var queryString = uriMatch.Groups[3].Value; var args = Regex.Matches(queryString, "([^?=&]+)(=([^&]*))?") .ToDictionary(x => x.Groups[1].Value, x => x.Groups[3].Value); var algorithm = OtpHashMode.Sha1; if (args.ContainsKey("algorithm")) { switch (args["algorithm"].ToUpper()) { case "SHA1": algorithm = OtpHashMode.Sha1; break; case "SHA256": algorithm = OtpHashMode.Sha256; break; case "SHA512": algorithm = OtpHashMode.Sha512; break; default: throw new InvalidAuthenticatorException(); } } var digits = args.ContainsKey("digits") ? Int32.Parse(args["digits"]) : DefaultDigits; var period = args.ContainsKey("period") ? Int32.Parse(args["period"]) : DefaultPeriod; var secret = CleanSecret(args["secret"]); var auth = new Authenticator { Secret = secret, Issuer = issuer.Trim().Truncate(IssuerMaxLength), Username = username.Trim().Truncate(UsernameMaxLength), Icon = Shared.Data.Icon.FindServiceKeyByName(issuer), Type = type, Algorithm = algorithm, Digits = digits, Period = period, Counter = 0 }; auth.Validate(); return(auth); }
public static Authenticator FromKeyUri(string uri) { const string uriExpr = @"^otpauth:\/\/([a-z]+)\/(.*?)\?(.*?)$"; var raw = Uri.UnescapeDataString(uri); var uriMatch = Regex.Match(raw, uriExpr); if (!uriMatch.Success) { throw new ArgumentException("URI is not valid"); } var type = uriMatch.Groups[1].Value == "totp" ? AuthenticatorType.Totp : AuthenticatorType.Hotp; // Get the issuer and username if possible const string issuerNameExpr = @"^(.*?):(.*?)$"; var issuerName = Regex.Match(uriMatch.Groups[2].Value, issuerNameExpr); string issuer; string username; if (issuerName.Success) { issuer = issuerName.Groups[1].Value; username = issuerName.Groups[2].Value; } else { issuer = uriMatch.Groups[2].Value; username = ""; } var queryString = uriMatch.Groups[3].Value; var args = Regex.Matches(queryString, "([^?=&]+)(=([^&]*))?") .ToDictionary(x => x.Groups[1].Value, x => x.Groups[3].Value); var algorithm = OtpHashMode.Sha1; if (args.ContainsKey("algorithm")) { switch (args["algorithm"].ToUpper()) { case "SHA1": algorithm = OtpHashMode.Sha1; break; case "SHA256": algorithm = OtpHashMode.Sha256; break; case "SHA512": algorithm = OtpHashMode.Sha512; break; default: throw new InvalidAuthenticatorException(); } } var digits = args.ContainsKey("digits") ? Int32.Parse(args["digits"]) : 6; var period = args.ContainsKey("period") ? Int32.Parse(args["period"]) : 30; var code = ""; for (var i = 0; i < digits; code += "-", i++) { ; } var secret = CleanSecret(args["secret"]); var auth = new Authenticator { Secret = secret, Issuer = issuer.Trim().Truncate(32), Username = username.Trim().Truncate(32), Icon = Icons.FindServiceKeyByName(issuer), Type = type, Algorithm = algorithm, Digits = digits, Period = period, Counter = 0, Code = code }; auth.Validate(); return(auth); }