RS256 против HS256: в чем разница?

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

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

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

3 ответов


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

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

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

Если вы будете разрабатывать приложение, потребляющее JWTs, вы можете безопасно использовать 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, вы увидите, что вам не нужно настраивать открытый ключ в любом месте: он извлекается автоматически платформой.


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

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

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

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

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

сценарий HS256 и RS256

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

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

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


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

просто поставить 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)

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

[программы.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.
        }
    }
}