diff options
-rw-r--r-- | TwoStepsAuthenticator.TestApp/MainWindow.xaml.cs | 2 | ||||
-rw-r--r-- | TwoStepsAuthenticator/Authenticator.cs | 15 | ||||
-rw-r--r-- | TwoStepsAuthenticator/TwoStepsAuthenticator.csproj | 1 | ||||
-rw-r--r-- | TwoStepsAuthenticator/UsedCodesManager.cs | 79 |
4 files changed, 95 insertions, 2 deletions
diff --git a/TwoStepsAuthenticator.TestApp/MainWindow.xaml.cs b/TwoStepsAuthenticator.TestApp/MainWindow.xaml.cs index 3a1ae68..43469af 100644 --- a/TwoStepsAuthenticator.TestApp/MainWindow.xaml.cs +++ b/TwoStepsAuthenticator.TestApp/MainWindow.xaml.cs @@ -31,7 +31,7 @@ namespace TwoStepsAuthenticatorTestApp private void Button_Click(object sender, RoutedEventArgs e) { - model.GetCode(); + model.GetCode(); } } } diff --git a/TwoStepsAuthenticator/Authenticator.cs b/TwoStepsAuthenticator/Authenticator.cs index de383d9..d196525 100644 --- a/TwoStepsAuthenticator/Authenticator.cs +++ b/TwoStepsAuthenticator/Authenticator.cs @@ -9,6 +9,12 @@ namespace TwoStepsAuthenticator { public class Authenticator { + private static UsedCodesManager usedCodes = new UsedCodesManager(); + + public string GenerateKey() + { + throw new NotImplementedException(); + } public string GetCode(string secret) { @@ -55,17 +61,24 @@ namespace TwoStepsAuthenticator public bool CheckCode(string secret, string code) { + if (usedCodes.IsCodeUsed(secret, code)) + return false; + var baseTime = DateTime.Now; - for (int i = -2; i <= 2; i++) + for (int i = -2; i <= 1; i++) { var checkTime = baseTime.AddSeconds(30 * i); if (GetCode(secret, checkTime) == code) + { + usedCodes.AddCode(secret, code); return true; + } } return false; } + } } diff --git a/TwoStepsAuthenticator/TwoStepsAuthenticator.csproj b/TwoStepsAuthenticator/TwoStepsAuthenticator.csproj index 7e9e1e0..b628bfd 100644 --- a/TwoStepsAuthenticator/TwoStepsAuthenticator.csproj +++ b/TwoStepsAuthenticator/TwoStepsAuthenticator.csproj @@ -42,6 +42,7 @@ <Compile Include="Base32Encoding.cs" /> <Compile Include="Authenticator.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="UsedCodesManager.cs" /> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. diff --git a/TwoStepsAuthenticator/UsedCodesManager.cs b/TwoStepsAuthenticator/UsedCodesManager.cs new file mode 100644 index 0000000..d60e1cb --- /dev/null +++ b/TwoStepsAuthenticator/UsedCodesManager.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +//using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Timers; + +namespace TwoStepsAuthenticator +{ + internal class UsedCodesManager + { + private class UsedCode + { + public UsedCode(String secret, String code) + { + this.UseDate = DateTime.Now; + this.Code = secret + code; + } + + public DateTime UseDate { get; set; } + public String Code { get; set; } + + public override bool Equals(object obj) + { + return obj.ToString().Equals(Code); + } + public override string ToString() + { + return Code; + } + public override int GetHashCode() + { + return Code.GetHashCode(); + } + } + + private Queue<UsedCode> codes; + private object codeLock = new object(); + private Timer cleaner; + + public UsedCodesManager() + { + codes = new Queue<UsedCode>(); + cleaner = new Timer(TimeSpan.FromSeconds(5).TotalMilliseconds); + cleaner.Elapsed += cleaner_Elapsed; + cleaner.Start(); + } + + void cleaner_Elapsed(object sender, ElapsedEventArgs e) + { + var timeToClean = DateTime.Now.AddSeconds(-5); + lock (codeLock) + { + while (codes.Count > 0 && codes.Peek().UseDate < timeToClean) + { + codes.Dequeue(); + } + } + } + + public void AddCode(String secret, String code) + { + lock (codeLock) + { + codes.Enqueue(new UsedCode(secret, code)); + } + } + + public bool IsCodeUsed(String secret, String code) + { + lock (codeLock) + { + return codes.Contains(new UsedCode(secret, code)); + } + } + } + + +} |