Ejemplo n.º 1
0
        private static Uri BuildUri(string label, string passwordType, string algorithmName, int passwordLength, byte[] secret, string additionalQueryArguments)
        {
            string base32Secret = OnetimePasswordSecret.ToBase32(secret);

            var uriString = $"{Globals.OtpScheme}://{passwordType}/{label}?secret={Uri.EscapeDataString(base32Secret)}&algorithm={Uri.EscapeDataString(algorithmName)}&digits={passwordLength}";

            if (!String.IsNullOrEmpty(additionalQueryArguments))
            {
                uriString += "&" + additionalQueryArguments;
            }

            return(new Uri(uriString, UriKind.Absolute));
        }
Ejemplo n.º 2
0
        public static OnetimePasswordAccount FromOtpUrl(Uri url)
        {
            if (url == null)
            {
                throw new ArgumentNullException(nameof(url));
            }

            if (String.Compare(url.Scheme, Globals.OtpScheme, StringComparison.OrdinalIgnoreCase) != 0)
            {
                throw new ArgumentException($"Url authority is not {Globals.OtpScheme}.", nameof(url));
            }

            if (url.Segments.Length < 2)
            {
                throw new ArgumentException("Url does not contain sufficient segments for an otp url.", nameof(url));
            }

            var passwordType = url.Authority;

            if (String.Compare(passwordType, Globals.HotpAuthority, StringComparison.OrdinalIgnoreCase) != 0 && String.Compare(passwordType, Globals.TotpAuthority, StringComparison.OrdinalIgnoreCase) != 0)
            {
                throw new ArgumentException("Url contains an unknown password type.", nameof(url));
            }

            var metadata = new Dictionary <string, string>();

            byte[] secret = null;
            var    label  = Uri.UnescapeDataString(url.Segments[1]);

            if (label.Contains(":"))
            {
                metadata["issuer"] = label.Substring(0, label.IndexOf(":"));
            }
            var queryParts = url.Query.Substring(1).Split('&');

            var passwordGenerator = (String.Compare(passwordType, Globals.HotpAuthority, StringComparison.OrdinalIgnoreCase) == 0 ? (IOnetimePasswordGenerator) new CounterBasedPasswordGenerator() : (IOnetimePasswordGenerator) new TimeBasedPasswordGenerator());

            foreach (var queryPart in queryParts)
            {
                var queryOption = queryPart.Split('=');
                var key         = Uri.UnescapeDataString(queryOption[0]);
                var value       = Uri.UnescapeDataString(queryOption[1]);

                switch (key.ToUpperInvariant())
                {
                case "ALGORITHM":
                    passwordGenerator.HashAlgorithm = HasherFromName(value) ?? passwordGenerator.HashAlgorithm;
                    break;

                case "DIGITS":
                    passwordGenerator.PasswordLength = Convert.ToInt32(value);
                    break;

                case "COUNTER":
                    ((CounterBasedPasswordGenerator)passwordGenerator).Counter = Convert.ToInt64(value);
                    break;

                case "PERIOD":
                case "INTERVAL":
                    ((TimeBasedPasswordGenerator)passwordGenerator).TimeInterval = TimeSpan.FromSeconds(Convert.ToInt64(value));
                    break;

                case "SECRET":
                    secret = OnetimePasswordSecret.FromBase32(value);
                    passwordGenerator.SetSecret(secret);
                    break;

                default:
                    metadata[key] = value;
                    break;
                }
            }

            var retVal = new OnetimePasswordAccount()
            {
                Label             = label,
                Secret            = secret,
                Metadata          = metadata,
                Issuer            = metadata.ContainsKey("Issuer") ? metadata["Issuer"] : null,
                PasswordGenerator = passwordGenerator
            };

            return(retVal);
        }