PKCS12, PEM hay DER: VPN client thực sự cần gì
Cách đóng gói quyết định việc client có nhập được danh tính hay không, chứ không quyết định nó có được tin cậy hay không. So sánh PKCS12, PEM và DER, rồi kiểm chứng.
Hai khẳng định cứ lưu truyền trong các thảo luận về chứng chỉ. Thứ nhất là .p12 là lựa chọn mạnh còn .pem là lựa chọn lỏng lẻo; thứ hai là một tệp văn bản phải an toàn để gửi đi vì bạn đọc được nó. Không khẳng định nào trụ nổi một phút kiểm tra.
PKCS12, PEM và DER mô tả cách các đối tượng chứng chỉ được đóng gói và mã hóa. Chúng không quyết định ai là bên kia, nhà phát hành có đáng tin hay không, hay tệp có cần mật khẩu hay không.
Điều client chấp nhận là câu hỏi về tương thích. Điều tệp chứa là câu hỏi về danh tính. Tách hai điều đó ra, và phần lớn lỗi nhập sẽ không còn bí ẩn.
Ba vùng chứa, một mô hình đối tượng
Hãy bắt đầu từ thứ bạn thực sự có. Chứng chỉ là một tuyên bố đã ký về một khóa công khai. Khóa riêng là vật liệu riêng biệt chứng minh bạn kiểm soát khóa đó. Chuỗi là tập hợp các nhà phát hành nối chứng chỉ của bạn với một gốc mà client tin cậy. Cả ba đều tồn tại bất kể cách đóng gói.
Tệp PKCS12, thường là .p12 hoặc .pfx, là vùng chứa được định nghĩa trong RFC 7292, có thể mang khóa riêng, một hoặc nhiều chứng chỉ và chuỗi trong một khối duy nhất được bảo vệ bằng mật khẩu, kèm một bí danh đặt tên cho danh tính. Tệp PEM là khung văn bản được định nghĩa trong RFC 7468: phần thân base64 giữa các dòng BEGIN và END, và một tệp có thể chứa nhiều khối nối tiếp. DER là cách mã hóa nhị phân của chính các cấu trúc ASN.1 đó, và phần thân PEM đúng nghĩa là DER được base64 bọc quanh.
Câu cuối cùng đó là câu đáng nhớ. Chuyển PEM sang DER viết lại lớp bọc, không phải nội dung, và chuyển ngược lại sẽ trả về đúng các byte ban đầu.
| Container | Can hold | Does not decide |
|---|---|---|
| PKCS12 (.p12, .pfx) | Key, leaf certificate, chain, alias, password | Which root the client trusts |
| PEM (.pem, .crt, .cer) | Any number of base64 blocks | Whether the private key is present |
| DER (.der, .cer) | One binary structure | The object type, whatever the extension says |
Mã hóa định dạng không phải mã hóa bảo mật
Base64 là một bảng chữ cái vận chuyển. Nó không giấu gì cả, và ai cũng có thể giải mã một khối PEM trong shell. Tệp DER là nhị phân và cũng công khai như vậy. Không thuộc tính nào trong hai thuộc tính đó là bảo vệ, và không thuộc tính nào ngụ ý rằng có mật khẩu.
Bảo vệ thật sự nằm trong vật liệu khóa. Một gói PKCS12 có thể mã hóa nội dung của nó bằng khóa dẫn xuất từ mật khẩu. Khóa riêng PEM có thể được mã hóa bằng khối tiêu đề cũ hoặc giữ trong PKCS#8 EncryptedPrivateKeyInfo. Bản thân chứng chỉ không chứa gì bí mật, đó là lý do một lần xuất chỉ tạo ra chứng chỉ khiến client không thể xác thực dù bạn bọc nó trong định dạng nào.
Phần mở rộng là gợi ý, không phải hợp đồng. Các tệp kết thúc bằng .cer và .crt xuất hiện ở cả hai cách mã hóa, và các thiết bị xuất chứng chỉ DER dưới tên .pem đủ thường xuyên để việc đoán từ hậu tố tốn cả một buổi chiều. Thay vào đó hãy đọc các byte đầu: tệp PEM mở bằng dòng BEGIN, còn DER bắt đầu bằng 0x30 vì cấu trúc ngoài cùng là SEQUENCE.
Vì sao việc nhập thực sự thất bại
Thông báo lỗi của client nén vài vấn đề khác nhau vào một câu về chứng chỉ không hợp lệ, nên hãy tách chúng theo nguyên nhân. Phổ biến nhất là lệch mã hóa: client phân tích PEM trả về lỗi phân tích trên tệp DER, và cách sửa là chuyển đổi chứ không phải chứng chỉ mới. Thứ hai là thiếu khóa, khi chứng chỉ vẫn ổn mà danh tính không chứng minh được. Thứ ba là chuỗi, khi một gói không có chứng chỉ trung gian trông đúng trong hộp thoại nhập nhưng thất bại trong lúc bắt tay.
Tham số mã hóa gây ra trường hợp thứ tư, và nó trông đúng như mật khẩu sai. Các thiết bị cũ xuất tệp PKCS12 với RC2-40 và 3DES, mà OpenSSL 3 từ chối trừ khi nạp trình cung cấp cũ. Xuất lại từ thiết bị với AES-256-CBC và PBKDF2 là cách sửa lâu bền. Để mật mã cũ bật vĩnh viễn trên máy client chỉ để chiều một tệp là một sự đánh đổi tồi.
Thứ năm là sự mơ hồ. Một vùng chứa có hai khóa và hai chứng chỉ, hoặc một tệp PEM có ba khối CERTIFICATE, buộc client phải chọn, và lựa chọn của nó thường chỉ là mục đầu tiên. Khi đường hầm dựng lên với danh tính sai, đó thường là nguyên nhân.
Kiểm tra trước khi chuyển đổi
Đọc cấu trúc mà không in ra bí mật. openssl pkcs12 -in bundle.p12 -info -noout báo cáo thuật toán mã hóa và các bí danh trong khi chặn đầu ra khóa và chứng chỉ, và hướng dẫn openssl-pkcs12 ghi lại các cờ. Bỏ -noout và thêm -nodes là để tạo ra tệp bạn định lưu, không phải để xem nhanh, vì nó ghi khóa riêng ở dạng rõ.
Với chứng chỉ, openssl x509 -in cert.pem -noout -subject -issuer -dates trả lời điều mà hộp thoại nhập không trả lời, và thêm -ext subjectAltName cho thấy những tên mà chứng chỉ thực sự hợp lệ. Nếu tệp là DER, thêm -inform DER; riêng cờ đó giải quyết phần lớn lỗi không tải được.
Ghép một khóa với một chứng chỉ là việc máy móc, và đáng làm trước mọi lần nhập:
openssl x509 -in cert.pem -noout -pubkey | openssl sha256openssl pkey -in key.pem -pubout | openssl sha256
Các digest giống nhau nghĩa là cặp đó thuộc về nhau. Các digest khác nhau nghĩa là bạn có khóa sai, và không lượng chuyển đổi định dạng nào thay đổi được điều đó.
Điều định dạng không bao giờ thay đổi
Các quyết định tin cậy diễn ra phía trên vùng chứa. Client đi dọc chuỗi tới một gốc trong kho của nó, kiểm tra cửa sổ hiệu lực, kiểm tra mục đích khóa mở rộng cho xác thực client, và ở phía máy chủ kiểm tra rằng tên nó đã gọi có xuất hiện trong chứng chỉ. Không bước nào trong số đó đọc phần mở rộng tệp.
Đó là lý do việc đổi tên tệp cho tới khi lỗi biến mất lại là cách mất thời gian đáng tin đến vậy. Việc nhập thành công, danh tính vẫn sai, và thất bại hiện lại trong lúc bắt tay, nơi thông báo ít hữu ích hơn. Đó cũng là lý do một gói xuất cách đây hai năm nhập sạch mà vẫn bị từ chối: ngày hết hạn đi theo bên trong chứng chỉ, chứ không nằm trong tên tệp.
Một thứ tự tránh phải làm lại
Hỏi tài liệu của client xem nó chấp nhận những cách mã hóa nào và mong đợi vùng chứa nào cho danh tính client, rồi xem thứ bạn được giao. Nếu client muốn một danh tính duy nhất có thể nhập và bạn có các tệp PEM rời, hãy dựng gói một lần với mật khẩu bạn kiểm soát và giữ lại các nguồn. Nếu nó muốn PEM, hãy tách khóa và chuỗi ra, rồi xóa các tệp trung gian sau đó qua bất kỳ quy trình xử lý thông tin xác thực nào mà nhóm bạn đã dùng.
Sau khi nhập, hãy kiểm chứng danh tính chứ không phải hộp thoại: chủ thể, nhà phát hành, ngày hết hạn, và tên mà client sẽ trình ra. Một cái tên thân thiện trong danh sách là nhãn, không phải danh tính đã xác minh. Nếu đường hầm sau đó thất bại, bạn đang gỡ lỗi xác thực hoặc định tuyến chứ không phải đóng gói, và đó là cuộc trò chuyện ngắn hơn nhiều.