2012-06-09 5 views
8

ten sposób wygenerować moje cert SSL, klucz, itp:Certyfikat SSL, nie uwierzytelniania poprzez oszczędności, ale OK za pomocą przeglądarki

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 

To działa, widzę wyjście w Chrome, chociaż dostaję ostrzegając, że najpierw otrzymam wirusy.

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

to fragment kodu z serwera. Będę szczery, nie jestem pewien dokładnie, co robi każda linia, choć mam dobry pomysł:

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

klient:

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

Jeśli komentuję loadTrustedCertificates w kliencie, a następnie otrzymuję wyjątek niezweryfikowanego certyfikatu SSL. Po pozostawieniu tej linii otrzymuję wyjątek wyjątku uwierzytelniania.

Oto 2 znacznie dłuższe fragmenty kodu, które umieszczają powyższe fragmenty w lepszej perspektywie.
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(); 

klient:

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(); 

Dzięki za poświęcenie czasu na przeczytanie tego. Jeśli pojawią się rażące błędy, ucieszę się, słysząc o tym. To była zmora mojej egzystencji zbyt długo. Za długo.

Odpowiedz

10

Wygląda na to, że generujesz samopodpisane certyfikaty (co jest w porządku), ale operacje wykonywane przy użyciu narzędzia openssl są mylące.

Linia 1 jest OK, generuje klucz prywatny.
Linia 2 jest bezużyteczna: klucz wyjściowy jest taki sam, jak klucz wejściowy! (Postaraj się, aby diff dwa klawisze, aby zobaczyć).
Linia 3 generuje raport CSR, a linia 4 w rzeczywistości sama ją podpisuje, dzięki czemu można je połączyć w jedną linię, jak zobaczymy.

Teraz rzućmy krok wstecz i spróbujmy zrozumieć, co robimy :-)

Używasz SSL do uwierzytelniania i szyfrowania komunikacji pomiędzy serwerem a klientem Thrift Thrift. Zakładam, że chcesz zarówno:

  1. Protect klienta z serwera nieautoryzowanego kodu (co stara się zrobić)
  2. chronić serwer z nieuczciwych klienta (co wydaje się jeszcze ważniejsze dla mnie).

Aby zrobić analogię HTTPS, (1) jest klasycznym certyfikatem serwera, (2) jest zwykle nazwą użytkownika/hasłem dla użytkownika. Ale dzięki rozwiązaniu Thrift SSL uzyskamy wzajemne uwierzytelnienie poprzez wystawienie certyfikatu również klientowi.

Podane przeze mnie przykłady będą używać samopodpisanych certyfikatów. Można je łatwo dostosować do mini CA zarządzanego przez openssl i pozostawię to jako ćwiczenie dla czytelnika.

Generowanie serwera klucza prywatnego:
openssl genrsa -out server-key.pem 2048

wygenerowania powiązany klucz publiczny i self-podpisać go:
openssl req -new -x509 -key server-key.pem -out server-cert.pem -days 10000

Generowanie klienta klucza prywatnego:
openssl genrsa -out client-key.pem 2048

wygenerowania powiązany klucz publiczny i samodzielnie go podpisać:
openssl req -new -x509 -key client-key.pem -out client-cert.pem -days 10000

Uwaga: kiedy openssl req prosi o "Common Name (e.g. server FQDN or YOUR name)", wstaw nazwę FQDN hosta, na którym będzie uruchomiony program Thrift. Pozwoli to nie dostosowywać klasy Thrift's AccessManager. Jeśli z drugiej strony nazwa FQDN nie może być znana z wyprzedzeniem, należy odziedziczyć AccessManager i odpowiednio przesłonić metody verify(). Zobacz TSSLSocket.cpp.

Dobrze, teraz do kodu.

Po stronie serwera:

socketFactory->server(true); jest zbędny, należy go usunąć.

socketFactory->authenticate(false) jest nieco myląca. Lepszą nazwą byłoby authenticatePeer. Jeśli powiesz "false", to nie uwierzytelni klienta, ale zdecydowaliśmy, zanim będziemy chcieli wzajemnego uwierzytelnienia.

Tak, preambuła SSL dla serwera jest:

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) { 
     .... 
    } 

Gdzie myKey jest server-key.pem, myCert jest server-cert.pem i trustedCerts jest ... albo cert od zaufanego urzędu certyfikacji, lub w przypadku samodzielnego -signed cert, cert klienta. Możesz cat wiele certyfikatów jeden po drugim w tym samym pliku. W naszym przykładzie wstawimy client-cert.pem, które stworzyliśmy wcześniej.

Preambuła protokołu SSL dla klienta jest dokładnie taka sama, z poprawnym kluczem prywatnym klienta, certyfikatem klienta i, dla trustedCerts, certyfikatem równorzędnego klienta: server-cert.pem, który stworzyliśmy wcześniej.

To wszystko :-) Spróbuj zrozumieć zanim przeskakujesz, aby go zakodować, jeśli nie masz jasnego obrazu jak działa uwierzytelnianie SSL (wzajemne), trudno zrozumieć komunikaty o błędach. Kod, który pokazałem, jest testowany do pracy.

Dokumentacja, niestety Oszczędzanie jest prawie nic. W przypadku protokołu SSL można zobaczyć: lib/cpp/README.SSL, test/cpp/src/TestServer.cpp i test/cpp/src/TestClient.cpp. Ostrzegam, że TestServer.cpp nie wykonuje wzajemnego uwierzytelniania, co jest komunikatem o błędzie IMHO.

Powiązane problemy