Vấn đề: Lỗi giải mã khóa riêng (Private Key)
Việc quản lý chứng chỉ SSL/TLS thường yêu cầu chuyển đổi hoặc mở khóa các khóa riêng. Bạn có thể đang gỡ bỏ mật khẩu (passphrase), chuyển đổi PEM sang PKCS#12, hoặc chỉ kiểm tra tính toàn vẹn của khóa. Bạn nhập mật khẩu, tin chắc rằng nó đúng, nhưng rồi OpenSSL từ chối với thông báo sau:
error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
Lỗi này xảy ra trong bước xác thực cuối cùng. OpenSSL đã xử lý dữ liệu thành công, nhưng văn bản giải mã kết quả không vượt qua được bước kiểm tra đệm (padding check). Về cơ bản, phép toán không khớp vì khóa đã được giải mã với các tham số sai.
Phân tích: Tại sao giải mã thất bại
Mặc dù "bad decrypt" thường là dấu hiệu của việc gõ sai, OpenSSL thường thất bại vì những lý do kỹ thuật tinh vi hơn:
- Shell Character Escaping: Nếu mật khẩu của bạn chứa
$,!, hoặc#, terminal của bạn có thể đang loại bỏ hoặc thay đổi các ký tự đó trước khi chúng đến được OpenSSL. - Line Ending Corruption: Việc di chuyển một khóa từ Windows sang Linux thường tạo ra các ký tự xuống dòng
\r\n. Những ký tự ẩn này có thể làm hỏng quá trình phân tích Base64. - OpenSSL 3.0 Legacy Deprecation: Các phiên bản hệ điều hành hiện đại như Ubuntu 22.04 hoặc macOS Sonoma sử dụng OpenSSL 3.x. Phiên bản này mặc định vô hiệu hóa các thuật toán cũ, "không an toàn" như dẫn xuất khóa dựa trên MD5. Nếu khóa của bạn được tạo từ nhiều năm trước, OpenSSL 3.x đơn giản là sẽ không thử giải mã nó nếu không có cờ cụ thể.
- Truncated Files: Thậm chí chỉ cần thiếu một ký tự trong khối Base64—thường do sao chép-dán sai—cũng sẽ gây ra lỗi đệm (padding failure).
Các bước khắc phục
1. Loại bỏ sự can thiệp của Terminal
Hãy ngừng nhập mật khẩu trực tiếp vào lời nhắc để tránh các vấn đề về thoát ký tự shell (shell escaping). Thay vào đó, hãy sử dụng một tệp tạm thời để truyền mật khẩu một cách sạch sẽ.
# Sử dụng printf để tránh thêm dòng mới ở cuối
printf "your_password_here" > pass.txt
# Thử đọc khóa bằng tệp mật khẩu
openssl rsa -in encrypted.key -passin file:pass.txt -text -noout
# Xóa tệp ngay lập tức
rm pass.txt
Sử dụng printf an toàn hơn echo vì nó giúp bạn kiểm soát chính xác các khoảng trắng. Chỉ cần một khoảng trắng dư thừa ở cuối mật khẩu cũng sẽ gây ra lỗi 06065064.
2. Kích hoạt Legacy Provider (OpenSSL 3.x)
Nếu bạn đang sử dụng một bản phân phối Linux gần đây hoặc macOS và bạn chắc chắn mật khẩu là đúng, vấn đề có khả năng là do một cipher cũ (legacy cipher). Các khóa cũ thường sử dụng pbeWithMD5AndDES-CBC, thứ mà OpenSSL 3.x bỏ qua vì lý do bảo mật.
Buộc OpenSSL tải module legacy với các cờ sau:
# Mở khóa một khóa RSA cũ
openssl rsa -in encrypted.key -out decrypted.key -legacy -provider default -provider legacy
Nếu bạn đang làm việc với gói .p12 hoặc .pfx, lệnh sẽ như thế này:
openssl pkcs12 -in bundle.p12 -nodes -out certs.pem -legacy
3. Loại bỏ các ký tự Windows ẩn
Các ký tự xuống dòng ẩn (CRLF) là một nguyên nhân phổ biến. Sử dụng tr để làm sạch tệp trước khi thử giải mã lại:
tr -d '\r' < encrypted.key > clean_encrypted.key
openssl rsa -in clean_encrypted.key -check
Bạn có thể xác minh xem các ký tự này có tồn tại hay không bằng cách chạy cat -A encrypted.key. Nếu bạn thấy ^M ở cuối các dòng, tệp của bạn có kết thúc dòng kiểu Windows.
Giải pháp lâu dài: Hiện đại hóa mã hóa của bạn
Nếu bạn phải sử dụng cờ -legacy, khóa của bạn là một rủi ro bảo mật. Các công cụ hiện đại như Nginx 1.24+ hoặc các môi trường Java mới hơn có thể từ chối nó. Bạn nên nâng cấp mã hóa lên AES-256 ngay lập tức.
Đầu tiên, giải mã khóa cũ:
openssl rsa -in old_key.key -out temp.key -legacy
Sau đó, mã hóa lại nó bằng các tiêu chuẩn hiện đại:
openssl rsa -in temp.key -aes256 -out new_secure.key
Điều này đảm bảo tính tương thích với OpenSSL 3.x mà không cần các ghi đè đặc biệt trong cấu hình production của bạn.
Xác minh: Kiểm tra tính toàn vẹn của khóa
Khi bạn nghĩ rằng mình đã khắc phục xong, hãy chạy một kiểm tra tính nhất quán. Điều này xác minh mối quan hệ toán học giữa các thành phần riêng tư (private) và công khai (public) của khóa.
openssl rsa -in your_key.key -check -noout
Nếu bạn thấy "RSA key ok", bạn đã hoàn tất. Nếu tệp không được mã hóa, phần header sẽ hiển thị -----BEGIN RSA PRIVATE KEY----- mà không có bất kỳ header Proc-Type hoặc DEK-Info phụ nào bên trong văn bản.
Phân tích mã lỗi
Thành phần
Mô tả
`06065064`
Danh tính số cho một lỗi giải mã EVP.
`EVP_DecryptFinal_ex`
Hàm kiểm tra xem dữ liệu có được giải mã sạch sẽ hay không.
`bad decrypt`
Xác nhận rằng mật khẩu hoặc thuật toán không khớp với dữ liệu.

