exposed password check

This commit is contained in:
Kyle Spearrin 2019-04-27 00:19:44 -04:00
parent 5e114e8074
commit 8fa2ef863f
6 changed files with 88 additions and 8 deletions

View file

@ -49,7 +49,7 @@ namespace Bit.App
} }
else else
{ {
await MainPage.DisplayAlert(details.Title, details.Text, details.ConfirmText); await MainPage.DisplayAlert(details.Title, details.Text, confirmText);
} }
_messagingService.Send("showDialogResolve", new Tuple<int, bool>(details.DialogId, confirmed)); _messagingService.Send("showDialogResolve", new Tuple<int, bool>(details.DialogId, confirmed));
} }

View file

@ -83,6 +83,7 @@
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Label <Label
Text="{u:I18n Password}" Text="{u:I18n Password}"
@ -101,12 +102,19 @@
Grid.Row="1" Grid.Row="1"
Grid.Column="0" Grid.Column="0"
IsVisible="{Binding ShowPassword}" /> IsVisible="{Binding ShowPassword}" />
<controls:FaButton
StyleClass="box-row-button, box-row-button-platform"
Text="&#xf058;"
Command="{Binding CheckPasswordCommand}"
Grid.Row="0"
Grid.Column="1"
Grid.RowSpan="2" />
<controls:FaButton <controls:FaButton
StyleClass="box-row-button, box-row-button-platform" StyleClass="box-row-button, box-row-button-platform"
Text="{Binding ShowPasswordIcon}" Text="{Binding ShowPasswordIcon}"
Command="{Binding TogglePasswordCommand}" Command="{Binding TogglePasswordCommand}"
Grid.Row="0" Grid.Row="0"
Grid.Column="1" Grid.Column="2"
Grid.RowSpan="2" /> Grid.RowSpan="2" />
<controls:FaButton <controls:FaButton
StyleClass="box-row-button, box-row-button-platform" StyleClass="box-row-button, box-row-button-platform"
@ -114,7 +122,7 @@
Command="{Binding CopyCommand}" Command="{Binding CopyCommand}"
CommandParameter="LoginPassword" CommandParameter="LoginPassword"
Grid.Row="0" Grid.Row="0"
Grid.Column="2" Grid.Column="3"
Grid.RowSpan="2" /> Grid.RowSpan="2" />
</Grid> </Grid>
<BoxView StyleClass="box-row-separator" /> <BoxView StyleClass="box-row-separator" />

View file

@ -20,6 +20,7 @@ namespace Bit.App.Pages
private readonly IUserService _userService; private readonly IUserService _userService;
private readonly ITotpService _totpService; private readonly ITotpService _totpService;
private readonly IPlatformUtilsService _platformUtilsService; private readonly IPlatformUtilsService _platformUtilsService;
private readonly IAuditService _auditService;
private CipherView _cipher; private CipherView _cipher;
private List<ViewFieldViewModel> _fields; private List<ViewFieldViewModel> _fields;
private bool _canAccessPremium; private bool _canAccessPremium;
@ -38,11 +39,13 @@ namespace Bit.App.Pages
_userService = ServiceContainer.Resolve<IUserService>("userService"); _userService = ServiceContainer.Resolve<IUserService>("userService");
_totpService = ServiceContainer.Resolve<ITotpService>("totpService"); _totpService = ServiceContainer.Resolve<ITotpService>("totpService");
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"); _platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
_auditService = ServiceContainer.Resolve<IAuditService>("auditService");
CopyCommand = new Command<string>((id) => CopyAsync(id, null)); CopyCommand = new Command<string>((id) => CopyAsync(id, null));
CopyUriCommand = new Command<LoginUriView>(CopyUriAsync); CopyUriCommand = new Command<LoginUriView>(CopyUri);
LaunchUriCommand = new Command<LoginUriView>(LaunchUriAsync); LaunchUriCommand = new Command<LoginUriView>(LaunchUri);
TogglePasswordCommand = new Command(TogglePassword); TogglePasswordCommand = new Command(TogglePassword);
ToggleCardCodeCommand = new Command(ToggleCardCode); ToggleCardCodeCommand = new Command(ToggleCardCode);
CheckPasswordCommand = new Command(CheckPasswordAsync);
PageTitle = AppResources.ViewItem; PageTitle = AppResources.ViewItem;
} }
@ -52,6 +55,7 @@ namespace Bit.App.Pages
public Command LaunchUriCommand { get; set; } public Command LaunchUriCommand { get; set; }
public Command TogglePasswordCommand { get; set; } public Command TogglePasswordCommand { get; set; }
public Command ToggleCardCodeCommand { get; set; } public Command ToggleCardCodeCommand { get; set; }
public Command CheckPasswordCommand { get; set; }
public string CipherId { get; set; } public string CipherId { get; set; }
public CipherView Cipher public CipherView Cipher
{ {
@ -221,6 +225,25 @@ namespace Bit.App.Pages
} }
} }
private async void CheckPasswordAsync()
{
if(string.IsNullOrWhiteSpace(Cipher.Login?.Password))
{
return;
}
await _deviceActionService.ShowLoadingAsync(AppResources.CheckingPassword);
var matches = await _auditService.PasswordLeakedAsync(Cipher.Login.Password);
await _deviceActionService.HideLoadingAsync();
if(matches > 0)
{
await _platformUtilsService.ShowDialogAsync(string.Format(AppResources.PasswordExposed, matches));
}
else
{
await _platformUtilsService.ShowDialogAsync(AppResources.PasswordSafe);
}
}
private async void CopyAsync(string id, string text = null) private async void CopyAsync(string id, string text = null)
{ {
string name = null; string name = null;
@ -254,12 +277,12 @@ namespace Bit.App.Pages
} }
} }
private void CopyUriAsync(LoginUriView uri) private void CopyUri(LoginUriView uri)
{ {
CopyAsync("LoginUri", uri.Uri); CopyAsync("LoginUri", uri.Uri);
} }
private void LaunchUriAsync(LoginUriView uri) private void LaunchUri(LoginUriView uri)
{ {
if(uri.CanLaunch) if(uri.CanLaunch)
{ {

View file

@ -834,6 +834,24 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Checking password....
/// </summary>
internal static string CheckingPassword {
get {
return ResourceManager.GetString("CheckingPassword", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Check if password has been exposed..
/// </summary>
internal static string CheckPassword {
get {
return ResourceManager.GetString("CheckPassword", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Choose File. /// Looks up a localized string similar to Choose File.
/// </summary> /// </summary>
@ -2580,6 +2598,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to This password has been exposed {0} time(s) in data breaches. You should change it..
/// </summary>
internal static string PasswordExposed {
get {
return ResourceManager.GetString("PasswordExposed", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Password generated.. /// Looks up a localized string similar to Password generated..
/// </summary> /// </summary>
@ -2625,6 +2652,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to This password was not found in any known data breaches. It should be safe to use..
/// </summary>
internal static string PasswordSafe {
get {
return ResourceManager.GetString("PasswordSafe", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Phone. /// Looks up a localized string similar to Phone.
/// </summary> /// </summary>

View file

@ -1368,4 +1368,17 @@
<value>URIs</value> <value>URIs</value>
<comment>Plural form of a URI</comment> <comment>Plural form of a URI</comment>
</data> </data>
<data name="CheckingPassword" xml:space="preserve">
<value>Checking password...</value>
<comment>A loading message when doing an exposed password check.</comment>
</data>
<data name="CheckPassword" xml:space="preserve">
<value>Check if password has been exposed.</value>
</data>
<data name="PasswordExposed" xml:space="preserve">
<value>This password has been exposed {0} time(s) in data breaches. You should change it.</value>
</data>
<data name="PasswordSafe" xml:space="preserve">
<value>This password was not found in any known data breaches. It should be safe to use.</value>
</data>
</root> </root>

View file

@ -16,7 +16,7 @@ namespace Bit.Core.Services
private readonly ICryptoFunctionService _cryptoFunctionService; private readonly ICryptoFunctionService _cryptoFunctionService;
private readonly IApiService _apiService; private readonly IApiService _apiService;
private HttpClient _httpClient; private HttpClient _httpClient = new HttpClient();
public AuditService( public AuditService(
ICryptoFunctionService cryptoFunctionService, ICryptoFunctionService cryptoFunctionService,