diff options
author | Guillaume Lacasa <guillaumelacasa@hotmail.com> | 2016-06-29 10:43:45 +0200 |
---|---|---|
committer | Guillaume Lacasa <guillaumelacasa@hotmail.com> | 2016-06-29 12:46:06 +0200 |
commit | 8e80d5923232b6b5852873a8c54fc3d8bbbc9a96 (patch) | |
tree | 05c8206b8e1aa94ec40b0e9cb921b2a3b06b3535 /TwoStepsAuthenticator.DotnetCore/Authenticator.cs | |
parent | 8cfb0a7876aa457254f199ca99210b58284e1151 (diff) | |
download | TwoStepsAuthenticator-8e80d5923232b6b5852873a8c54fc3d8bbbc9a96.zip TwoStepsAuthenticator-8e80d5923232b6b5852873a8c54fc3d8bbbc9a96.tar.gz TwoStepsAuthenticator-8e80d5923232b6b5852873a8c54fc3d8bbbc9a96.tar.bz2 |
Dotnet Core support
Diffstat (limited to 'TwoStepsAuthenticator.DotnetCore/Authenticator.cs')
-rw-r--r-- | TwoStepsAuthenticator.DotnetCore/Authenticator.cs | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/TwoStepsAuthenticator.DotnetCore/Authenticator.cs b/TwoStepsAuthenticator.DotnetCore/Authenticator.cs new file mode 100644 index 0000000..95ce955 --- /dev/null +++ b/TwoStepsAuthenticator.DotnetCore/Authenticator.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace TwoStepsAuthenticator +{ + public abstract class Authenticator + { +#if CORE + private static readonly RandomNumberGenerator Random = RandomNumberGenerator.Create(); +#else + private static readonly RNGCryptoServiceProvider Random = new RNGCryptoServiceProvider(); +#endif + private static readonly int KeyLength = 16; + private static readonly string AvailableKeyChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; + + public static string GenerateKey() { + var keyChars = new char[KeyLength]; + for (int i = 0; i < keyChars.Length; i++) { + keyChars[i] = AvailableKeyChars[RandomInt(AvailableKeyChars.Length)]; + } + return new String(keyChars); + } + + protected string GetCodeInternal(string secret, ulong challengeValue) { + ulong chlg = challengeValue; + byte[] challenge = new byte[8]; + for (int j = 7; j >= 0; j--) { + challenge[j] = (byte)((int)chlg & 0xff); + chlg >>= 8; + } + + var key = Base32Encoding.ToBytes(secret); + for (int i = secret.Length; i < key.Length; i++) { + key[i] = 0; + } + + HMACSHA1 mac = new HMACSHA1(key); + var hash = mac.ComputeHash(challenge); + + int offset = hash[hash.Length - 1] & 0xf; + + int truncatedHash = 0; + for (int j = 0; j < 4; j++) { + truncatedHash <<= 8; + truncatedHash |= hash[offset + j]; + } + + truncatedHash &= 0x7FFFFFFF; + truncatedHash %= 1000000; + + string code = truncatedHash.ToString(); + return code.PadLeft(6, '0'); + } + + protected bool ConstantTimeEquals(string a, string b) { + uint diff = (uint)a.Length ^ (uint)b.Length; + + for (int i = 0; i < a.Length && i < b.Length; i++) { + diff |= (uint)a[i] ^ (uint)b[i]; + } + + return diff == 0; + } + + protected static int RandomInt(int max) { + var randomBytes = new byte[4]; + Random.GetBytes(randomBytes); + + return Math.Abs((int)BitConverter.ToUInt32(randomBytes, 0) % max); + } + + + } +} |