Является ли эта реализация подписанных URL-адресов достаточно безопасной? - PullRequest
2 голосов
/ 14 апреля 2020

Я пытаюсь реализовать подписанные URL для кратковременного доступа к файлам c. Идея такова:

Когда я получаю запрос на сервере, я вынимаю параметр signature и проверяю, что оставшаяся часть URL-адреса, подписанная с помощью HMACSHA256, и тот же общий секретный ключ дают одинаковые результаты. подпись.

Реализация выглядит следующим образом:

    public static class URLSigner
    {
        private static string GetSignatureForUri(string uri, byte[] key)
        {
            var hmac = new HMACSHA256(key);
            var signature = hmac.ComputeHash(Encoding.UTF8.GetBytes(uri));
            var hexSignature = BitConverter.ToString(signature).Replace("-", string.Empty).ToLowerInvariant();
            return hexSignature;
        }

        public static string SignUri(string uri, byte[] key)
        {
            var hexSignature = GetSignatureForUri(uri, key);
            return QueryHelpers.AddQueryString(uri, new Dictionary<string, string> { { "signature", hexSignature }});
        }

        public static bool VerifyUri(string uri, byte[] key)
        {
            var signatureRegex = "[\\?&]signature=([a-z0-9]+)$";
            var signatureMatch = Regex.Match(uri, signatureRegex);
            if (!signatureMatch.Success || signatureMatch.Groups.Count != 2)
                return false;
            var parsedSignature = signatureMatch.Groups[1].Value;

            var originalUri = Regex.Replace(uri, signatureRegex, "");
            var hexSignature = GetSignatureForUri(originalUri, key);
            return hexSignature == parsedSignature;
        }
    }

и используется следующим образом:

var signedUri = URLSigner.SignUri("https://example.com/file.png?download=false", secretKey);
var isVerified = URLSigner.VerifyUri(signedUri, secretKey);

Достаточно ли безопасна эта реализация подписанных URL-адресов?

Ответы [ 3 ]

1 голос
/ 20 апреля 2020

Да, это безопасно, если ключ обрабатывается правильно. Ха sh должен быть в состоянии обеспечить целостность данных (данные в URL не модифицируются другими людьми).

Возможно, одно небольшое улучшение - dispose объект HMACSHA256 (может быть using), но это не может быть связано с безопасностью.

1 голос
/ 16 апреля 2020

В вашей реализации, похоже, отсутствует проверка истечения срока действия, поэтому любой один ключ в настоящее время будет работать бесконечно.

В остальном, я не вижу ничего плохого в этом подходе вообще. Возможно, вы захотите добавить ключ помимо отметки времени для идентификации пользователя или запроса каким-либо образом.

Вот хорошая статья о том, как общий подход используется для одноразовых паролей, что по сути то, что вы делаю.

https://www.freecodecamp.org/news/how-time-based-one-time-passwords-work-and-why-you-should-use-them-in-your-app-fdd2b9ed43c3/

0 голосов
/ 20 апреля 2020

У меня есть одна проблема. Вы говорите, что хотите использовать HMACSHA256 и закрытый ключ , но в терминологии безопасности вы передаете HMA C не закрытый ключ , это общий секрет .

Если у вас должен быть публичный c закрытый ключ для вашей подписи и проверки подлинности, я бы предложил использовать RSACryptoServiceProvider. В RSA у вас есть два ключа: ключ publi c и закрытый ключ.

Ваш клиент создает закрытый ключ, сохраняет его и передает свой ключ publi c серверу. Таким образом, только клиент может подписать и любой пользователь с ключом publi c может проверить это.

С другой стороны, независимо от того, какой алгоритм вы в итоге использовали, я бы предложил добавить подпись в заголовок авторизации вместо запроса строка. Это чаще, и вам не нужно сопоставлять регулярное выражение в каждом запросе.

...