Add number of characters and extend time of Rfc6238AuthenticationService

0 投票
最新提问 用户: (320 分)

I am using Rfc6238AuthenticationService at https://github.com/aspnet/Identity/blob/85012bd0ac83548f7eab31f0585dae3836935d9d/src/Microsoft.AspNet.Identity/Rfc6238AuthenticationService.cs

which uses rfc6238 https://tools.ietf.org/html/rfc6238

internal static class Rfc6238AuthenticationService
{
    private static readonly DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    private static readonly TimeSpan _timestep = TimeSpan.FromMinutes(3);
    private static readonly Encoding _encoding = new UTF8Encoding(false, true);

    private static int ComputeTotp(HashAlgorithm hashAlgorithm, ulong timestepNumber, string modifier)
    {
        // # of 0's = length of pin
        const int Mod = 1000000;

        // See https://tools.ietf.org/html/rfc4226
        // We can add an optional modifier
        var timestepAsBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((long)timestepNumber));
        var hash = hashAlgorithm.ComputeHash(ApplyModifier(timestepAsBytes, modifier));

        // Generate DT string
        var offset = hash[hash.Length - 1] & 0xf;
        Debug.Assert(offset + 4 < hash.Length);
        var binaryCode = (hash[offset] & 0x7f) << 24
                         | (hash[offset + 1] & 0xff) << 16
                         | (hash[offset + 2] & 0xff) << 8
                         | (hash[offset + 3] & 0xff);

        return binaryCode % Mod;
    }

    private static byte[] ApplyModifier(byte[] input, string modifier)
    {
        if (String.IsNullOrEmpty(modifier))
        {
            return input;
        }

        var modifierBytes = _encoding.GetBytes(modifier);
        var combined = new byte[checked(input.Length + modifierBytes.Length)];
        Buffer.BlockCopy(input, 0, combined, 0, input.Length);
        Buffer.BlockCopy(modifierBytes, 0, combined, input.Length, modifierBytes.Length);
        return combined;
    }

    // More info: https://tools.ietf.org/html/rfc6238#section-4
    private static ulong GetCurrentTimeStepNumber()
    {
        var delta = DateTime.UtcNow - _unixEpoch;
        return (ulong)(delta.Ticks / _timestep.Ticks);
    }

    public static int GenerateCode(byte[] securityToken, string modifier = null)
    {
        if (securityToken == null)
        {
            throw new ArgumentNullException(nameof(securityToken));
        }

        // Allow a variance of no greater than 90 seconds in either direction
        var currentTimeStep = GetCurrentTimeStepNumber();
        using (var hashAlgorithm = new HMACSHA1(securityToken))
        {
            return ComputeTotp(hashAlgorithm, currentTimeStep, modifier);
        }
    }

    public static bool ValidateCode(byte[] securityToken, int code, string modifier = null)
    {
        if (securityToken == null)
        {
            throw new ArgumentNullException(nameof(securityToken));
        }

        // Allow a variance of no greater than 90 seconds in either direction
        var currentTimeStep = GetCurrentTimeStepNumber();
        using (var hashAlgorithm = new HMACSHA1(securityToken))
        {
            for (var i = -2; i <= 2; i++)
            {
                var computedTotp = ComputeTotp(hashAlgorithm, (ulong)((long)currentTimeStep + i), modifier);
                if (computedTotp == code)
                {
                    return true;
                }
            }
        }

        // No match
        return false;
    }
}

Is it possible to add character limit in this class and make it configurable(like 6 chars)? Also, is it possible to extend the time of token and make it configurable(like 120 seconds)?

登录 或者 注册 后回答这个问题。

欢迎来到 Security Q&A ,有什么不懂的可以尽管在这里提问,你将会收到社区其他成员的回答。
...