Подтвердить что ты не робот

RS256 против HS256: Какая разница?

Я использую Auth0 для проверки подлинности в своем веб-приложении. Я использую ASP.NET Core v1.0.0 и Angular 2 rc5, и я вообще мало знаю об аутентификации/безопасности.

В Документах Auth0 для ASP.NET Core Web Api существует два варианта для алгоритма JWT: RS256 и HS256. Это может быть глупый вопрос, но:

Какая разница между RS256 и HS256? Каковы некоторые варианты использования (если применимо)?

4b9b3361

Ответ 1

Оба варианта относятся к тому, какой алгоритм провайдер идентификации использует для подписи JWT. Подписание - это криптографическая операция, которая генерирует "подпись" (часть JWT), которую получатель токена может проверить, чтобы убедиться, что токен не был подделан.

  • RS256 (подпись RSA с SHA-256) является асимметричным алгоритмом, и он использует пару открытый/секретный ключ: у провайдера идентификации есть закрытый (секретный) ключ, используемый для генерации подписи, а потребитель JWT получает открытый ключ проверить подпись. Поскольку открытый ключ, в отличие от закрытого ключа, не нуждается в защите, большинство провайдеров идентификации делают его доступным для потребителей для получения и использования (обычно через URL-адрес метаданных).

  • HS256 (HMAC с SHA-256), с другой стороны, включает в себя комбинацию функции хеширования и одного (секретного) ключа, который совместно используется двумя сторонами, используемыми для генерации хэша, который будет служить подписью. Поскольку один и тот же ключ используется как для создания подписи, так и для ее проверки, необходимо позаботиться о том, чтобы ключ не был скомпрометирован.

Если вы будете разрабатывать приложение, использующее JWT, вы можете безопасно использовать HS256, потому что у вас будет контроль над тем, кто использует секретные ключи. Если, с другой стороны, у вас нет контроля над клиентом или у вас нет возможности защитить секретный ключ, RS256 подойдет лучше, поскольку потребителю нужно знать только открытый (общий) ключ.

Поскольку открытый ключ обычно предоставляется из конечных точек метаданных, клиенты могут быть запрограммированы на автоматическое получение открытого ключа. В этом случае (как и в случае библиотек .Net Core) у вас будет меньше работы по настройке (библиотеки будут получать открытый ключ с сервера). Симметричные ключи, с другой стороны, необходимо обменивать вне полосы (обеспечивая безопасный канал связи) и обновлять вручную, если происходит переключение ключа подписи.

Auth0 предоставляет конечные точки метаданных для протоколов OIDC, SAML и WS-Fed, где можно получить открытые ключи. Вы можете увидеть эти конечные точки в разделе "Расширенные настройки" клиента.

Конечная точка метаданных OIDC, например, имеет вид https://{account domain}/.well-known/openid-configuration. Если вы перейдете по этому URL-адресу, вы увидите объект JSON со ссылкой на https://{account domain}/.well-known/jwks.json, который содержит открытый ключ (или ключи) учетной записи.

Если вы посмотрите на образцы RS256, то увидите, что вам не нужно никуда настраивать открытый ключ: он автоматически извлекается платформой.

Ответ 2

В криптографии используются два типа алгоритмов:

Симметричные алгоритмы

Один ключ используется для шифрования данных. При шифровании с помощью ключа данные могут быть расшифрованы с использованием того же ключа. Например, если Мэри зашифрует сообщение с помощью ключа "мой секрет" и отправит его Джону, он сможет правильно расшифровать сообщение с помощью того же ключа "мой секрет".

Асимметричные алгоритмы

Два ключа используются для шифрования и дешифрования сообщений. В то время как один ключ (открытый) используется для шифрования сообщения, другой ключ (частный) может использоваться только для его расшифровки. Таким образом, Джон может генерировать как открытый, так и закрытый ключи, а затем отправлять только открытый ключ Мэри, чтобы зашифровать ее сообщение. Сообщение может быть расшифровано только с помощью закрытого ключа.

Сценарий HS256 и RS256

Эти алгоритмы НЕ используются для шифрования/дешифрования данных. Скорее они используются для проверки происхождения или подлинности данных. Когда Мэри необходимо отправить открытое сообщение Джону, и он должен проверить, что сообщение обязательно от Мэри, можно использовать HS256 или RS256.

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

RS256 использует пару ключей, чтобы сделать то же самое. Подпись может быть сгенерирована только с использованием закрытого ключа. И открытый ключ должен быть использован для проверки подписи. В этом случае, даже если Джек найдет открытый ключ, он не сможет создать поддельное сообщение с подписью, чтобы выдать себя за Мэри.

Ответ 3

Есть разница в производительности.

Проще говоря, HS256 примерно на 1 порядок быстрее, чем RS256 для проверки, но примерно на 2 порядка быстрее, чем RS256 для выдачи (подписи).

 640,251  91,464.3 ops/s
  86,123  12,303.3 ops/s (RS256 verify)
   7,046   1,006.5 ops/s (RS256 sign)

Не зацикливайтесь на реальных цифрах, просто думайте о них с уважением друг к другу.

[Program.cs]

class Program
{
    static void Main(string[] args)
    {
        foreach (var duration in new[] { 1, 3, 5, 7 })
        {
            var t = TimeSpan.FromSeconds(duration);

            byte[] publicKey, privateKey;

            using (var rsa = new RSACryptoServiceProvider())
            {
                publicKey = rsa.ExportCspBlob(false);
                privateKey = rsa.ExportCspBlob(true);
            }

            byte[] key = new byte[64];

            using (var rng = new RNGCryptoServiceProvider())
            {
                rng.GetBytes(key);
            }

            var s1 = new Stopwatch();
            var n1 = 0;

            using (var hs256 = new HMACSHA256(key))
            {
                while (s1.Elapsed < t)
                {
                    s1.Start();
                    var hash = hs256.ComputeHash(privateKey);
                    s1.Stop();
                    n1++;
                }
            }

            byte[] sign;

            using (var rsa = new RSACryptoServiceProvider())
            {
                rsa.ImportCspBlob(privateKey);

                sign = rsa.SignData(privateKey, "SHA256");
            }

            var s2 = new Stopwatch();
            var n2 = 0;

            using (var rsa = new RSACryptoServiceProvider())
            {
                rsa.ImportCspBlob(publicKey);

                while (s2.Elapsed < t)
                {
                    s2.Start();
                    var success = rsa.VerifyData(privateKey, "SHA256", sign);
                    s2.Stop();
                    n2++;
                }
            }

            var s3 = new Stopwatch();
            var n3 = 0;

            using (var rsa = new RSACryptoServiceProvider())
            {
                rsa.ImportCspBlob(privateKey);

                while (s3.Elapsed < t)
                {
                    s3.Start();
                    rsa.SignData(privateKey, "SHA256");
                    s3.Stop();
                    n3++;
                }
            }

            Console.WriteLine($"{s1.Elapsed.TotalSeconds:0} {n1,7:N0} {n1 / s1.Elapsed.TotalSeconds,9:N1} ops/s");
            Console.WriteLine($"{s2.Elapsed.TotalSeconds:0} {n2,7:N0} {n2 / s2.Elapsed.TotalSeconds,9:N1} ops/s");
            Console.WriteLine($"{s3.Elapsed.TotalSeconds:0} {n3,7:N0} {n3 / s3.Elapsed.TotalSeconds,9:N1} ops/s");

            Console.WriteLine($"RS256 is {(n1 / s1.Elapsed.TotalSeconds) / (n2 / s2.Elapsed.TotalSeconds),9:N1}x slower (verify)");
            Console.WriteLine($"RS256 is {(n1 / s1.Elapsed.TotalSeconds) / (n3 / s3.Elapsed.TotalSeconds),9:N1}x slower (issue)");

            // RS256 is about 7.5x slower, but it can still do over 10K ops per sec.
        }
    }
}