如何在Python中复制证书认证(Mumble(c/c++))?

1 投票
1 回答
1377 浏览
提问于 2025-04-16 02:37

好的,在我开始这个帖子之前,我得先提醒你,这可能不是一个简单的解决办法。能看到并回复这个帖子的朋友,应该对C/C++有一定了解,至少也要懂一些Python,才能回答我上面提到的问题。

简单来说,我有一个来自Mumble(一个语音聊天客户端)的连接方法,它可以连接到服务器,并发送一个SSL证书用于身份验证。同时,我还有一个Python脚本,它也能连接到同一个Mumble语音服务器,但我并没有发送证书。

我需要修改我现有的代码,让它像当前的Mumble客户端那样发送证书。

--

这是看起来能发送证书的C++代码:

    ServerHandler::ServerHandler() {
         MumbleSSL::addSystemCA();

          {
           QList<QSslCipher> pref;
           foreach(QSslCipher c, QSslSocket::defaultCiphers()) {
           if (c.usedBits() < 128)
             continue;
            pref << c;
           }
           if (pref.isEmpty())
            qFatal("No ciphers of at least 128 bit found");
           QSslSocket::setDefaultCiphers(pref);
          }

    void ServerHandler::run() {
          qbaDigest = QByteArray();
          QSslSocket *qtsSock = new QSslSocket(this);

           qtsSock->setPrivateKey(g.s.kpCertificate.second);
           qtsSock->setLocalCertificate(g.s.kpCertificate.first.at(0));
           QList<QSslCertificate> certs = qtsSock->caCertificates();
           certs << g.s.kpCertificate.first;
           qtsSock->setCaCertificates(certs);

          cConnection = ConnectionPtr(new Connection(this, qtsSock));

          qtsSock->setProtocol(QSsl::TlsV1);
          qtsSock->connectToHostEncrypted(qsHostName, usPort);

     void ServerHandler::serverConnectionConnected() {
          tConnectionTimeoutTimer->stop();

          qscCert = cConnection->peerCertificateChain();
          qscCipher = cConnection->sessionCipher();

          if (! qscCert.isEmpty()) {
           const QSslCertificate &qsc = qscCert.last();
           qbaDigest = sha1(qsc.publicKey().toDer());
           bUdp = Database::getUdp(qbaDigest);
                  } else {
           bUdp = true;
          }

          QStringList tokens = Database::getTokens(qbaDigest);
          foreach(const QString &qs, tokens)
           mpa.add_tokens(u8(qs));

          QMap<int, CELTCodec *>::const_iterator i;
          for (i=g.qmCodecs.constBegin(); i != g.qmCodecs.constEnd(); ++i)
                mpa.add_celt_versions(i.key());

          sendMessage(mpa);

--

而现在,我在Python中连接的方式是这样的:

    try:
        self.socket.connect(self.host)
    except:
        print self.threadName,"Couldn't connect to server"
        return
    self.socket.setblocking(0)
    print self.threadName,"connected to server"

--

所以……我需要在我的Python代码中做些什么,才能连接到需要证书的服务器呢?因为我现在的代码可以顺利连接到任何requirecert设置为false的Mumble服务器。我需要它能在所有服务器上都能工作,因为这将用于我自己的服务器(讽刺的是,我的服务器是需要证书的)。

我可以预先生成证书,格式可以是.p12或其他类型的文件,所以我不需要程序来生成证书。我只需要它按照服务器的要求发送证书(就像我发的C++代码那样)。

请尽快帮我!如果你需要更多信息,可以再给我发消息。我已经去掉了所有不相关的代码,现在只剩下处理SSL的代码。

1 个回答

0

从这段C++代码来看,你只需要有SSL支持,并且使用正确的证书文件进行协商,然后用正确的私钥来加密数据。那些证书和私钥很可能就存放在你原来的程序里。如果C++可能会加载一些非标准的认证机构,你需要找出把这些根认证机构放在哪里,或者确保Python忽略这些问题,但这样做安全性就会降低。

在Python中,你可以像上面那样创建一个套接字,不过可以用urllib这个库。这个库支持HTTPS,并且可以提供证书和私钥。URLOpener

使用示例:

opener = urllib.URLopener(key_file = 'mykey.key', cert_file = 'mycert.cer')
self.socket = opener.open(url)

你可能还需要加一些错误检查之类的,让它更稳健,但希望这些信息能对你有帮助。

撰写回答