public async Task <TotpResult> ValidateAccountTOTPAsync(string globalId, string code, Func <string, string, Task <bool> > dupeChecker = null) { var result = new TotpResult { Code = code, Timestamp = DateTime.UtcNow }; if (!Int32.TryParse(code, out int number)) { return(result); } var account = await _store.LoadByGuid(globalId); if (account != null) { var token = account.Tokens.Where(t => t.Type == AccountTokenType.TOTP).FirstOrDefault(); if (token != null) { var otp = new OtpNet.Totp(Encoding.UTF8.GetBytes(token.Hash)); //, mode: OtpHashMode.Sha256); if (otp.VerifyTotp(code, out long matchedStep, new OtpNet.VerificationWindow(1, 1))) { result.Valid = (dupeChecker != null) ? await dupeChecker.Invoke(globalId, matchedStep.ToString()) : true; } } } return(result); }
/// <summary> /// Pass in a valid Base-32 encoded TOTP-Secret; receive a valid 2FA token.<para> </para> /// If the token would be closer than 2 seconds to expiry, the method waits for a fresh one to avoid authentication failures due to latency. /// </summary> /// <param name="totpSecret">The Base-32 encoded secret to use for TOTP generation. If this is <c>null</c> or empty, <c>null</c> is returned.</param> /// <returns>The 6-cipher string containing the TOTP; <c>null</c> if generation failed for some reason (e.g. invalid <paramref name="totpSecret"/> parameter).</returns> public async Task <string> GetTotp(string totpSecret) { if (totpSecret.NullOrEmpty()) { return(null); } try { var totp = new OtpNet.Totp(Base32Encoding.ToBytes(totpSecret)); if (totp.RemainingSeconds() < 2) { await Task.Delay(1250); } return(totp.ComputeTotp()); } catch (Exception) { return(null); } }
public Totp(string secret, int period, OtpHashMode algorithm, int digits) { var secretBytes = Base32Encoding.ToBytes(secret); _totp = new OtpNet.Totp(secretBytes, period, algorithm, digits); }
public SteamOtp(string secret) { var secretBytes = Base32Encoding.ToBytes(secret); _totp = new SteamTotp(secretBytes); }