Skip to content

Commit

Permalink
added more input validation
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulMiami committed Jul 8, 2016
1 parent 4515c13 commit e94ab89
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace PaulMiami.AspNetCore.Authentication.Authenticator
public class AuthenticatorService
{
private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private static readonly int[] TenPow = new[] { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
private static readonly int[] TenPow = new[] { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
private AuthenticatorServiceOptions _options;
private ISystemTime _systemTime;

Expand All @@ -25,6 +25,12 @@ public AuthenticatorService(IOptions<AuthenticatorServiceOptions> options, ISyst

options.Value.Issuer.CheckMandatoryOption(nameof(options.Value.Issuer));

if (options.Value.NumberOfDigits < 6 || options.Value.NumberOfDigits > 8)
throw new ArgumentException(Resources.Exception_InvalidNumberOfDigits);

if (options.Value.PeriodInSeconds < 30)
throw new ArgumentException(Resources.Exception_InvalidPeriodInSeconds);

_options = options.Value;
_systemTime = systemTime;
}
Expand All @@ -47,13 +53,19 @@ public string GetUri(string userIdentifier, byte[] secret)
_options.PeriodInSeconds);
}

public int GetCode(HashAlgorithm hashAlgorithm, byte[] secret, int numberOfDigits, int periodInSeconds)
public int GetCode(HashAlgorithm hashAlgorithm, byte[] secret, byte numberOfDigits, byte periodInSeconds)
{
//https://tools.ietf.org/html/rfc4226#section-5.4
//https://tools.ietf.org/html/rfc6238#section-4.2

secret.CheckArgumentNullOrEmpty(nameof(secret));

if (numberOfDigits < 6 || numberOfDigits > 8)
throw new ArgumentException(Resources.Exception_InvalidNumberOfDigits);

if (periodInSeconds < 30)
throw new ArgumentException(Resources.Exception_InvalidPeriodInSeconds);

var deltaTime = _systemTime.GetUtcNow() - UnixEpoch;
var counter = ConvertToBytes((ulong)(deltaTime.TotalSeconds / periodInSeconds));
byte[] hash;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public class AuthenticatorServiceOptions

public HashAlgorithm HashAlgorithm { get; set; } = HashAlgorithm.SHA1;

public int NumberOfDigits { get; set; } = 6;
public byte NumberOfDigits { get; set; } = 6;

public int PeriodInSeconds { get; set; } = 30;
public byte PeriodInSeconds { get; set; } = 30;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Exception_InvalidNumberOfDigits" xml:space="preserve">
<value>The number of digits must be between 6 and 8.</value>
</data>
<data name="Exception_InvalidPeriodInSeconds" xml:space="preserve">
<value>The period must be at least 30 seconds.</value>
</data>
<data name="Exception_OptionMustBeProvided" xml:space="preserve">
<value>The '{0}' option must be provided.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ public void MissingIssuer()
}

[Theory]
[InlineData(HashAlgorithm.SHA1, 10, 5)]
[InlineData(HashAlgorithm.SHA256, 20, 8)]
[InlineData(HashAlgorithm.SHA512, 35, 9)]
public void GetUriSuccess(HashAlgorithm hashAlgorithm, int period, int digits)
[InlineData(HashAlgorithm.SHA1, 30, 6)]
[InlineData(HashAlgorithm.SHA256, 60, 8)]
[InlineData(HashAlgorithm.SHA512, 200, 7)]
public void GetUriSuccess(HashAlgorithm hashAlgorithm, byte period, byte digits)
{
var id = Guid.NewGuid().ToString();
var secret = new byte[32];
Expand Down Expand Up @@ -168,5 +168,59 @@ public void GetCodeBadHashAlgotithm()
var service = new AuthenticatorService(options, new DefaultSystemTime());
Assert.Throws<ArgumentException>(()=> service.GetCode((HashAlgorithm)10000, Encoding.UTF8.GetBytes("test"), 8, 30));
}

[Theory]
[InlineData(1)]
[InlineData(5)]
[InlineData(9)]
[InlineData(10)]
public void InvalidNumberOfDigits(byte numberOfDigit)
{
var options = GetOptions();
options.Value.NumberOfDigits = numberOfDigit;

var ex = Assert.Throws<ArgumentException>(() => new AuthenticatorService(options, new DefaultSystemTime()));
Assert.Equal("The number of digits must be between 6 and 8.", ex.Message);
}

[Theory]
[InlineData(1)]
[InlineData(29)]
public void InvalidPeriodInSeconds(byte periodInSeconds)
{
var options = GetOptions();
options.Value.PeriodInSeconds = periodInSeconds;

var ex = Assert.Throws<ArgumentException>(() => new AuthenticatorService(options, new DefaultSystemTime()));
Assert.Equal("The period must be at least 30 seconds.", ex.Message);
}

[Theory]
[InlineData(1)]
[InlineData(5)]
[InlineData(9)]
[InlineData(10)]
public void GetCodeInvalidNumberOfDigits(byte numberOfDigit)
{
var options = GetOptions();
var service = new AuthenticatorService(options, new DefaultSystemTime());

var ex = Assert.Throws<ArgumentException>(() => service.GetCode(HashAlgorithm.SHA1, Encoding.UTF8.GetBytes("12345678901234567890"), numberOfDigit, 30));
Assert.Equal("The number of digits must be between 6 and 8.", ex.Message);
}

[Theory]
[InlineData(1)]
[InlineData(5)]
[InlineData(9)]
[InlineData(10)]
public void GetCodeInvalidPeriodInSeconds(byte periodInSeconds)
{
var options = GetOptions();
var service = new AuthenticatorService(options, new DefaultSystemTime());

var ex = Assert.Throws<ArgumentException>(() => service.GetCode(HashAlgorithm.SHA1, Encoding.UTF8.GetBytes("12345678901234567890"), 6, periodInSeconds));
Assert.Equal("The period must be at least 30 seconds.", ex.Message);
}
}
}

0 comments on commit e94ab89

Please sign in to comment.