Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
HotpValidator.cs
1using System;
2using System.Threading.Tasks;
6
8{
13 public class HotpValidator
14 {
18 public const string ProtocolName = "HOTP";
19
20 private readonly int nrDigits;
21 private readonly byte[] secret;
22 private readonly HashFunction hashFunction;
23 private readonly LoginAuditor auditor;
24 private readonly string endpoint;
25
33 public HotpValidator(byte[] Secret, string OtpEndpoint, LoginAuditor Auditor)
34 : this(HotpCalculator.DefaultNrDigits, Secret,
35 HotpCalculator.DefaultHashFunction, OtpEndpoint, Auditor)
36 {
37 }
38
47 public HotpValidator(int NrDigits, byte[] Secret, string OtpEndpoint,
49 : this(NrDigits, Secret, HotpCalculator.DefaultHashFunction, OtpEndpoint, Auditor)
50 {
51 }
52
62 public HotpValidator(int NrDigits, byte[] Secret, HashFunction HashFunction,
64 {
65 HotpCalculator.CheckNrDigits(NrDigits);
66 HotpCalculator.CheckSecret(Secret);
67
68 this.nrDigits = NrDigits;
69 this.secret = Secret;
70 this.hashFunction = HashFunction;
71 this.endpoint = OtpEndpoint;
72 this.auditor = Auditor;
73 }
74
78 public int NrDigits => this.nrDigits;
79
83 public HashFunction HashFunction => this.hashFunction;
84
88 public string OtpEndpoint => this.endpoint;
89
93 public LoginAuditor Auditor => this.auditor;
94
101 public static async Task<HotpValidator> TryCreate(string OtpEndpoint,
103 {
105 if (Secret is null || !Secret.HashFunction.HasValue)
106 return null;
107
108 return new HotpValidator(Secret.NrDigits, Secret.Secret, Secret.HashFunction.Value,
110 }
111
120 public Task<ValidationResult> Validate(string OtpEndpoint, string RemoteEndPoint,
121 long Counter, int PassCode)
122 {
123 return Validate(this.nrDigits, this.secret, this.hashFunction, OtpEndpoint,
124 RemoteEndPoint, Counter, PassCode, this.auditor);
125 }
126
137 public static Task<ValidationResult> Validate(byte[] Secret, string OtpEndpoint,
138 string RemoteEndPoint, long Counter, int PassCode, LoginAuditor Auditor)
139 {
141 RemoteEndPoint, Counter, PassCode, Auditor);
142 }
143
155 public static Task<ValidationResult> Validate(int NrDigits, byte[] Secret,
156 string OtpEndpoint, string RemoteEndPoint, long Counter, int PassCode,
158 {
160 OtpEndpoint, RemoteEndPoint, Counter, PassCode, Auditor);
161 }
162
175 public static async Task<ValidationResult> Validate(int NrDigits, byte[] Secret,
176 HashFunction HashFunction, string OtpEndpoint, string RemoteEndPoint,
177 long Counter, int PassCode, LoginAuditor Auditor)
178 {
179 using Semaphore Lock = await Semaphores.BeginWrite(ProtocolName + ":" + OtpEndpoint);
180
181 string Key = ProtocolName + "." + OtpEndpoint;
182 long LastCounter = await RuntimeCounters.GetCount(Key);
183 if (Counter <= LastCounter)
184 {
185 LoginAuditor.Fail("Counter value not valid (replay attack?).", OtpEndpoint,
186 RemoteEndPoint, ProtocolName);
187 return new ValidationResult();
188 }
189
190 await RuntimeCounters.IncrementCounter(Key, Counter - LastCounter);
191
192 DateTime? EarliestOpportunity = await Auditor.GetEarliestLoginOpportunity(RemoteEndPoint, ProtocolName);
193 if (EarliestOpportunity.HasValue)
194 return new ValidationResult(EarliestOpportunity.Value);
195
196 int Expected = HotpCalculator.Compute(NrDigits, Secret, HashFunction, Counter);
197 bool Ok = Expected == PassCode;
198
199 if (Ok)
200 {
201 LoginAuditor.Success(ProtocolName + " authentication successful.",
202 OtpEndpoint, RemoteEndPoint, ProtocolName);
203 }
204 else
205 {
206 LoginAuditor.Fail(ProtocolName + " authentication failed.",
207 OtpEndpoint, RemoteEndPoint, ProtocolName);
208 }
209
210 return new ValidationResult(Ok);
211 }
212 }
213}
Static class managing persistent counters.
static Task< long > IncrementCounter(CaseInsensitiveString Key)
Increments a counter.
static async Task< long > GetCount(CaseInsensitiveString Key)
Gets the current count of a counter.
Represents a named semaphore, i.e. an object, identified by a name, that allows single concurrent wri...
Definition: Semaphore.cs:19
Static class of application-wide semaphores that can be used to order access to editable objects.
Definition: Semaphores.cs:17
static async Task< Semaphore > BeginWrite(string Key)
Waits until the semaphore identified by Key is ready for writing. Each call to BeginWrite must be fo...
Definition: Semaphores.cs:91
Class that monitors login events, and help applications determine malicious intent....
Definition: LoginAuditor.cs:26
async Task< DateTime?> GetEarliestLoginOpportunity(string RemoteEndPoint, string Protocol)
Checks when a remote endpoint can login.
static async void Success(string Message, string UserName, string RemoteEndPoint, string Protocol, params KeyValuePair< string, object >[] Tags)
Handles a successful login attempt.
static void Fail(string Message, string UserName, string RemoteEndPoint, string Protocol)
Handles a failed login attempt.
Contains OTP secret information for an OTP endpoint.
HashFunction? HashFunction
Hash function used for the endpoint.
Implements the HOTP calculator algorithm, as defined in RFC 4226: https://datatracker....
int Compute(long Counter)
Calculates the expected one-time-password for the given counter value.
const int DefaultNrDigits
Default number of digits (6).
const HashFunction DefaultHashFunction
Default Hash Function (SHA-1)
Implements the HOTP validator algorithm, as defined in RFC 4226: https://datatracker....
HashFunction HashFunction
Hash function to use in computation.
static Task< ValidationResult > Validate(int NrDigits, byte[] Secret, string OtpEndpoint, string RemoteEndPoint, long Counter, int PassCode, LoginAuditor Auditor)
Calculates the expected one-time-password for the given counter value.
HotpValidator(byte[] Secret, string OtpEndpoint, LoginAuditor Auditor)
Implements the HOTP validator algorithm, as defined in RFC 4226: https://datatracker....
Task< ValidationResult > Validate(string OtpEndpoint, string RemoteEndPoint, long Counter, int PassCode)
Calculates the expected one-time-password for the given counter value.
int NrDigits
Number of digits to present.
static Task< ValidationResult > Validate(byte[] Secret, string OtpEndpoint, string RemoteEndPoint, long Counter, int PassCode, LoginAuditor Auditor)
Calculates the expected one-time-password for the given counter value.
const string ProtocolName
Protocol name (HOTP).
LoginAuditor Auditor
Login auditor.
static async Task< HotpValidator > TryCreate(string OtpEndpoint, LoginAuditor Auditor)
Tries to create an HOTP calculator for the given endpoint.
HotpValidator(int NrDigits, byte[] Secret, string OtpEndpoint, LoginAuditor Auditor)
Implements the HOTP validator algorithm, as defined in RFC 4226: https://datatracker....
HotpValidator(int NrDigits, byte[] Secret, HashFunction HashFunction, string OtpEndpoint, LoginAuditor Auditor)
Implements the HOTP validator algorithm, as defined in RFC 4226: https://datatracker....
static async Task< ValidationResult > Validate(int NrDigits, byte[] Secret, HashFunction HashFunction, string OtpEndpoint, string RemoteEndPoint, long Counter, int PassCode, LoginAuditor Auditor)
Calculates the expected one-time-password for the given counter value.
Contains information of a HOTP or TOTP validation attempt.
CredentialAlgorithm
Specifies the type of external credential algorithm to use.
HashFunction
Hash method enumeration.
Definition: Hashes.cs:26