-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathOtp.cs
More file actions
75 lines (60 loc) · 1.81 KB
/
Otp.cs
File metadata and controls
75 lines (60 loc) · 1.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
using System;
namespace Fire.Authentication.Private;
public abstract class Otp
{
protected readonly IKeyProvider _secretKey;
protected readonly OtpHashMode _hashMode;
public OtpHashMode HashMode => _hashMode;
public Otp(byte[] secretKey, OtpHashMode mode)
{
_secretKey = secretKey?.Length > 0 ? new InMemoryKey(secretKey) : throw new ArgumentNullException(nameof(secretKey), "Secret key is empty");
_hashMode = mode;
}
public Otp(IKeyProvider key, OtpHashMode mode)
{
_secretKey = key ?? throw new ArgumentNullException(nameof(key));
_hashMode = mode;
}
protected abstract string Compute(long counter, OtpHashMode mode);
protected internal long CalculateOtp(byte[] data, OtpHashMode mode)
{
byte[] hmacComputedHash = _secretKey.ComputeHmac(mode, data);
int offset = hmacComputedHash[^1] & 0x0F;
return ((hmacComputedHash[offset] & 0x7f) << 24)
| ((hmacComputedHash[offset + 1] & 0xff) << 16)
| ((hmacComputedHash[offset + 2] & 0xff) << 8)
| ((hmacComputedHash[offset + 3] & 0xff) % 1000000);
}
protected internal static string Digits(long input, int digitCount)
{
return (input % (long)Math.Pow(10, digitCount)).ToString().PadLeft(digitCount, '0');
}
protected bool Verify(long initialStep, string valueToVerify, out long matchedStep, VerificationWindow window)
{
window ??= new VerificationWindow();
foreach (long frame in window.ValidationCandidates(initialStep))
{
string comparisonValue = Compute(frame, _hashMode);
if (ValuesEqual(comparisonValue, valueToVerify))
{
matchedStep = frame;
return true;
}
}
matchedStep = 0;
return false;
}
private bool ValuesEqual(string a, string b)
{
if (a.Length != b.Length)
{
return false;
}
int result = 0;
for (int i = 0; i < a.Length; i++)
{
result |= a[i] ^ b[i];
}
return result == 0;
}
}