2012-06-09 53 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不会做相互认证,这是一个错误恕我直言。