public static int CalcOTP(string key, long time) { time /= 30; var keyData = Base32StringToBytes(key); var timeData = BitConverter.GetBytes(time).Reverse().ToArray(); var result = new HMACSHA1(keyData).ComputeHash(timeData); int i = (int)(result.Last() & 15); return(((int)(result[i] & 127) << 24 | (int)(result[i + 1] & 255) << 16 | (int)(result[i + 2] & 255) << 8 | (int)(result[i + 3] & 255)) % 1000000); }
private void CalculateOneTimePassword() { // https://tools.ietf.org/html/rfc4226 Timestamp = Convert.ToInt64(GetUnixTimestamp() / 30); var data = BitConverter.GetBytes(Timestamp).Reverse().ToArray(); Hmac = new HMACSHA1(Secret).ComputeHash(data); Offset = Hmac.Last() & 0x0F; OneTimePassword = ( ((Hmac[Offset + 0] & 0x7f) << 24) | ((Hmac[Offset + 1] & 0xff) << 16) | ((Hmac[Offset + 2] & 0xff) << 8) | (Hmac[Offset + 3] & 0xff) ) % 1000000; }
private static string GenerateOtpCode(string otpSecret) { var timestamp = Convert.ToInt64(Convert.ToInt64(Math.Round((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds)) / 30); var data = BitConverter.GetBytes(timestamp).Reverse().ToArray(); var hmac = new HMACSHA1(ToBytes(otpSecret)).ComputeHash(data); var offset = hmac.Last() & 0x0F; var oneTimePassword = ( ((hmac[offset + 0] & 0x7f) << 24) | ((hmac[offset + 1] & 0xff) << 16) | ((hmac[offset + 2] & 0xff) << 8) | (hmac[offset + 3] & 0xff)) % 1000000; var code = oneTimePassword.ToString().PadLeft(6, '0'); return(code); }
private string ComputeCode(string secret, long counter) { var buffer = Base32.Decode(secret); var hash = new HMACSHA1(buffer).ComputeHash(BitConverter.GetBytes(counter).Reverse().ToArray()); var offset = hash.Last() & 0x0F; var truncatedHash = ((hash[offset] & 0x7f) << 24) | (hash[offset + 1] << 16) | (hash[offset + 2] << 8) | hash[offset + 3]; var code = (truncatedHash % 1000000).ToString().PadLeft(6, '0'); return(code); }
//------------------------------------------------------------------------------------------------- //--- Generate a OneTime Password from a Guid //------------------------------------------------------------------------------------------------- public static async Task <int> OTPFromGuid(Guid TheGuid, bool UseNetworkTime = false) { Int64 myTimeStamp; byte[] mySecret; byte[] myHmac; byte[] myData; int myOffset; int myOneTimePassword; Int64 MyUnixTimestamp; mySecret = StringToBytes(TheGuid.ToString("N")); #if WINDOWS_UWP var myCryptprovider = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha1); #else HMACSHA1 crypt = new HMACSHA1(mySecret); #endif MyUnixTimestamp = await GetUnixTimestamp(UseNetworkTime); myTimeStamp = Convert.ToInt64(MyUnixTimestamp / 30); myData = BitConverter.GetBytes(myTimeStamp).Reverse().ToArray(); #if WINDOWS_UWP var myBuffer = CryptographicBuffer.CreateFromByteArray(myData); var myKeyBuffer = CryptographicBuffer.CreateFromByteArray(mySecret); var myKey = myCryptprovider.CreateKey(myKeyBuffer); var mySignedBuffer = CryptographicEngine.Sign(myKey, myBuffer); CryptographicBuffer.CopyToByteArray(mySignedBuffer, out myHmac); #else myHmac = new HMACSHA1(mySecret).ComputeHash(myData); #endif myOffset = myHmac.Last() & 0x0F; myOneTimePassword = ( ((myHmac[myOffset + 0] & 0x7f) << 24) | ((myHmac[myOffset + 1] & 0xff) << 16) | ((myHmac[myOffset + 2] & 0xff) << 8) | (myHmac[myOffset + 3] & 0xff) ) % 1000000; return(myOneTimePassword); }
public static string CalculateOneTimePassword(byte[] secret, int slotOffset = 0) { // https://tools.ietf.org/html/rfc4226 int steps = 30; // 30 seconds for Google Authentication byte[] secretHash = new MD5CryptoServiceProvider().ComputeHash(secret).Take(10).ToArray(); Int64 UnixTimestamp = GetUnixTimestamp(); Int64 GoodTillTimestamp = Convert.ToInt64(UnixTimestamp / steps) + slotOffset; int SecondsRemain = steps - Convert.ToInt32(UnixTimestamp % steps); var data = BitConverter.GetBytes(GoodTillTimestamp).Reverse().ToArray(); byte[] Hmac = new HMACSHA1(secretHash).ComputeHash(data); int Offset = Hmac.Last() & 0x0F; int OneTimePassword = ( ((Hmac[Offset + 0] & 0x7f) << 24) | ((Hmac[Offset + 1] & 0xff) << 16) | ((Hmac[Offset + 2] & 0xff) << 8) | (Hmac[Offset + 3] & 0xff) ) % 1000000; return(string.Format("{0:000000}", OneTimePassword)); }
public static string CalculateOneTimePassword(byte[] secret, int slotOffset = 0, int digits = 6) { // https://tools.ietf.org/html/rfc4226 int steps = 30; // 30 seconds for Google Authentication byte[] secretHash = HashSecret(secret); Int64 UnixTimestamp = GetUnixTimestamp(); Int64 GoodTillTimestamp = Convert.ToInt64(UnixTimestamp / steps) + slotOffset; int SecondsRemain = steps - Convert.ToInt32(UnixTimestamp % steps); int mod = (int)Math.Pow(10, digits); string formatter = string.Format("{{0:{0}}}", mod.ToString().Substring(1)); var data = BitConverter.GetBytes(GoodTillTimestamp).Reverse().ToArray(); byte[] Hmac = new HMACSHA1(secretHash).ComputeHash(data); int Offset = Hmac.Last() & 0x0F; int OneTimePassword = ( ((Hmac[Offset + 0] & 0x7f) << 24) | ((Hmac[Offset + 1] & 0xff) << 16) | ((Hmac[Offset + 2] & 0xff) << 8) | (Hmac[Offset + 3] & 0xff) ) % mod; return(string.Format(formatter, OneTimePassword)); }
//------------------------------------------------------------------------------------------------- //--- Check if a provided OTP is valid for the provided GUID (allow 3 past + 3 future ones) //------------------------------------------------------------------------------------------------- public static async Task <bool> IsValidOTPFromGuid(Guid TheGuid, int TheOTPToCheck, bool UseNetworkTime = false) { bool success = false; int myNumberOfOTPs = 7; Int64 myTimeStamp; byte[] mySecret; byte[] myHmac; byte[] myData; int myOffset; int myOneTimePassword; Int64 MyUnixTimestamp; int[] myAllowedOTPArray = new int[myNumberOfOTPs]; mySecret = StringToBytes(TheGuid.ToString("N")); #if WINDOWS_UWP var myCryptprovider = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha1); #else HMACSHA1 myCryptprovider = new HMACSHA1(mySecret); #endif MyUnixTimestamp = await GetUnixTimestamp(UseNetworkTime); myTimeStamp = Convert.ToInt64(MyUnixTimestamp / 30); for (int i = 0; i < myNumberOfOTPs; i++) { //current timestamp = myTimeStamp(-0) //So we allow the previous 3 values and future 3 values as well myData = BitConverter.GetBytes(myTimeStamp + i - 3).Reverse().ToArray(); #if WINDOWS_UWP var myBuffer = CryptographicBuffer.CreateFromByteArray(myData); var myKeyBuffer = CryptographicBuffer.CreateFromByteArray(mySecret); var myKey = myCryptprovider.CreateKey(myKeyBuffer); var mySignedBuffer = CryptographicEngine.Sign(myKey, myBuffer); CryptographicBuffer.CopyToByteArray(mySignedBuffer, out myHmac); #else myHmac = new HMACSHA1(mySecret).ComputeHash(myData); #endif myOffset = myHmac.Last() & 0x0F; myOneTimePassword = ( ((myHmac[myOffset + 0] & 0x7f) << 24) | ((myHmac[myOffset + 1] & 0xff) << 16) | ((myHmac[myOffset + 2] & 0xff) << 8) | (myHmac[myOffset + 3] & 0xff) ) % 1000000; myAllowedOTPArray[i] = myOneTimePassword; } //do the check int index = 0; while ((index < myNumberOfOTPs) & (!success)) { success = myAllowedOTPArray[index] == TheOTPToCheck; index++; } return(success); }