我必须创建一个密钥分发服务器,它只是一个本地服务器,通过自己的API从DRM提供程序获取AES密钥,并将它们返回给连接的客户端。客户端是我自己的基于FFmpeg库的媒体播放器或本机Android媒体播放器。
我在Windows上使用Boost ASIO库和OpenSSL进行了实验 - 有一个如何创建简单HTTPS服务器和客户端的示例。在我的情况下,我必须只启用服务器访问专用的应用程序/客户端,所以我需要一个客户端身份验证。有一些事情我不清楚,因为我从来都不是这类事情的专家。
我知道HTTPS服务器必须要求客户端进行身份验证,客户端应该发送其证书,服务器然后reeds并验证证书中的某些数据。 问题是:
我正在撰写的所有内容都在本机级别执行,即它由Linux共享库实现。这就是为什么我认为对于普通的Android开发者而言,这对Linux大师来说是个问题。
有人可以解释我 - 在一些子弹中,如何做到这一点 - 如果有可能的话?任何提示都是受欢迎的!
非常感谢!
答案 0 :(得分: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();
}
}