2012-06-09 55 views
8

我這是怎麼產生我的SSL證書,密鑰等:SSL證書,而不是通過節儉驗證,但是OK通過瀏覽器

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 

這工作,我可以在Chrome中看到輸出,雖然我得到一個警告我要先獲取病毒。

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

這是服務器的一個片段。我會說實話,我不知道到底是什麼每一行正在做,但我有一個好主意:

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

客戶端:

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

如果我在客戶端註釋掉loadTrustedCertificates,然後我得到一個SSL未驗證的證書異常。 留下這條線,我得到一個auth失敗異常。

這裏有2個更長的代碼片段,這些代碼片段可以更好地展示上面的代碼片斷。
服務器:

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

客戶端:

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

感謝您抽出寶貴的時間來閱讀。如果有明顯的錯誤,我會很高興聽到它。這一直是我現在已經很久的詛咒。太長。

回答

10

看起來您正在生成自簽名證書(這很好),但您使用openssl實用程序進行的操作令人困惑。

第1行是OK,它會生成一個私鑰。
第2行無用:輸出鍵與輸入鍵相同! (試試看diff這兩個鍵)。
第3行生成CSR,第4行實際上自我簽名,因此可以像我們將看到的那樣將它們合併到一行中。

現在,讓我們退後一步,讓我們試着去了解我們正在:-)

做你正在使用SSL驗證和加密節儉服務器和客戶端節儉之間的通信。我假設你想都:

  1. 從流氓服務器(你的代碼是試圖做)
  2. 防止惡意的客戶端服務器(這似乎更重要的是我)保護客戶端。

要進行HTTPS比喻,(1)是典型的服務器證書,(2)通常是用戶的用戶名/密碼。但是通過Thrift SSL,我們也會通過向客戶頒發證書來獲得相互認證。

我會做的例子將使用自簽名證書。他們可以很容易地適應openssl管理的小型CA,我將這個作爲練習留給讀者。

生成服務器私鑰:
openssl genrsa -out server-key.pem 2048

生成相關的公共密鑰和自簽名:
openssl req -new -x509 -key server-key.pem -out server-cert.pem -days 10000

生成客戶端私鑰:
openssl genrsa -out client-key.pem 2048

生成關聯公鑰並自行簽名:
openssl req -new -x509 -key client-key.pem -out client-cert.pem -days 10000

注意:當openssl req要求"Common Name (e.g. server FQDN or YOUR name)"時,將運行Thrift程序的主機的FQDN。這將允許不定製Thrift的AccessManager類。如果在另一方面,FQDN無法預先知道,一個需要繼承AccessManager並相應地覆蓋verify()方法。見TSSLSocket.cpp

好,現在的代碼。

在服務器端:

socketFactory->server(true);是多餘的,將其刪除。

socketFactory->authenticate(false)是有點誤導。更好的名字應該是authenticatePeer。如果你說false,它不會認證客戶端,但我們決定之前,我們需要相互認證。

因此,對於服務器的SSL序言是:

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

哪裏myKeyserver-key.pemmyCertserver-cert.pemtrustedCerts是...信任的CA的任證書,或者在自我的情況下,簽署的證書,客戶的證書。您可以在同一個文件中依次選擇cat多個證書。在我們的例子中,我們將把我們之前創建的client-cert.pem

客戶端的SSL序言完全一樣,具有正確的客戶端私鑰,客戶端證書和trustedCerts,我們之前創建的對等證書:server-cert.pem

這一切:-)嘗試跳轉到代碼時,如果你沒有怎麼SSL(相互)認證工作,這是很難理解的錯誤信息清晰的畫面之前理解。我所展示的代碼已經過測試。

文檔,明智的,不幸的是節儉是幾乎爲零。對於SSL,可以看到:lib/cpp/README.SSLtest/cpp/src/TestServer.cpptest/cpp/src/TestClient.cpp。被警告TestServer.cpp不會做相互認證,這是一個錯誤恕我直言。