bitwarden-android/src/App/Services/PasswordGenerationService.cs

179 lines
6.2 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bit.App.Abstractions;
using Plugin.Settings.Abstractions;
namespace Bit.App.Services
{
public class PasswordGenerationService : IPasswordGenerationService
{
private readonly ISettings _settings;
private Random _random = new Random();
public PasswordGenerationService(ISettings settings)
{
_settings = settings;
}
public string GeneratePassword(
int? length = null,
bool? uppercase = null,
bool? lowercase = null,
bool? numbers = null,
bool? special = null,
bool? ambiguous = null,
int? minUppercase = null,
int? minLowercase = null,
int? minNumbers = null,
int? minSpecial = null)
{
int minUppercaseValue = minUppercase.GetValueOrDefault(1),
minLowercaseValue = minLowercase.GetValueOrDefault(1),
minNumbersValue = minNumbers.GetValueOrDefault(_settings.GetValueOrDefault(Constants.PasswordGeneratorMinNumbers, 1)),
minSpecialValue = minSpecial.GetValueOrDefault(_settings.GetValueOrDefault(Constants.PasswordGeneratorMinSpecial, 1)),
lengthValue = length.GetValueOrDefault(_settings.GetValueOrDefault(Constants.PasswordGeneratorLength, 10));
bool uppercaseValue = uppercase.GetValueOrDefault(_settings.GetValueOrDefault(Constants.PasswordGeneratorUppercase, true)),
lowercaseValue = lowercase.GetValueOrDefault(_settings.GetValueOrDefault(Constants.PasswordGeneratorLowercase, true)),
numbersValue = numbers.GetValueOrDefault(_settings.GetValueOrDefault(Constants.PasswordGeneratorNumbers, true)),
specialValue = special.GetValueOrDefault(_settings.GetValueOrDefault(Constants.PasswordGeneratorSpecial, true)),
ambiguousValue = ambiguous.GetValueOrDefault(_settings.GetValueOrDefault(Constants.PasswordGeneratorAmbiguous, false));
// Sanitize
if(uppercaseValue && minUppercaseValue < 0)
{
minUppercaseValue = 1;
}
if(lowercaseValue && minLowercaseValue < 0)
{
minLowercaseValue = 1;
}
if(numbersValue && minNumbersValue < 0)
{
minNumbersValue = 1;
}
if(specialValue && minSpecialValue < 0)
{
minSpecialValue = 1;
}
if(lengthValue < 1)
{
lengthValue = 10;
}
var minLength = minUppercaseValue + minLowercaseValue + minNumbersValue + minSpecialValue;
if(lengthValue < minLength)
{
lengthValue = minLength;
}
var positionsBuilder = new StringBuilder();
if(lowercaseValue && minLowercaseValue > 0)
{
for(int i = 0; i < minLowercaseValue; i++)
{
positionsBuilder.Append("l");
}
}
if(uppercaseValue && minUppercaseValue > 0)
{
for(int i = 0; i < minUppercaseValue; i++)
{
positionsBuilder.Append("u");
}
}
if(numbersValue && minNumbersValue > 0)
{
for(int i = 0; i < minNumbersValue; i++)
{
positionsBuilder.Append("n");
}
}
if(specialValue && minSpecialValue > 0)
{
for(int i = 0; i < minSpecialValue; i++)
{
positionsBuilder.Append("s");
}
}
while(positionsBuilder.Length < lengthValue)
{
positionsBuilder.Append("a");
}
// Shuffle
var positions = positionsBuilder.ToString().ToCharArray().OrderBy(a => _random.Next()).ToArray();
// Build out other character sets
var allCharSet = string.Empty;
var lowercaseCharSet = "abcdefghijkmnopqrstuvwxyz";
if(ambiguousValue)
{
lowercaseCharSet = string.Concat(lowercaseCharSet, "l");
}
if(lowercaseValue)
{
allCharSet = string.Concat(allCharSet, lowercaseCharSet);
}
var uppercaseCharSet = "ABCDEFGHIJKLMNPQRSTUVWXYZ";
if(ambiguousValue)
{
uppercaseCharSet = string.Concat(uppercaseCharSet, "O");
}
if(uppercaseValue)
{
allCharSet = string.Concat(allCharSet, uppercaseCharSet);
}
var numberCharSet = "23456789";
if(ambiguousValue)
{
numberCharSet = string.Concat(numberCharSet, "01");
}
if(numbersValue)
{
allCharSet = string.Concat(allCharSet, numberCharSet);
}
var specialCharSet = "!@#$%^&*";
if(specialValue)
{
allCharSet = string.Concat(allCharSet, specialCharSet);
}
var password = new StringBuilder();
for(var i = 0; i < lengthValue; i++)
{
string positionChars = string.Empty;
switch(positions[i])
{
case 'l':
positionChars = lowercaseCharSet;
break;
case 'u':
positionChars = uppercaseCharSet;
break;
case 'n':
positionChars = numberCharSet;
break;
case 's':
positionChars = specialCharSet;
break;
case 'a':
positionChars = allCharSet;
break;
}
var randomCharIndex = _random.Next(0, positionChars.Length - 1);
password.Append(positionChars[randomCharIndex]);
}
return password.ToString();
}
}
}