2019-04-18 00:10:21 +03:00
|
|
|
|
using Bit.Core.Abstractions;
|
|
|
|
|
using Bit.Core.Exceptions;
|
|
|
|
|
using Bit.Core.Models.Response;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Net.Http;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace Bit.Core.Services
|
|
|
|
|
{
|
|
|
|
|
public class AuditService : IAuditService
|
|
|
|
|
{
|
|
|
|
|
private const string PwnedPasswordsApi = "https://api.pwnedpasswords.com/range/";
|
|
|
|
|
|
|
|
|
|
private readonly ICryptoFunctionService _cryptoFunctionService;
|
|
|
|
|
private readonly IApiService _apiService;
|
|
|
|
|
|
2019-04-27 07:19:44 +03:00
|
|
|
|
private HttpClient _httpClient = new HttpClient();
|
2019-04-18 00:10:21 +03:00
|
|
|
|
|
|
|
|
|
public AuditService(
|
|
|
|
|
ICryptoFunctionService cryptoFunctionService,
|
|
|
|
|
IApiService apiService)
|
|
|
|
|
{
|
|
|
|
|
_cryptoFunctionService = cryptoFunctionService;
|
|
|
|
|
_apiService = apiService;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<int> PasswordLeakedAsync(string password)
|
|
|
|
|
{
|
|
|
|
|
var hashBytes = await _cryptoFunctionService.HashAsync(password, Enums.CryptoHashAlgorithm.Sha1);
|
2019-05-01 17:33:48 +03:00
|
|
|
|
var hash = BitConverter.ToString(hashBytes).Replace("-", string.Empty).ToUpperInvariant();
|
2019-04-18 00:10:21 +03:00
|
|
|
|
var hashStart = hash.Substring(0, 5);
|
|
|
|
|
var hashEnding = hash.Substring(5);
|
|
|
|
|
var response = await _httpClient.GetAsync(string.Concat(PwnedPasswordsApi, hashStart));
|
|
|
|
|
var leakedHashes = await response.Content.ReadAsStringAsync();
|
|
|
|
|
var match = leakedHashes.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)
|
|
|
|
|
.FirstOrDefault(v => v.Split(':')[0] == hashEnding);
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (match != null && int.TryParse(match.Split(':')[1], out var matchCount))
|
2019-04-18 00:10:21 +03:00
|
|
|
|
{
|
|
|
|
|
return matchCount;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<List<BreachAccountResponse>> BreachedAccountsAsync(string username)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
return await _apiService.GetHibpBreachAsync(username);
|
|
|
|
|
}
|
2020-03-28 16:16:28 +03:00
|
|
|
|
catch (ApiException e)
|
2019-04-18 00:10:21 +03:00
|
|
|
|
{
|
2020-03-28 16:16:28 +03:00
|
|
|
|
if (e.Error != null && e.Error.StatusCode == System.Net.HttpStatusCode.NotFound)
|
2019-04-18 00:10:21 +03:00
|
|
|
|
{
|
|
|
|
|
return new List<BreachAccountResponse>();
|
|
|
|
|
}
|
|
|
|
|
throw e;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|