Lokaler HTTPS-Server auf Android mit Client-Authentifizierung

Ich muss einen Key-Distribution-Server erstellen, der nur ein lokaler Server sein soll, der AES-Schlüssel vom DRM-Provider über seine eigene API erhält und sie an die angeschlossenen Clients zurückgibt. Der Client ist entweder mein eigener Mediaplayer, der auf der FFmpeg-Bibliothek oder dem nativen Android Media Player basiert.

Ich habe auf Windows mit Boost ASIO-Bibliothek und OpenSSL experimentiert – es gibt ein Beispiel dafür, wie man einen einfachen HTTPS Server und Client erstellt. In meinem Fall muss ich den Zugriff auf den Server nur auf dedizierte Anwendungen / Clients aktivieren, damit ich eine Client-Authentifizierung benötige. Es gibt ein paar Dinge, die mir unklar sind, da ich noch nie ein Experte in dieser Art von Sachen gewesen bin.

Ich weiß, dass HTTPS-Server muss Client für die Authentifizierung fragen, sollte der Client sein Zertifikat senden, Server dann Schilf und validiert einige Daten aus dem Zertifikat. Die Fragen sind:

  • Welche Art von Zertifikat benötige ich für den Client, wie kann ich es schaffen?
  • Welche Art von Zertifikat benötige ich für Server, wie kann ich es erstellen?
  • Wo kann ich das Client-Zertifikat so speichern, dass es für die Clients zugänglich ist (FFmpeg, Android MediaPlayer)? Es darf nicht für jede andere Anwendung zugänglich sein.
  • Wo kann ich das Serverzertifikat speichern?

Alles, was ich schreibe, führt auf der nativen Ebene, dh es wird von Linux geteilten Bibliotheken implementiert. Das ist der Grund, warum ich denke, es ist eher eine Frage für Linux-Gurus dann für gängige Android-Entwickler.

Kann mir jemand erklären – in ein paar Kugeln, wie dies geschehen könnte – wenn es jemals möglich ist? Alle Hinweise sind auch willkommen!

Danke vielmals!

  • SSL / TLS-Protokolle und Chiffre-Suiten mit dem AndroidHttpClient
  • In-App Kauf Signaturprüfung mit PHP openssl
  • Unbekannter Protokollfehler mit HTTPS-Verbindung auf Android
  • Übertragen Sie PrivateKey von KeyStore, verwenden Sie in OpenSSL mit JNI
  • Android App auf die neueste Version von OpenSSL aktualisieren
  • Javax.crypto.Cipher arbeiten anders als Android 6 Marshmallow
  • Android ssl: javax.net.ssl.SSLPeerUnverifiedException: Kein Peer-Zertifikat (nochmal)
  • Wie importiere ich den RSA-privaten Schlüssel, der von openssl generiert wurde, in AndroidKeyStore
  • One Solution collect form web for “Lokaler HTTPS-Server auf Android mit Client-Authentifizierung”

    Also, zuerst aus, der Server fragt den Client nicht nach einem Zertifikat. Es ist umgekehrt. Der Client kann, aber nicht immer, das Zertifikat vom Server anfordern. Von der Formulierung Ihrer Frage, es klingt wie Sie vielleicht nicht brauchen, um ein Zertifikat zu verwenden. Siehe diesen Link für weitere Informationen sonst. Der Server muss normalerweise den Client authentifizieren, aber dies geschieht in der Regel über eine Benutzername / Passwort-Nachricht, die an den Server zurückgegeben wird, nachdem eine sichere Verbindung vorhanden ist. Sie sind verantwortlich für das Schreiben des Codes, um das auf dem Server und dem Client zu behandeln.

    Hier ist ein Code, den ich für die Verbindung zu einem Server über eine SSL-Verbindung verwende:

    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(); } } 
    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.