summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Enzmann <christoph.enzmann@confer.ch>2013-12-05 17:47:33 +0100
committerChristoph Enzmann <christoph.enzmann@confer.ch>2013-12-05 17:47:33 +0100
commit3e3f949d007812349c623da09f539ab465d46b50 (patch)
tree99563a436dc76c982acc0cf13fa027a08a5a7f5a
parent9b8c9cc8bafa315516b6ac704859c6d13ce1b768 (diff)
downloadTwoStepsAuthenticator-3e3f949d007812349c623da09f539ab465d46b50.zip
TwoStepsAuthenticator-3e3f949d007812349c623da09f539ab465d46b50.tar.gz
TwoStepsAuthenticator-3e3f949d007812349c623da09f539ab465d46b50.tar.bz2
Methods for synchronization
-rw-r--r--TwoStepsAuthenticator.UnitTests/CounterAuthenticatorTests.cs12
-rw-r--r--TwoStepsAuthenticator.UnitTests/TimeAuthenticatorTests.cs15
-rw-r--r--TwoStepsAuthenticator/CounterAuthenticator.cs18
-rw-r--r--TwoStepsAuthenticator/TimeAuthenticator.cs16
4 files changed, 61 insertions, 0 deletions
diff --git a/TwoStepsAuthenticator.UnitTests/CounterAuthenticatorTests.cs b/TwoStepsAuthenticator.UnitTests/CounterAuthenticatorTests.cs
index 4738ba1..ecb96c0 100644
--- a/TwoStepsAuthenticator.UnitTests/CounterAuthenticatorTests.cs
+++ b/TwoStepsAuthenticator.UnitTests/CounterAuthenticatorTests.cs
@@ -38,5 +38,17 @@ namespace TwoStepsAuthenticator.UnitTests {
}
+ [Test]
+ public void VerifyUsedCounter() {
+ var authenticator = new CounterAuthenticator();
+
+ // Test Values from http://www.ietf.org/rfc/rfc4226.txt - Appendix D
+ var base32Secret = Base32Encoding.ToString(Encoding.ASCII.GetBytes("12345678901234567890"));
+
+ long usedCounter;
+ Assert.True(authenticator.CheckCode(base32Secret, "520489", 0L, out usedCounter));
+
+ Assert.AreEqual(usedCounter, 9L);
+ }
}
}
diff --git a/TwoStepsAuthenticator.UnitTests/TimeAuthenticatorTests.cs b/TwoStepsAuthenticator.UnitTests/TimeAuthenticatorTests.cs
index 3d19ea2..3dc6d86 100644
--- a/TwoStepsAuthenticator.UnitTests/TimeAuthenticatorTests.cs
+++ b/TwoStepsAuthenticator.UnitTests/TimeAuthenticatorTests.cs
@@ -30,5 +30,20 @@ namespace TwoStepsAuthenticator.UnitTests {
Assert.IsTrue(authenticator.CheckCode(secret, code));
}
+
+ [Test]
+ public void VerifyUsedTime() {
+ var date = DateTime.Parse("2013-12-05 17:23:50 +0100");
+ var authenticator = new TimeAuthenticator(() => date);
+
+ DateTime usedTime;
+
+ Assert.True(authenticator.CheckCode("H22Q7WAMQYFZOJ2Q", "696227", out usedTime));
+
+ // 17:23:50 - 30s
+ Assert.AreEqual(usedTime.Hour, 17);
+ Assert.AreEqual(usedTime.Minute, 23);
+ Assert.AreEqual(usedTime.Second, 20);
+ }
}
}
diff --git a/TwoStepsAuthenticator/CounterAuthenticator.cs b/TwoStepsAuthenticator/CounterAuthenticator.cs
index 90b0ee4..b9ed5d2 100644
--- a/TwoStepsAuthenticator/CounterAuthenticator.cs
+++ b/TwoStepsAuthenticator/CounterAuthenticator.cs
@@ -38,13 +38,31 @@ namespace TwoStepsAuthenticator {
/// <param name="counter">Current Counter Position</param>
/// <returns>true if any code from counter to counter + WindowSize matches</returns>
public bool CheckCode(string secret, string code, long counter) {
+ long successfulSequenceNumber = 0L;
+
+ return CheckCode(secret, code, counter, out successfulSequenceNumber);
+ }
+
+ /// <summary>
+ /// Checks if the passed code is valid.
+ /// </summary>
+ /// <param name="secret">Shared Secret</param>
+ /// <param name="code">OTP</param>
+ /// <param name="counter">Current Counter Position</param>
+ /// <param name="usedCounter">Matching counter value if successful</param>
+ /// <returns>true if any code from counter to counter + WindowSize matches</returns>
+ public bool CheckCode(string secret, string code, long counter, out long usedCounter) {
var codeMatch = false;
+ long successfulSequenceNumber = 0L;
+
for (int i = 0; i <= WindowSize; i++) {
if (ConstantTimeEquals(GetCode(secret, counter + i), code)) {
codeMatch = true;
+ successfulSequenceNumber = counter + i;
}
}
+ usedCounter = successfulSequenceNumber;
return codeMatch;
}
}
diff --git a/TwoStepsAuthenticator/TimeAuthenticator.cs b/TwoStepsAuthenticator/TimeAuthenticator.cs
index a461520..8e8e462 100644
--- a/TwoStepsAuthenticator/TimeAuthenticator.cs
+++ b/TwoStepsAuthenticator/TimeAuthenticator.cs
@@ -45,7 +45,21 @@ namespace TwoStepsAuthenticator {
/// <param name="code">OTP</param>
/// <returns>true if code matches</returns>
public bool CheckCode(string secret, string code) {
+ DateTime successfulTime = DateTime.MinValue;
+
+ return CheckCode(secret, code, out successfulTime);
+ }
+
+ /// <summary>
+ /// Checks if the passed code is valid.
+ /// </summary>
+ /// <param name="secret">Shared Secret</param>
+ /// <param name="code">OTP</param>
+ /// <param name="usedDateTime">Matching time if successful</param>
+ /// <returns>true if code matches</returns>
+ public bool CheckCode(string secret, string code, out DateTime usedDateTime) {
var baseTime = NowFunc();
+ DateTime successfulTime = DateTime.MinValue;
// We need to do this in constant time
var codeMatch = false;
@@ -53,9 +67,11 @@ namespace TwoStepsAuthenticator {
var checkTime = baseTime.AddSeconds(30 * i);
if (ConstantTimeEquals(GetCode(secret, checkTime), code)) {
codeMatch = true;
+ successfulTime = checkTime;
}
}
+ usedDateTime = successfulTime;
return codeMatch;
}
}