/// <summary>
        /// Generates a new HOTP code using the supplied HMAC generater, key, counter and 
        /// HOTP length.
        /// </summary>
        /// <param name="hmac">The HMAC algorithm to use</param>
        /// <param name="secretKey">The secret key used in HMAC-ing the counter</param>
        /// <param name="counter">The counter to use to generate a HOTP code for</param>
        /// <param name="hotpLength">The required length of the generated HOTP code</param>
        /// <returns>The generated HOTP code</returns>
        /// <exception cref="System.ArgumentNullException">Thrown if hmac or secretKey is null</exception>
        /// <exception cref="System.ArgumentException">Thrown if secretKey is empty or hotpLength is not a valid value</exception>
        public static string Generate(byte[] secretKey, ulong counter, HMAC hmac, OneTimePasswordLength hotpLength)
        {
            #region Input validation

            Insist.IsNotNull(hmac, "hmac");
            Insist.IsNotNull(secretKey, "secretKey");
            Insist.IsNotEmpty(secretKey, "secretKey");
            Insist.IsDefined<OneTimePasswordLength>(hotpLength, "hotpLength");

            #endregion

            byte[] hashedCounter = HashCounter(hmac, secretKey, counter);

            uint truncatedHash = DynamicTruncate(hashedCounter);

            //Convert to string and preserve leading 0s
            return GenerateHotpValue(truncatedHash, hotpLength).ToString("D" + (int)hotpLength);
        }
 /// <summary>
 /// Generates a new one time password using the current datetime and default timestep
 /// </summary>
 /// <param name="secretKey">The secret key to use in the HMAC</param>
 /// <param name="hmac">The hmac algorithm to use</param>
 /// <param name="otpLength">The required legnth of the returned passcode</param>
 /// <returns>A one time password code of the required size</returns>
 /// <exception cref="System.ArgumentNullException">Thrown if hmac or secret key is null</exception>
 /// <exception cref="System.ArgumentException">Thrown if secret key is empty, optLength is
 /// not defined value.</exception>
 public static string Generate(byte[] secretKey, HMAC hmac, OneTimePasswordLength otpLength)
 {
     return Generate(secretKey, hmac, DateTime.Now, TimeSpan.Zero, DEFAULT_TIME_STEP, otpLength);
 }
        /// <summary>
        /// Generates a new one time password from the supplied data.
        /// </summary>
        /// <param name="secretKey">The secret key to use in the HMAC</param>
        /// <param name="hmac">The hmac algorithm to use</param>
        /// <param name="dt">The date and time to generate a code for</param>
        /// <param name="offset">Any offsets that should be applied to the supplie date time</param>
        /// <param name="timeStep">The timestep value to use to calculate the current step</param>
        /// <param name="otpLength">The required legnth of the returned passcode</param>
        /// <returns>A one time password code</returns>
        /// <exception cref="System.ArgumentNullException">Thrown if hmac or secret key is null</exception>
        /// <exception cref="System.ArgumentException">Thrown if secret key is empty, optLength is
        /// not defined value or timeStep is less than 1 second.</exception>
        public static string Generate(byte[] secretKey, HMAC hmac, DateTime dt, TimeSpan offset, TimeSpan timeStep, OneTimePasswordLength otpLength)
        {
            #region Input validation

            Insist.IsNotNull(hmac, "hmac");
            Insist.IsNotNull(secretKey, "secretKey");
            Insist.IsNotEmpty(secretKey, "secretKey");
            Insist.IsDefined<OneTimePasswordLength>(otpLength, "optLength");
            Insist.IsAtLeast(timeStep.TotalSeconds, 1, "timeStep");

            #endregion

            dt = dt + offset;

            ulong stepNumber = (ulong)Math.Floor((double)dt.ToUnixTime() / (double)timeStep.TotalSeconds);

            return HmacOneTimePassword.Generate(secretKey, stepNumber, hmac, otpLength);
        }
 /// <summary>
 /// Generates a new one time password from the current datetime
 /// </summary>
 /// <param name="secretKey">The secret key to use in the HMAC</param>
 /// <param name="hmac">The hmac algorithm to use</param>
 /// <param name="timeStep">The timestep value to use to calculate the current step</param>
 /// <param name="otpLength">The required legnth of the returned passcode</param>
 /// <returns>A one time password code of the required length</returns>
 /// <exception cref="System.ArgumentNullException">Thrown if hmac or secret key is null</exception>
 /// <exception cref="System.ArgumentException">Thrown if secret key is empty, optLength is
 /// not defined value or timeStep is less than 1 second.</exception>
 public static string Generate(byte[] secretKey, HMAC hmac, TimeSpan timeStep, OneTimePasswordLength otpLength)
 {
     return Generate(secretKey, hmac, DateTime.Now, TimeSpan.Zero, timeStep, otpLength);
 }
        /// <summary>
        /// Generates the final HOTP value from the truncated value
        /// </summary>
        private static uint GenerateHotpValue(UInt32 truncatedHash, OneTimePasswordLength htopLength)
        {
            //calculate 10^(htopLength-1)
            int calculatedModulo = 10;

            htopLength = htopLength - 1;
            for (int i = 0; i < (int)htopLength; i++)
            {
                calculatedModulo *= 10;
            }

            return (uint)(truncatedHash % calculatedModulo);
        }
 /// <summary>
 /// Generates a new one time password using the current datetime and default timestep
 /// </summary>
 /// <param name="secretKey">The secret key to use in the HMAC</param>
 /// <param name="hmac">The hmac algorithm to use</param>
 /// <param name="otpLength">The required legnth of the returned passcode</param>
 /// <returns>A one time password code of the required size</returns>
 /// <exception cref="System.ArgumentNullException">Thrown if hmac or secret key is null</exception>
 /// <exception cref="System.ArgumentException">Thrown if secret key is empty, optLength is
 /// not defined value.</exception>
 public static string Generate(byte[] secretKey, HMAC hmac, OneTimePasswordLength otpLength)
 {
     return(Generate(secretKey, hmac, DateTime.Now, TimeSpan.Zero, DEFAULT_TIME_STEP, otpLength));
 }
        /// <summary>
        /// Generates a new one time password from the supplied data.
        /// </summary>
        /// <param name="secretKey">The secret key to use in the HMAC</param>
        /// <param name="hmac">The hmac algorithm to use</param>
        /// <param name="dt">The date and time to generate a code for</param>
        /// <param name="offset">Any offsets that should be applied to the supplie date time</param>
        /// <param name="timeStep">The timestep value to use to calculate the current step</param>
        /// <param name="otpLength">The required legnth of the returned passcode</param>
        /// <returns>A one time password code</returns>
        /// <exception cref="System.ArgumentNullException">Thrown if hmac or secret key is null</exception>
        /// <exception cref="System.ArgumentException">Thrown if secret key is empty, optLength is
        /// not defined value or timeStep is less than 1 second.</exception>
        public static string Generate(byte[] secretKey, HMAC hmac, DateTime dt, TimeSpan offset, TimeSpan timeStep, OneTimePasswordLength otpLength)
        {
            #region Input validation

            Insist.IsNotNull(hmac, "hmac");
            Insist.IsNotNull(secretKey, "secretKey");
            Insist.IsNotEmpty(secretKey, "secretKey");
            Insist.IsDefined <OneTimePasswordLength>(otpLength, "optLength");
            Insist.IsAtLeast(timeStep.TotalSeconds, 1, "timeStep");

            #endregion

            dt = dt + offset;

            ulong stepNumber = (ulong)Math.Floor((double)dt.ToUnixTime() / (double)timeStep.TotalSeconds);

            return(HmacOneTimePassword.Generate(secretKey, stepNumber, hmac, otpLength));
        }
 /// <summary>
 /// Generates a new one time password from the current datetime
 /// </summary>
 /// <param name="secretKey">The secret key to use in the HMAC</param>
 /// <param name="hmac">The hmac algorithm to use</param>
 /// <param name="timeStep">The timestep value to use to calculate the current step</param>
 /// <param name="otpLength">The required legnth of the returned passcode</param>
 /// <returns>A one time password code of the required length</returns>
 /// <exception cref="System.ArgumentNullException">Thrown if hmac or secret key is null</exception>
 /// <exception cref="System.ArgumentException">Thrown if secret key is empty, optLength is
 /// not defined value or timeStep is less than 1 second.</exception>
 public static string Generate(byte[] secretKey, HMAC hmac, TimeSpan timeStep, OneTimePasswordLength otpLength)
 {
     return(Generate(secretKey, hmac, DateTime.Now, TimeSpan.Zero, timeStep, otpLength));
 }