/// <summary> /// Checks if password has been compromised using PwnedPasswords API. /// </summary> /// <param name="password">Password to check</param> /// <returns>True if strong password, false if weak password</returns> public async Task <ResponseDto <bool> > IsPasswordValidAsync(string password) { var passwordHash = ""; // Hash password with SHA1. using (var hasher = new SHA1Cng()) { passwordHash = BitConverter.ToString(hasher.ComputeHash(Encoding.UTF8.GetBytes(password))); passwordHash = passwordHash.Replace("-", ""); } ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // Get first 5 characters of hash and send it as part of the url for a get request. var prefixHash = passwordHash.Substring(0, 5); var request = new GetRequestService($"{ApiConstants.PWNED_PASSWORD_URL}{prefixHash}"); var response = await new BackoffRequest(request).TryExecute(); var responseBody = await response.Content.ReadAsStringAsync(); // Separate response by lines into an array of strings var splitResponse = responseBody.Split(new[] { Environment.NewLine }, StringSplitOptions.None); // Iterate through every line of response and check if hash matches and, if so, if the count // falls within valid range. foreach (var line in splitResponse) { // Splits the line by the hash suffix and the breach count. // An example line would be: // 1E4C9B93F3F0682250B6CF8331B7EE68FD8:3303003 var splitLine = line.Split(':'); var suffixHash = splitLine[0]; // If password hash does not match, continue to next iteration. if (!passwordHash.Equals(prefixHash + suffixHash.ToUpper())) { continue; } var breachCount = int.Parse(splitLine[1]); var isPasswordValid = true; // flag password as invalid if the breach count is greater than the limit if (breachCount > _maxValidCount) { isPasswordValid = false; } return(new ResponseDto <bool>() { Data = isPasswordValid }); } // If password has has no matches, it is valid. return(new ResponseDto <bool>() { Data = true }); }
/// <summary> /// Calculates offset from UTC from geocoordinates using Google's Timezone API. /// </summary> /// <param name="coordinates">Coordinates of location to check time zone.</param> /// <returns>Offset of time (in seconds) from UTC.</returns> public async Task <ResponseDto <int> > GetOffsetAsync(IGeoCoordinates coordinates) { // Get current date in seconds to determine if its DST for Google's API. var baseTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Local); var timeStamp = (int)DateTime.Now.Subtract(baseTime).TotalSeconds; // Retrieve key from configuration and build url for get request. var key = ConfigurationManager.AppSettings[GoogleApiConstants.GOOGLE_TIMEZONE_API_KEYWORD]; var url = BuildUrl(coordinates, key, timeStamp); // Send get request and parse response var request = new GetRequestService(url); var response = await new GoogleBackoffRequest(request).TryExecute(); var responseJson = await response.Content.ReadAsStringAsync(); var responseObj = JsonConvert.DeserializeObject <GoogleTimeZoneDto>(responseJson); if (responseObj.status != GoogleApiConstants.GOOGLE_GEOCODE_STATUS_OK) { if (responseObj.status == GoogleApiConstants.GOOGLE_TIMEZONE_STATUS_ZERO_RESULTS) { return(new ResponseDto <int>() { Error = GoogleApiConstants.GOOGLE_TIMEZONE_ERROR_INVALID_ADDRESS }); } return(new ResponseDto <int>() { Error = GoogleApiConstants.GOOGLE_TIMEZONE_ERROR_GENERAL }); } return(new ResponseDto <int>() { Data = responseObj.rawOffset + responseObj.dstOffset }); }
/// <summary> /// Converts an address into geocoordinates using Google's Geocoding API. /// </summary> /// <param name="address">Address to geocode.</param> /// <returns>Coordinates of address.</returns> public async Task <ResponseDto <IGeoCoordinates> > GeocodeAsync(IAddress address) { try { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // Retrieve key from configuration and build url for the get request. var key = ConfigurationManager.AppSettings[GoogleApiConstants.GOOGLE_GEOCODE_API_KEYWORD]; var url = BuildUrl(address, key); // Send get request and parse the response var request = new GetRequestService(url); var response = await new GoogleBackoffRequest(request).TryExecute(); var responseJson = await response.Content.ReadAsStringAsync(); var responseObj = JsonConvert.DeserializeObject <GoogleGeocodingDto>(responseJson); if (responseObj.status != GoogleApiConstants.GOOGLE_GEOCODE_STATUS_OK) { if (responseObj.status == GoogleApiConstants.GOOGLE_GEOCODE_STATUS_ZERO_RESULTS) { return(new ResponseDto <IGeoCoordinates>() { Error = GoogleApiConstants.GOOGLE_GEOCODE_ERROR_INVALID_ADDRESS }); } return(new ResponseDto <IGeoCoordinates>() { Error = GoogleApiConstants.GOOGLE_GEOCODE_ERROR_GENERAL }); } var result = responseObj.results[0]; foreach (var addresses in responseObj.results[0].address_components) { foreach (var type in addresses.types) { if (type != GoogleApiConstants.GOOGLE_GEOCODE_TYPE_STREET) { continue; } var lat = result.geometry.location.lat; var lng = result.geometry.location.lng; var geoCoordinates = new GeoCoordinates(lat, lng); return(new ResponseDto <IGeoCoordinates>() { Data = geoCoordinates }); } } return(new ResponseDto <IGeoCoordinates>() { Error = GoogleApiConstants.GOOGLE_GEOCODE_ERROR_INVALID_ADDRESS }); } catch { return(new ResponseDto <IGeoCoordinates>() { Error = GoogleApiConstants.GOOGLE_GEOCODE_ERROR_GENERAL }); } }