/// <summary> /// Verify and create the authenticator if needed /// </summary> /// <returns>true is successful</returns> private bool verifyAuthenticator(string privatekey) { if (string.IsNullOrEmpty(privatekey)) { return(false); } Authenticator.Name = nameField.Text; var authtype = "totp"; // if this is a URL, pull it down Uri uri; Match match; if (Regex.IsMatch(privatekey, "https?://.*") && Uri.TryCreate(privatekey, UriKind.Absolute, out uri)) { try { var request = (HttpWebRequest)WebRequest.Create(uri); request.AllowAutoRedirect = true; request.Timeout = 20000; request.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)"; using (var response = (HttpWebResponse)request.GetResponse()) { if (response.StatusCode == HttpStatusCode.OK && response.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase)) { using (var bitmap = (Bitmap)Image.FromStream(response.GetResponseStream())) { IBarcodeReader reader = new BarcodeReader(); var result = reader.Decode(bitmap); if (result != null) { privatekey = HttpUtility.UrlDecode(result.Text); } } } } } catch (Exception ex) { WinAuthForm.ErrorDialog(Owner, "Cannot load QR code image from " + privatekey, ex); return(false); } } else if ((match = Regex.Match(privatekey, @"data:image/([^;]+);base64,(.*)", RegexOptions.IgnoreCase)) .Success) { var imagedata = Convert.FromBase64String(match.Groups[2].Value); using (var ms = new MemoryStream(imagedata)) { using (var bitmap = (Bitmap)Image.FromStream(ms)) { IBarcodeReader reader = new BarcodeReader(); var result = reader.Decode(bitmap); if (result != null) { privatekey = HttpUtility.UrlDecode(result.Text); } } } } else if (IsValidFile(privatekey)) { // assume this is the image file using (var bitmap = (Bitmap)Image.FromFile(privatekey)) { IBarcodeReader reader = new BarcodeReader(); var result = reader.Decode(bitmap); if (result != null) { privatekey = result.Text; } } } // check for otpauth://, e.g. "otpauth://totp/[email protected]?secret=IHZJDKAEEC774BMUK3GX6SA" match = Regex.Match(privatekey, @"otpauth://([^/]+)/([^?]+)\?(.*)", RegexOptions.IgnoreCase); if (match.Success) { authtype = match.Groups[1].Value; // @todo we only handle totp (not hotp) if (string.Compare(authtype, "totp", true) != 0) { WinAuthForm.ErrorDialog(Owner, "Only time-based (TOTP) authenticators are supported when adding a Google Authenticator. Use the general \"Add Authenticator\" for counter-based (HOTP) authenticators."); return(false); } var label = match.Groups[2].Value; if (string.IsNullOrEmpty(label) == false) { Authenticator.Name = nameField.Text = label; } var qs = WinAuthHelper.ParseQueryString(match.Groups[3].Value); privatekey = qs["secret"] ?? privatekey; } // just get the hex chars privatekey = Regex.Replace(privatekey, @"[^0-9a-z]", "", RegexOptions.IgnoreCase); if (privatekey.Length == 0) { WinAuthForm.ErrorDialog(Owner, "The secret code is not valid"); return(false); } try { var auth = new GoogleAuthenticator(); auth.Enroll(privatekey); Authenticator.AuthenticatorData = auth; codeProgress.Visible = true; var key = Base32.getInstance().Encode(Authenticator.AuthenticatorData.SecretKey); secretCodeField.Text = Regex.Replace(key, ".{3}", "$0 ").Trim(); codeField.Text = auth.CurrentCode; if (auth.ServerTimeDiff == 0L && SyncErrorWarned == false) { SyncErrorWarned = true; MessageBox.Show(this, string.Format(strings.AuthenticatorSyncError, "Google"), WinAuthMain.APPLICATION_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Warning); } } catch (Exception irre) { WinAuthForm.ErrorDialog(Owner, "Unable to create the authenticator. The secret code is probably invalid.", irre); return(false); } return(true); }
/// <summary> /// Verify and create the authenticator if needed /// </summary> /// <returns>true is successful</returns> private bool verifyAuthenticator(string privatekey) { if (string.IsNullOrEmpty(privatekey) == true) { return false; } this.Authenticator.Name = nameField.Text; string authtype = "totp"; // if this is a URL, pull it down Uri uri; Match match; if (Regex.IsMatch(privatekey, "https?://.*") == true && Uri.TryCreate(privatekey, UriKind.Absolute, out uri) == true) { try { var request = (HttpWebRequest)WebRequest.Create(uri); request.AllowAutoRedirect = true; request.Timeout = 20000; request.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)"; using (var response = (HttpWebResponse)request.GetResponse()) { if (response.StatusCode == HttpStatusCode.OK && response.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase) == true) { using (Bitmap bitmap = (Bitmap)Bitmap.FromStream(response.GetResponseStream())) { IBarcodeReader reader = new BarcodeReader(); var result = reader.Decode(bitmap); if (result != null) { privatekey = HttpUtility.UrlDecode(result.Text); } } } } } catch (Exception ex) { WinAuthForm.ErrorDialog(this.Owner, "Cannot load QR code image from " + privatekey, ex); return false; } } else if ((match = Regex.Match(privatekey, @"data:image/([^;]+);base64,(.*)", RegexOptions.IgnoreCase)).Success == true) { byte[] imagedata = Convert.FromBase64String(match.Groups[2].Value); using (MemoryStream ms = new MemoryStream(imagedata)) { using (Bitmap bitmap = (Bitmap)Bitmap.FromStream(ms)) { IBarcodeReader reader = new BarcodeReader(); var result = reader.Decode(bitmap); if (result != null) { privatekey = HttpUtility.UrlDecode(result.Text); } } } } else if (IsValidFile(privatekey) == true) { // assume this is the image file using (Bitmap bitmap = (Bitmap)Bitmap.FromFile(privatekey)) { IBarcodeReader reader = new BarcodeReader(); var result = reader.Decode(bitmap); if (result != null) { privatekey = result.Text; } } } // check for otpauth://, e.g. "otpauth://totp/[email protected]?secret=IHZJDKAEEC774BMUK3GX6SA" match = Regex.Match(privatekey, @"otpauth://([^/]+)/([^?]+)\?(.*)", RegexOptions.IgnoreCase); if (match.Success == true) { authtype = match.Groups[1].Value; // @todo we only handle totp (not hotp) if (string.Compare(authtype, "totp", true) != 0) { WinAuthForm.ErrorDialog(this.Owner, "Only time-based (TOTP) authenticators are supported when adding a Google Authenticator. Use the general \"Add Authenticator\" for counter-based (HOTP) authenticators."); return false; } string label = match.Groups[2].Value; if (string.IsNullOrEmpty(label) == false) { this.Authenticator.Name = this.nameField.Text = label; } NameValueCollection qs = WinAuthHelper.ParseQueryString(match.Groups[3].Value); privatekey = qs["secret"] ?? privatekey; } // just get the hex chars privatekey = Regex.Replace(privatekey, @"[^0-9a-z]", "", RegexOptions.IgnoreCase); if (privatekey.Length == 0) { WinAuthForm.ErrorDialog(this.Owner, "The secret code is not valid"); return false; } try { GoogleAuthenticator auth = new GoogleAuthenticator(); auth.Enroll(privatekey); this.Authenticator.AuthenticatorData = auth; codeProgress.Visible = true; string key = Base32.getInstance().Encode(this.Authenticator.AuthenticatorData.SecretKey); this.secretCodeField.Text = Regex.Replace(key, ".{3}", "$0 ").Trim(); this.codeField.Text = auth.CurrentCode; if (auth.ServerTimeDiff == 0L && SyncErrorWarned == false) { SyncErrorWarned = true; MessageBox.Show(this, string.Format(strings.AuthenticatorSyncError, "Google"), WinAuthMain.APPLICATION_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Warning); } } catch (Exception irre) { WinAuthForm.ErrorDialog(this.Owner, "Unable to create the authenticator. The secret code is probably invalid.", irre); return false; } return true; }