2013-03-06 13 views
5

鍵配布サーバを作成する必要があります。これは、ローカルサーバだけで、DRMプロバイダから独自のAPIを使用してAES鍵を取得し、接続されたクライアントに返します。クライアントは、FFmpegライブラリに基づく私自身のメディアプレーヤーか、ネイティブのAndroidメディアプレーヤーです。クライアント認証付きAndroid上のローカルHTTPSサーバ

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

私は、HTTPSサーバーがクライアントに認証を要求しなければならないことを知っています。クライアントは証明書を送信し、サーバーは次にリードを受け取り、証明書からデータの一部を検証します。 質問は次のとおりです。

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

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

誰かが私に説明することができます - いくつかの箇条書きで、これをどうやって行うことができますか?どんなヒントも大歓迎です!

多くの感謝!

+0

あなたがこの中にどのような言葉を書いているの? –

+0

私はC/C++を使って書いています。 – vitakot

答えて

2

まず、サーバーはクライアントに証明書を要求しません。それは別の方法です。クライアントは、常にそうとは限らないが、サーバーに証明書を要求することはできない。あなたの質問の文言から、それはあなたが証明書を使用する必要はないかもしれないように聞こえる。特にそうでない場合は、linkを参照してください。通常、サーバーはクライアントを認証する必要がありますが、これは通常、セキュリティで保護された接続が確立された後にサーバーに戻されるユーザー名/パスワードメッセージによって行われます。サーバーとクライアントの両方でそれを処理するコードを書く責任があります。ここで

は、私がSSL接続を介してサーバーに接続するために使用するいくつかのコードです:

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(); 
    } 
} 
+0

お返事ありがとうございます - 投票しました!問題はクライアント側で何も変更できないことです。それは "ブラックボックス"です - うまくいけば、Webブラウザの動作を備えた標準のHTTPSクライアントです。そうでなければ簡単だろう。あなたが提供したリンクのように、私は標準的なアプローチに従う必要があります。 – vitakot

関連する問題