2012-06-09 27 views
8

Đây là cách tôi tạo SSL cert của tôi, chìa khóa, vv:SSL Certificate, không chứng thực qua hành tiết kiệm, nhưng OK qua trình duyệt

openssl genrsa -out server.key 1024 
openssl rsa -in server.key -out new_key.pem 
openssl req -new -key server.key -out server.csr 
openssl x509 -req -days 10000 -in server.csr -signkey new_key.pem -out server.crt 

này làm việc, tôi có thể nhìn thấy đầu ra trong chrome, mặc dù tôi nhận được một cảnh báo rằng tôi sắp nhiễm virus trước.

openssl s_server -cert server.crt -www -key new_key.pem 

đây là đoạn trích từ máy chủ. Sẽ thật mà nói, tôi không chắc chắn chính xác những gì mỗi dòng đang làm, dù tôi có một ý tưởng tốt:

socketFactory->server(true); // this is the server 
socketFactory->authenticate(false); // no auth? 
socketFactory->loadCertificate("server.crt"); 
socketFactory->loadPrivateKey("new_key.pem"); 

khách hàng:

socketFactory->loadTrustedCertificates("server.crt"); 
socketFactory->authenticate(true); //auth? wierd, right? This guy does this:[1] 

[1] http://permalink.gmane.org/gmane.comp.lib.thrift.user/1651

Nếu tôi nhận xét ra loadTrustedCertificates trong ứng dụng khách, sau đó tôi nhận được một ngoại lệ chứng chỉ SSL chưa được xác minh. Với dòng đó còn lại, tôi nhận được một ngoại lệ thất bại auth.

Dưới đây là 2 đoạn mã dài hơn, đặt các đoạn mã trên ở góc độ tốt hơn.
server:

shared_ptr<SkullduggeryHandler> handler(new SkullduggeryHandler()); 
shared_ptr<TBufferedTransportFactory> transportFactory = 
     shared_ptr<TBufferedTransportFactory>(new TBufferedTransportFactory()); 
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); 
shared_ptr<TProcessor> processor(new SkullduggeryProcessor(handler)); 
shared_ptr<TSSLSocketFactory> socketFactory = 
     shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory()); 
socketFactory->server(true); 
socketFactory->authenticate(false); 
socketFactory->loadCertificate("server.crt"); 
socketFactory->loadPrivateKey("new_key.pem"); 
shared_ptr<TSSLServerSocket> socket(new TSSLServerSocket(port, socketFactory)); 
TThreadedServer server(processor, 
           socket, 
           transportFactory, 
           protocolFactory); 
server.serve(); 

khách hàng:

shared_ptr <TSSLSocketFactory> socketFactory = shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory()); 
socketFactory->loadTrustedCertificates("server.crt"); 
socketFactory->authenticate(false); 
shared_ptr <TSSLSocket>socket = socketFactory->createSocket(configuration.ip, configuration.port); 
shared_ptr<TBufferedTransport> transport(new TBufferedTransport(socket)); 
shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport)); 
SkullduggeryClient client(protocol); 
transport->open(); 

Cảm ơn đã dành thời gian để đọc. Nếu có lỗi rõ ràng, tôi sẽ rất vui khi nghe về nó. Đây đã là lệnh cấm tồn tại của tôi quá lâu rồi. Quá lâu.

Trả lời

10

Dường như bạn đang tạo chứng chỉ tự ký (điều này là tốt), nhưng các thao tác bạn đang thực hiện với tiện ích openssl rất khó hiểu.

Dòng 1 là OK, nó tạo khóa riêng.
Dòng 2 là vô dụng: khóa đầu ra giống với khóa đầu vào! (Hãy thử diff hai phím để xem).
Dòng 3 tạo CSR và dòng 4 thực sự tự ký nó, để chúng có thể được hợp nhất với nhau thành một dòng như chúng ta sẽ thấy.

Bây giờ, chúng ta hãy lùi lại một bước và chúng ta hãy cố gắng hiểu những gì chúng tôi đang làm :-)

Bạn đang sử dụng SSL để xác thực và mã hóa các thông tin liên lạc giữa máy chủ tiết kiệm và một khách hàng tiết kiệm. Tôi giả sử bạn muốn cả hai:

  1. Bảo vệ khách hàng từ một máy chủ giả mạo (những gì mã của bạn đang cố gắng để làm)
  2. Bảo vệ máy chủ từ một khách hàng giả mạo (mà có vẻ quan trọng hơn đối với tôi).

Để tương tự HTTPS, (1) là chứng chỉ máy chủ cổ điển, (2) thường là tên người dùng/mật khẩu cho người dùng. Nhưng với SSL tiết kiệm, chúng tôi sẽ có được xác thực lẫn nhau bằng cách phát hành một chứng chỉ cũng cho khách hàng.

Ví dụ tôi sẽ thực hiện sẽ sử dụng chứng chỉ tự ký. Chúng có thể dễ dàng thích ứng với một CA nhỏ được quản lý bởi openssl, và tôi để nó như một bài tập cho người đọc.

Tạo server private key:
openssl genrsa -out server-key.pem 2048

Tạo khóa công khai liên quan và tự ký tên:
openssl req -new -x509 -key server-key.pem -out server-cert.pem -days 10000

Tạo client private key:
openssl genrsa -out client-key.pem 2048

Tạo khóa công khai được liên kết và tự ký tên:
openssl req -new -x509 -key client-key.pem -out client-cert.pem -days 10000

Lưu ý: khi openssl req yêu cầu "Common Name (e.g. server FQDN or YOUR name)", đặt FQDN của máy chủ lưu trữ mà chương trình Tiết kiệm sẽ chạy. Điều này sẽ cho phép không tùy chỉnh lớp AccessManager của Thrift. Nếu mặt khác FQDN không thể được biết trước, một trong những nhu cầu kế thừa AccessManager và ghi đè lên các phương pháp verify() cho phù hợp. Xem TSSLSocket.cpp.

Tốt, bây giờ đến mã.

Ở phía máy chủ:

socketFactory->server(true); là dự phòng, hãy xóa nó.

socketFactory->authenticate(false) hơi gây hiểu lầm. Một tên tốt hơn sẽ là authenticatePeer. Nếu bạn nói false, nó sẽ không xác thực khách hàng, nhưng chúng tôi đã quyết định trước khi chúng tôi muốn xác thực lẫn nhau.

Vì vậy, một lời mở đầu SSL cho máy chủ là:

try { 
    signal(SIGPIPE, SIG_IGN); // See README.SSL 
    shared_ptr<TSSLSocketFactory> sslSocketFactory(new TSSLSocketFactory()); 
    sslSocketFactory->loadPrivateKey(myKey); 
    sslSocketFactory->loadCertificate(myCert); 
    sslSocketFactory->authenticate(true); 
    sslSocketFactory->loadTrustedCertificates(trustedCerts); 
    sslSocketFactory->ciphers("HIGH:!DSS:[email protected]"); 
    ... 
    } catch (TException& tx) { 
     .... 
    } 

đâu myKeyserver-key.pem, myCertserver-cert.pemtrustedCerts được ... hoặc là các CERT của một CA đáng tin cậy, hoặc, trong trường hợp của một tự cert-cert, cert của khách hàng. Bạn có thể cat nhiều thẻ khác nhau trong cùng một tệp. Trong ví dụ của chúng tôi, chúng tôi sẽ đặt client-cert.pem mà chúng tôi đã tạo trước đây.

Lời mở đầu SSL cho khách hàng giống hệt nhau, với khóa riêng của khách hàng chính xác, chứng chỉ ứng dụng khách và, cho trustedCerts, chứng chỉ của số ngang hàng: server-cert.pem mà chúng tôi đã tạo trước đó.

Đó là tất cả :-) Cố gắng hiểu trước khi nhảy để mã hóa nó, nếu bạn không có hình ảnh rõ ràng về cách xác thực SSL (lẫn nhau) hoạt động, rất khó để hiểu được thông báo lỗi. Mã tôi cho thấy được thử nghiệm để hoạt động.

Tài liệu khôn ngoan, tiếc là Tiết kiệm gần như không có gì. Đối với SSL, bạn có thể thấy: lib/cpp/README.SSL, test/cpp/src/TestServer.cpptest/cpp/src/TestClient.cpp. Được cảnh báo rằng TestServer.cpp không thực hiện xác thực lẫn nhau, đây là lỗi IMHO.

Các vấn đề liên quan