Có một số mã trong hệ thống của chúng tôi để tự động tạo chứng chỉ tự ký vào kho khóa mà sau đó được Jetty sử dụng. Nếu một khóa cho một máy chủ đã cho đã tồn tại thì không có gì xảy ra nhưng nếu nó không tồn tại, chúng tôi tạo ra một khóa mới, như thế này:Nếu có nhiều hơn một chứng chỉ trong kho khóa của Jetty, nó sẽ chọn như thế nào?
public void generateKey(String commonName) {
X500Name x500Name = new X500Name("CN=" + commonName);
CertAndKeyGen keyPair = new CertAndKeyGen("DSA", "SHA1withDSA");
keyPair.generate(1024);
PrivateKey privateKey = keyPair.getPrivateKey();
X509Certificate certificate = keyPair.getSelfCertificate(x500Name, 20*365*24*60*60);
Certificate[] chain = { certificate };
keyStore.setEntry(commonName, privateKey, "secret".toCharArray(), chain);
}
Điều này tất cả hoạt động tốt miễn là chỉ có một khóa và chứng chỉ trong kho khóa. Khi bạn có nhiều phím, những điều kỳ lạ xảy ra khi bạn cố gắng kết nối:
java.io.IOException: HTTPS hostname wrong: should be <127.0.0.1>
này khá một lỗi bí ẩn nhưng cuối cùng tôi đã được quản lý để theo dõi nó xuống bằng cách viết một bài kiểm tra đơn vị này kết nối với máy chủ và khẳng định rằng CN trên chứng chỉ khớp với tên máy chủ. Những gì tôi thấy khá thú vị - Jetty dường như tự ý chọn chứng chỉ nào để trình bày cho khách hàng, nhưng theo một cách nhất quán.
Ví dụ:
- Nếu "CN = localhost" và "CN = cheese.mydomain" đang ở trong cửa hàng quan trọng, nó luôn luôn chọn "CN = cheese.mydomain".
- Nếu "CN = 127.0.0.1" và "CN = cheese.mydomain" nằm trong kho khóa, nó luôn chọn "CN = cheese.mydomain".
- Nếu "CN = 192.168.222.100" (cheese.mydomain) và "CN = cheese.mydomain" nằm trong kho khóa, nó luôn chọn "CN = 192.168.222.100".
Tôi đã viết một số mã vòng qua chứng chỉ trong cửa hàng để in ra và thấy rằng nó không nhất quán chọn chứng chỉ đầu tiên hoặc bất kỳ điều gì tầm thường như thế.
Vậy chính xác sử dụng tiêu chí nào? Ban đầu tôi nghĩ rằng localhost là đặc biệt nhưng sau đó ví dụ thứ ba đã làm tôi bối rối hoàn toàn.
Tôi lấy nó rằng điều này được quyết định bằng cách nào đó bởi KeyManagerFactory, đó là SunX509 trong trường hợp của tôi.
Vâng, chúng tôi đã phát hiện ra điều có địa chỉ IP, điều này dẫn đến việc viết HostnameVerifier riêng của chúng tôi để kiểm tra xem liệu nó có khớp và trả về true không. Ban đầu chúng tôi đã có một HostnameVerifier mà trả về đúng luôn luôn, mà chỉ đơn giản là đã được ném ra vì lý do rõ ràng. Nhiều người dùng hiện có đã định cấu hình địa chỉ IP là "tên máy chủ" của họ và chúng tôi không muốn tấn công mạnh mẽ vào lúc này. – Trejkaz