Trong [bài viết trước](https://viblo.asia/vuonghv/posts/OEqGj6rNG9bL), ta thấy rằng các hệ mã hóa công khai có rất nhiều ứng dụng thực tế, giúp ta vượt qua những hạn chế của các hệ mã khóa đối xứng. Gỉa sử Alice muốn truyền tin bí mật cho Bob. Việc đầu tiên mà Alice cần làm là lấy được public key (PK) của Bob, sau đó mã hóa dữ liệu với khóa PK này và gửi cho Bob. Bob sẽ sử dụng khóa secret key (SK) của mình để giải mã. Đối với các hệ mã công khai, có một kiểu tấn công rất phổ biến đó là Man-in-The-Middle (MiTM) attack. Trong đó, Eve sẽ chặn ở giữa phiên truyền tin của Alice và Bob: * B1: Alice request khóa công khai `PK` của Bob * B2: Bob gửi khóa công khai `PK` của mình về cho Alice. * B3: Eve chặn ở giữa và gửi khóa công khai giả mạo `PK'` của mình về cho Alice. * B4: Alice nhận được khóa giả mạo `PK'`, mã hóa tin nhắn cần gửi `M`: `C' = E(PK', M)` và gửi `C'` cho Bob. Eve nhận được bản mã `C'`, sử dụng khóa bí mật `SK'` của mình để giải mã và lấy được `M = D(SK', C')`. Sau đó mã hóa `M` với khóa `PK` của Bob: `C = E(PK, M)`, rồi gửi bản mã `C` cho Bob. ![mitm_diagram.png](/uploads/e2da1eae-c7f2-4224-adeb-49cf19570609.png) Từ trên ta thấy rằng Bob và Alice vẫn nghĩ rằng phiên làm việc của mình an toàn, nhưng thực ra mọi thông điệp đều bị kẻ thứ 3 Eve nghe lén. Vấn đề cốt lõi ở đây là khóa công khai `PK` của Bob đã bị giả mạo bởi `PK'` của Eve, và Alice không có cách nào để xác minh liệu khóa mình nhận được có đúng là của Bob hay không? Vậy làm thế nào để Alice có thể xác thực khóa `PK` mà mình nhận được đích thị là của Bob, chứ không phải kẻ giả mạo Eve? Câu trả lời nằm ở Chứng chỉ số (Digital Certificates). Vậy chứng chỉ số là gì? có ăn được không? Hiểu đơn giản, chứng chỉ số giống như chứng minh nhân dân (CMND) nhưng thay vì chứng minh một người là ai, nó chứng minh khóa công khai `PK` thuộc về ai. Tương tự, CMND được cấp phép bởi một cơ quan có thẩm quyền và tin cậy (để không bị làm giả) là bộ công an, chứng chỉ số được phát hành (được ký) bởi một bên thứ 3 tin cậy và có uy tín mà ta gọi là Certificate Authority (CA). Vậy một chứng chỉ số chứa đựng những thông tin gì? Bên dưới là chứng chỉ số của [Viblo](https://viblo.asia): ![Certificate Authority image](/uploads/813a527d-8adc-49ff-96f4-36e06f187823.png) Với chuẩn X.509 version 3, một chứng chỉ số có những trường sau: * **Version number** Phiên bản của chứng chỉ. ví dụ, với Viblo ta có phiên bản 3. * **Serial number** Đây là số định danh duy nhất của chứng chỉ, được gán bởi CA. Mỗi chứng chỉ sẽ có **Serial number** khác nhau. Với Viblo là `00:F1:85:83:3E:13:BE:CA:7D:79:D6:EF:F2:0E:83:0D:C5` * **Certificate signature algorithm** Thông tin về thuật toán khóa công khai được CA dùng để ký lên chứng chỉ. Trên ví dụ trên là `PKCS #1 SHA-256 With RSA Encryption` * **Issuer name** Tên của cơ quan phát hành chứng chỉ, đây chính là định danh của CA. Theo đó, chứng chỉ của Viblo được phát hành bởi *COMODO RSA Domain Validation Secure Server CA* * **Validity period** Thời hạn hiệu lực của chứng chỉ, bao gồm ngày bắt đầu và ngày hết hạn. Nếu thời gian hiện tại nằm ngoài khoảng này thì chứng chỉ không còn hợp lệ. * **Subject name** Tên của chủ sở hữu chứng chỉ. Trong ví dụ trên, chính là *viblo.asia* * **Subject public key information** Thông tin về khóa công khai `PK` của chủ sở hữu chứng chỉ, cũng như là thuật toán mã hóa liên kết với khóa đấy. * **Issuer unique identifier** Đây là định danh duy nhất của cơ quan phát hành chứng chỉ. * **Subject unique identifier** Tương tự như **Issuer unique identifier**, đây là định danh duy nhất của chủ sở hữu chứng chỉ. * **Extensions** Trường này chứa một số thông tin bổ sung liên quan đến việc sử dụng chứng chỉ. * **Certificate signature value** Đây là chữ ký của CA lên khóa công khai `PK` bằng cách sử dụng khóa bí mật của CA với thuật toán được mô tả trong trường **Certificate algorithm identifier**. Bây giờ, mỗi lần Alice yêu cầu khóa công khai `PK` của Bob, Bob sẽ gửi `PK` cùng với chứng chỉ số của mình về cho Alice. Alice sẽ sử dụng chứng chỉ này để xác minh `PK`. Vậy làm thế nào để Alice xác minh `PK` sau khi đã có chứng chỉ của Bob? Rất đơn giản, Alice sẽ sử dụng khóa công khai của CA để xác minh chữ ký (được lấy từ trường **Certificate signature value**) và khóa `PK` của Bob có khớp nhau hay không. Đến đây bạn sẽ tự hỏi, ta sử dụng khóa công khai của một bên thứ 3 CA để xác minh một khóa công khai `PK` khác, vậy làm thế nào để ta có thể tin chắc rằng khóa công khai của CA không bị giả mạo? Để khóa công khai của CA không bị giả mạo, CA cần phải phải cung cấp cho Alice chứng chỉ của chính mình, được phát hành bởi một bên thứ 3 khác có thẩm quyền cao hơn và tin cậy hơn, cứ tiếp tục như thế, ta có một cây phân cấp chứng chỉ. ![chain-of-trust.gif](/uploads/8e4e6a31-1e90-4305-939c-2f1fbf87646f.gif) Cuối cây phân cấp là chứng chỉ gốc (Root Digital Certificate) mà Alice cần phải mặc định tin là hợp hệ. Hay nói cách khác, Alice mặc định phải tin rằng khóa công khai của CA gốc không thể bị giả mạo. Vì vậy những chứng chỉ gốc sẽ được tích hợp sẵn vào trong phần mềm như Firefox và Chrome. Ví dụ, chứng chỉ của viblo.asia gồm 3 cấp như sau: ![Capture.PNG](/uploads/c87b5f26-b0c4-4c7e-91d7-04c051511a10.png) 1. Chứng chỉ của *`viblo.asia`* được ký bởi *`COMODO RSA Domain Validation Secure Server CA`* 2. Chứng chỉ của *`COMODO RSA Domain Validation Secure Server CA`* được ký bởi *`COMODO RSA Certification Authority`* 3. Chứng chỉ gốc của *`COMODO RSA Certification Authority`* và đây là chứng chỉ do chính *`COMODO RSA Certification Authority`* tự ký. chứng chỉ gốc này được tích hợp sẵn trong Firefox, đo đó Firefox sẽ mặc định tin là khóa công khai của *COMODO RSA Certification Authority* là hợp lệ và không thể bị giả mão. ## Kết luận Hy vọng rằng với bài viết không quá đi sâu vào chi tiết kỹ thuật sẽ cung cung cấp cho mọi người kiến thức tổng quát về chứng chỉ số.