RS256 vs HS256: Sự khác biệt là gì?


254

Tôi đang sử dụng Auth0 để xử lý xác thực trong ứng dụng web của mình. Tôi đang sử dụng ASP.NET Core v1.0.0 và Angular 2 rc5 và tôi không biết nhiều về xác thực / bảo mật nói chung.

Trong các tài liệu Auth0 cho ASP.NET Core Web Api , có hai lựa chọn cho thuật toán JWT là RS256 và HS256. Đây có thể là một câu hỏi ngớ ngẩn nhưng:

Sự khác biệt giữa RS256 và HS256 là gì? Một số trường hợp sử dụng (nếu có) là gì?


Tôi tìm thấy một Angular2-JWT với firbase / php-JWT tại ứng dụng server-side hướng dẫn freakyjolly.com/...
Mã Spy

Câu trả lời:


437

Cả hai lựa chọn đều đề cập đến thuật toán mà nhà cung cấp nhận dạng sử dụng để JWT. Việc ký là một hoạt động mã hóa tạo ra "chữ ký" (một phần của JWT) mà người nhận mã thông báo có thể xác thực để đảm bảo rằng mã thông báo không bị giả mạo.

  • RS256 (Chữ ký RSA với SHA-256 ) là thuật toán bất đối xứng và nó sử dụng cặp khóa công khai / riêng: nhà cung cấp nhận dạng có khóa riêng (bí mật) được sử dụng để tạo chữ ký và người tiêu dùng JWT nhận được khóa chung để xác nhận chữ ký. Vì khóa chung, trái ngược với khóa riêng, không cần phải bảo mật, hầu hết các nhà cung cấp nhận dạng giúp người tiêu dùng dễ dàng lấy và sử dụng (thường thông qua URL siêu dữ liệu).

  • HS256 ( HMAC với SHA-256), mặt khác, liên quan đến sự kết hợp giữa chức năng băm và một khóa (bí mật) được chia sẻ giữa hai bên được sử dụng để tạo ra hàm băm sẽ đóng vai trò là chữ ký. Vì cùng một khóa được sử dụng cả để tạo chữ ký và xác thực nó, nên phải cẩn thận để đảm bảo rằng khóa không bị xâm phạm.

Nếu bạn sẽ phát triển ứng dụng tiêu thụ JWT, bạn có thể sử dụng HS256 một cách an toàn, bởi vì bạn sẽ có quyền kiểm soát ai sử dụng các khóa bí mật. Mặt khác, nếu bạn không có quyền kiểm soát khách hàng hoặc bạn không có cách nào bảo mật khóa bí mật, RS256 sẽ phù hợp hơn, vì người tiêu dùng chỉ cần biết khóa chung (chia sẻ).

Vì khóa chung thường được cung cấp từ các điểm cuối siêu dữ liệu, khách hàng có thể được lập trình để tự động lấy khóa chung. Nếu đây là trường hợp (như với các thư viện .Net Core), bạn sẽ có ít việc phải làm hơn về cấu hình (các thư viện sẽ lấy khóa công khai từ máy chủ). Mặt khác, các khóa đối xứng cần phải được trao đổi ngoài băng tần (đảm bảo kênh liên lạc an toàn) và được cập nhật thủ công nếu có cuộn mã khóa ký.

Auth0 cung cấp các điểm cuối siêu dữ liệu cho các giao thức OIDC, SAML và WS-Fed, nơi các khóa công khai có thể được truy xuất. Bạn có thể thấy các điểm cuối đó trong "Cài đặt nâng cao" của khách hàng.

Ví dụ, điểm cuối siêu dữ liệu OIDC có dạng https://{account domain}/.well-known/openid-configuration. Nếu bạn duyệt đến URL đó, bạn sẽ thấy một đối tượng JSON có tham chiếu đến https://{account domain}/.well-known/jwks.json, chứa khóa công khai (hoặc khóa) của tài khoản.

Nếu bạn nhìn vào các mẫu RS256, bạn sẽ thấy rằng bạn không cần phải định cấu hình khóa chung ở bất cứ đâu: nó được lấy tự động theo khung.


46
NB khi sử dụng rs256 - có (hoặc) rủi ro bảo mật trong nhiều thư viện cho phép mã thông báo xác định thuật toán nào sẽ sử dụng. Về cơ bản kẻ tấn công có thể sử dụng khóa rs256 công khai với mã hóa hs256 để giả vờ đó là khóa bí mật. Vì vậy, hãy chắc chắn rằng thư viện của bạn không có hành vi này!
AlexFoxGill

7
Một điều chỉnh nhỏ, "HS256 (HMAC với SHA-256), mặt khác, là một thuật toán đối xứng" - HMAC không sử dụng thuật toán khóa đối xứng (cho phép bạn mã hóa và giải mã chữ ký theo định nghĩa của nó). Nó sử dụng hàm băm mật mã và khóa mật mã bí mật bên dưới HMAC . Điều này ngụ ý tính toán hàm băm (hàm một chiều) qua tin nhắn có khóa bí mật được nối thêm.
Kikoz

1
Ví dụ với Google: Truy cập vào tài khoản.google.com/.well- Unknown / openid-configuration và xem jwks_uri; nó chuyển tiếp bạn đến googleapis.com/oauth2/v3/certs nơi bạn có thể tìm thấy các khóa. Sau đó, bạn chỉ cần lấy chìa khóa tốt bởi đứa trẻ của nó.
Denis TRUFFAUT

Đáng lưu ý là vì HS256 chia sẻ một khóa giữa hai bên khiến thuật toán này không thể hỗ trợ nhiều đối tượng trong một access_token, trong khi RS256 có thể hỗ trợ nhiều đối tượng. Điều này quan trọng với các máy khách Nhận dạng như Auth0, người chỉ cho phép yêu cầu điểm cuối / userinfo sử dụng access_token nếu cấu hình là RS256, vì họ cần mã thông báo này để hỗ trợ miền api của bạn dưới dạng kiểm toán, cũng như miền auth0 của họ.
jezpez

94

Trong mật mã học có hai loại thuật toán được sử dụng:

Thuật toán đối xứng

Một khóa duy nhất được sử dụng để mã hóa dữ liệu. Khi được mã hóa bằng khóa, dữ liệu có thể được giải mã bằng cùng một khóa. Ví dụ, nếu Mary mã hóa tin nhắn bằng khóa "bí mật của tôi" và gửi nó cho John, anh ta sẽ có thể giải mã tin nhắn một cách chính xác với cùng một khóa "bí mật của tôi".

Các thuật toán bất đối xứng

Hai khóa được sử dụng để mã hóa và giải mã tin nhắn. Mặc dù một khóa (công khai) được sử dụng để mã hóa tin nhắn, nhưng khóa kia (riêng tư) chỉ có thể được sử dụng để giải mã nó. Vì vậy, John có thể tạo cả khóa công khai và khóa riêng, sau đó chỉ gửi khóa chung cho Mary để mã hóa tin nhắn của cô. Tin nhắn chỉ có thể được giải mã bằng khóa riêng.

Kịch bản HS256 và RS256

Các thuật toán này KHÔNG được sử dụng để mã hóa / giải mã dữ liệu. Thay vào đó, chúng được sử dụng để xác minh nguồn gốc hoặc tính xác thực của dữ liệu. Khi Mary cần gửi một tin nhắn mở tới Jhon và anh ta cần xác minh rằng tin nhắn đó chắc chắn là của Mary, HS256 hoặc RS256 có thể được sử dụng.

HS256 có thể tạo chữ ký cho một mẫu dữ liệu nhất định bằng một phím duy nhất. Khi tin nhắn được truyền cùng với chữ ký, bên nhận có thể sử dụng cùng một khóa để xác minh rằng chữ ký khớp với tin nhắn.

RS256 sử dụng cặp chìa khóa để làm tương tự. Một chữ ký chỉ có thể được tạo bằng khóa riêng. Và khóa công khai phải được sử dụng để xác minh chữ ký. Trong kịch bản này, ngay cả khi Jack tìm thấy khóa chung, anh ta không thể tạo một tin nhắn giả mạo có chữ ký để mạo danh Mary.


38

Có một sự khác biệt trong hiệu suất.

Đơn giản chỉ cần đặt HS256nhanh hơn khoảng 1 bậc so RS256với xác minh nhưng nhanh hơn khoảng 2 bậc so RS256với phát hành (ký).

 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)

Đừng gác máy với những con số thực tế, hãy nghĩ về chúng với sự tôn trọng lẫn nhau.

[Chương trình.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.
        }
    }
}

Đây là những con số quan trọng. cảm ơn bạn. Tôi có xu hướng nghĩ về mã hóa là thông lượng wrt trong suốt hoặc ít hơn, nhưng nghiên cứu của bạn ngụ ý rằng sử dụng R256 để ký thông tin liên lạc giữa các liên kết thêm 1 ms mỗi hop.
Matthew Mark Miller

1
@MatthewMarkMiller Hãy ghi nhớ rằng chúng không được sử dụng như nhau. Họ có những đặc điểm khác nhau. RS256 không đối xứng và do đó trong giao tiếp kiểu máy khách / máy chủ nơi bạn chỉ chia sẻ khóa chung, đó là một lựa chọn tốt hơn. HS256 yêu cầu chia sẻ khóa có thể vừa ký VÀ xác minh - chỉ hữu ích nếu bạn tin tưởng hai bên hoặc không cần một trong các bên giải mã bất cứ điều gì.
Rob Evans

7
@RobEvans có, đừng gác máy về số hiệu suất ở đây. Chọn giải pháp đúng cho vấn đề của bạn. Đây chỉ là một quan sát, không phải là một khuyến nghị để ủng hộ HS256 hơn RS256, bạn phải đưa ra quyết định dựa trên bối cảnh của bạn.
John Leidegren

1
Khi lựa chọn giao thức có thể có tác động tương tự đến độ trễ như thêm một km cáp, điều đó đáng để biết, đặc biệt là trong những ngày của chuỗi cuộc gọi dài và các tín hiệu chặt chẽ.
Matthew Mark Miller

0

câu trả lời ngắn, cụ thể cho OAuth2,

  • Bí mật ứng dụng khách người dùng HS256 để tạo chữ ký mã thông báo và cùng một bí mật được yêu cầu để xác thực mã thông báo ở mặt sau. Vì vậy, bạn nên có một bản sao của bí mật đó trong máy chủ phụ trợ của mình để xác minh chữ ký.
  • RS256 sử dụng mã hóa khóa chung để ký mã thông báo. Ký hiệu (hàm băm) sẽ tạo bằng khóa riêng và nó có thể xác minh bằng khóa chung. Vì vậy, không cần khóa riêng hoặc bí mật của máy khách để lưu trữ trong máy chủ back-end, nhưng máy chủ back-end sẽ lấy khóa công khai từ url cấu hình openid trong đối tượng thuê của bạn ( https: // [tenant] /.well- Unknown / openen -configuration ) để xác minh mã thông báo. Tham số KID bên trong access_toekn sẽ sử dụng để phát hiện khóa chính xác (công khai) từ cấu hình openid.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.