5

キー配布サーバーを作成する必要があります。これは、独自の API を介して DRM プロバイダーから AES キーを取得し、接続されたクライアントに返す単なるローカル サーバーです。クライアントは、FFmpeg ライブラリに基づく独自のメディア プレーヤーか、ネイティブの Android メディア プレーヤーです。

Boost ASIO ライブラリと OpenSSL を使用して Windows で実験しました。単純な HTTPS サーバーとクライアントを作成する方法の例があります。私の場合、専用のアプリケーション/クライアントのみがサーバーにアクセスできるようにする必要があるため、クライアント認証が必要です。私はこの種の専門家ではなかったので、私には不明な点がいくつかあります。

HTTPSサーバーはクライアントに認証を要求する必要があり、クライアントは証明書を送信する必要があり、サーバーは証明書から一部のデータを読み込んで検証する必要があることを知っています。質問は次のとおりです。

  • クライアントにはどの種類の証明書が必要ですか? どうすれば作成できますか?
  • サーバーにはどの種類の証明書が必要ですか? どうすれば作成できますか?
  • クライアント (FFmpeg、Android MediaPlayer) がアクセスできるように、クライアント証明書をどこに保存できますか? 他のアプリケーションからアクセスできないようにする必要があります。
  • サーバー証明書はどこに保存できますか?

私が書いていることはすべてネイティブ レベルで実行されます。つまり、Linux 共有ライブラリによって実装されます。だからこそ、一般的な Android 開発者よりも、むしろ Linux の達人に問題があると思います。

誰かが私に説明してくれませんか – いくつかの箇条書きで、これがどのように行われるのか – 可能であれば? ヒントも大歓迎です!

どうもありがとう!

4

1 に答える 1

2

So, first off, the server does not ask the client for a certificate. It is the other way around. The client can, but not always, request the certificate from the server. From the wording of your question, it sounds like you might not need to use a certificate. See this link for more info otherwise. The server does typically need to authenticate the client, but this is usually done through a username / password message that is passed back to the server after a secure connection is in place. You are responsible for writing the code to handle that on both the server and client.

Here is some code that I use to connect to a server via an SSL connection:

void SSLSocket::Connect(SSLSocket* psSLS, const string& serverPath, string& port)
{
   // Connects to the server.
   // serverPath - specifies the path to the server.  Can be either an ip address or url.
   // port - port server is listening on.
   //
   try
   {
      boost::shared_ptr<boost::asio::io_service> IOServ(new boost::asio::io_service);
      IOService = IOServ; // Defined the same way in the class
      Locking CodeLock(SocketLock); // Single thread the code.
      // If the user has tried to connect before, then make sure everything is clean before trying to do so again.
      if (pSocket)
      {
         delete pSocket;
         pSocket = 0;
      }                                                                                                  
      // Create the resolver and query objects to resolve the host name in serverPath to an ip address.
      boost::asio::ip::tcp::resolver resolver(*IOService);
      boost::asio::ip::tcp::resolver::query query(serverPath, port);
      boost::asio::ip::tcp::resolver::iterator EndpointIterator = resolver.resolve(query);
      // Set up an SSL context.
      boost::asio::ssl::context ctx(*IOService, boost::asio::ssl::context::tlsv1_client);
      // Specify to not verify the server certificiate right now.
      ctx.set_verify_mode(boost::asio::ssl::context::verify_none);
      // Init the socket object used to initially communicate with the server.
      pSocket = new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(*IOService, ctx);
      //
      // The thread we are on now, is most likely the user interface thread.  Create a thread to handle all incoming and outgoing socket work messages.
      if (!RcvThreadCreated)
      {
         WorkerThreads.create_thread(boost::bind(&SSLSocket::RcvWorkerThread, this));
         RcvThreadCreated = true;
         WorkerThreads.create_thread(boost::bind(&SSLSocket::SendWorkerThread, this));
      }
      // Try to connect to the server.  Note - add timeout logic at some point.
      // This is an async method and will return right away.  When it completes, the
      // SSLSocket::HandleConnect method will be called and will contain error info to
      // identify if a successful connection was made or not.
      boost::asio::async_connect(pSocket->lowest_layer(), EndpointIterator,
         boost::bind(&SSLSocket::HandleConnect, this, boost::asio::placeholders::error));
}

void SSLSocket::HandleConnect(const boost::system::error_code& error)
{
   // This method is called asynchronously when the server has responded to the connect request.
   std::stringstream ss;
   try
   {
      if (!error)
      {
         pSocket->async_handshake(boost::asio::ssl::stream_base::client,
            boost::bind(&SSLSocket::HandleHandshake, this, boost::asio::placeholders::error));
         ss << "SSLSocket::HandleConnect: From worker thread " << Logger::NumberToString(boost::this_thread::get_id()) << ".\n";
         Log.LogString(ss.str(), LogInfo);
      }
      else
      {
         // Log an error.  This worker thread should exit gracefully after this.
         ss << "SSLSocket::HandleConnect: connect failed to " << sClientIp << " : " << uiClientPort << ".  Error: " << error.message() + ".\n";
         Log.LogString(ss.str(), LogError);
         Stop();
      }
   }
   catch (std::exception& e)
   {
      stringstream ss;
      ss << "SSLSocket::InitAsynchIO: threw an error - " << e.what() << ".\n";
      Log.LogString(ss.str(), LogError);
      Stop();
   }
}

void SSLSocket::HandleHandshake(const boost::system::error_code& error)
{
   // This method is called asynchronously when the server has responded to the handshake request.
   std::stringstream ss;
   try
   {
      if (!error)
      {
         // Try to send the first message that the server is expecting.  This msg tells the server we want to connect.
         // The first 4 bytes specifies the msg length after the first 4 bytes.  The next 2 bytes specifies the msg type.
         // The next 4 bytes specifies the source code.  The next 13 bytes specifies the msg "AttackPoker".
         // The next 2 bytes specifies the locale length.  The last 2 bytes specifies the locale - en for English.
         //
         unsigned char Msg[27] = {0x17, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x41,
            0x74, 0x74, 0x61, 0x63, 0x6b, 0x50, 0x6f, 0x6b, 0x65, 0x72, 0x02, 0x00, 0x65, 0x6e};
         boost::system::error_code Err;

         sClientIp = pSocket->lowest_layer().remote_endpoint().address().to_string();
         uiClientPort = pSocket->lowest_layer().remote_endpoint().port();
         ReqAlive = true;
         // boost::asio::async_write(*pSocket, boost::asio::buffer(Msg), boost::bind(&SSLSocket::HandleFirstWrite, this,
         //   boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
         int Count = boost::asio::write(*pSocket, boost::asio::buffer(Msg), boost::asio::transfer_exactly(27), Err);
         if (Err)
         {
            ss << "SSLSocket::HandleHandshake: write failed - " << error.message() << ".\n";
            Log.LogString(ss.str(), LogInfo);
         }
         HandleFirstWrite(Err, Count);
         // boost::asio::async_write(pSocket, boost::asio::buffer(Msg, 27), boost::bind(&SSLSocket::HandleWrite, this,
         // boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
         ss.str("");
         ss << "SSLSocket::HandleHandshake: From worker thread " << boost::this_thread::get_id() << ".\n";
      }
      else
      {
         ss << "SSLSocket::HandleHandshake: failed - " << error.message() << ".\n";
         IOService->stop();
      }
      Log.LogString(ss.str(), LogInfo);
   }
   catch (std::exception& e)
   {
      stringstream ss;
      ss << "SSLSocket::HandleHandshake: threw an error - " << e.what() << ".\n";
      Log.LogString(ss.str(), LogError);
      Stop();
   }
}

void SSLSocket::HandleFirstWrite(const boost::system::error_code& error, size_t bytesTransferred)
{
   // This method is called after a msg has been written out to the socket.
   std::stringstream ss;
   try
   {
      if (!error)
      {
         // boost::asio::async_read(pSocket, boost::asio::buffer(reply_, bytesTransferred), boost::bind(&SSLSocket::handle_read,
         //   this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
         // boost::asio::async_read(pSocket, boost::asio::buffer(reply_, 84), boost::bind(&SSLSocket::handle_read,
         //   this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
         // Locking CodeLock(ReadLock); // Single thread the code.
         // Signal the other threads that msgs are now ready to be sent and received.
         // boost::asio::async_read(pSocket, boost::asio::buffer(pRepBuf), boost::asio::transfer_exactly(4), boost::bind(&SSLSocket::HandleRead,
         //  this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
         //
         // Notify the UI that we are now connected. - TBD
         // Get the 1st 4 bytes of the next msg, which is always the length of the that msg.
         pDataBuf = BufMang.GetPtr(MsgLenBytes);

         // int i1=1,i2=2,i3=3,i4=4,i5=5,i6=6,i7=7,i8=8,i9=9;
         //   (boost::bind(&nine_arguments,_9,_2,_1,_6,_3,_8,_4,_5,_7))
         //     (i1,i2,i3,i4,i5,i6,i7,i8,i9);

         // boost::asio::read(*pSocket, boost::asio::buffer(pReqBuf, MsgLenBytes), boost::asio::transfer_exactly(MsgLenBytes), Err);
         // boost::asio::async_read(pSocket, boost::asio::buffer(pReqBuf, MsgLenBytes), boost::bind(&SSLSocket::HandleRead, _1,_2,_3))
         //   (this, pReqBuf, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred);
         //   boost::asio::async_read(*pSocket, boost::asio::buffer(reply_), boost::asio::transfer_exactly(ByteCount), boost::bind(&Client::handle_read,
         //      this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
         // boost::asio::async_write(*pSocket, boost::asio::buffer(pDataBuf, MsgLenBytes), boost::bind(&SSLSocket::HandleWrite, this,
         //    boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));

         HandShakeReady = true;
         Locking CodeLock(SocketLock); // Single thread the code.
         boost::asio::async_read(*pSocket, boost::asio::buffer(pDataBuf, MsgLenBytes), boost::bind(&SSLSocket::HandleRead, this,
            boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
      }
      else
      {
         ss << "SSLSocket::HandleFirstWrite: failed - " << error.message() << ".\n";
         Log.LogString(ss.str(), LogError);
         Stop();
      }
   }
   catch (std::exception& e)
   {
      stringstream ss;
      ss << "SSLSocket::HandleFirstWrite: threw an error - " << e.what() << ".\n";
      Log.LogString(ss.str(), LogError);
      Stop();
   }
}
于 2013-03-06T22:23:16.180 に答える