免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1206 | 回复: 0
打印 上一主题 下一主题

openssl的简单使用 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-04-28 16:30 |只看该作者 |倒序浏览

OpenSSL的运用比较广泛了,最主要的也许是它是开源的。
下面是我的一个简单例子:
#include
#include
#include
#include
#include "openssl/rsa.h"
#include "openssl/crypto.h"
#include "openssl/x509.h"
#include "openssl/pem.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
#include "openssl/rand.h"
class SSLClientSocket
{
public:
    static const char HEADER_LINE_DELIMITER = '\n';
public:
    SSLClientSocket ();
   
    virtual ~SSLClientSocket ();
public:
    static int InitWinsock ();
   
static int InitCtx(bool bServer,int VerType);
public:
    bool IsOpened () const;
    int Connect (const CString& host, int port);
    void Disconnect ();
    int Poll ();
public:
    virtual void OnConnected () = 0;
    virtual void OnDisconnected () = 0;
    virtual void OnMessage (MXMessage& msg) = 0;
   
    int SendData (const CString& buf);
private:
    void ResetSocketState ();
    int ParseHeaderLine (const CString &line);
    int ProcessInputBuffer ();
int SSLrecv (char *buf, int len);
int SSLsend (char *buf, int len);
private:
    SOCKET _socket;
    CString _input_buf;
    CString _output_buf;
    bool _is_reading_body;
    int _body_bytes_to_read;
    MXMessage _tmp_message;
private:
int err;
static SSL_CTX* ctx;
static SSL*     ssl;
static X509*    server_cert;
static SSL_METHOD *meth;
static int       seed_int[100]; /*存放随机序列*/
WSADATA wsaData;
public:
static CString strCERTF;  /*客户端的证书(需经CA签名)*/
static CString strKEYF;  /*客户端的私钥(建议加密存储)*/
static CString strCACERT;  /*CA 的证书*/
};
#endif // SSL_CLIENTSOCKET_H
#include "stdafx.h"
#include "ssl_clientsocket.h"
SSL_CTX* SSLClientSocket::ctx;
SSL*  SSLClientSocket::ssl;
X509*  SSLClientSocket::server_cert;
SSL_METHOD* SSLClientSocket::meth;
int   SSLClientSocket::seed_int[100]; /*存放随机序列*/
CString  SSLClientSocket::strCERTF="";  /*客户端的证书(需经CA签名)*/
CString  SSLClientSocket::strKEYF="";  /*客户端的私钥(建议加密存储)*/
CString  SSLClientSocket::strCACERT="";  /*CA 的证书*/
int SSLClientSocket::InitWinsock ()
{
WORD sockVersion;
WSADATA wsaData;
sockVersion = MAKEWORD (2, 2);
    TRACE0 ("Initializing WinSock...\n");
// Initialize Winsock as before
if (WSAStartup (sockVersion, &wsaData) != NO_ERROR)
    {
        TRACE0 ("WinSock failed to initialize !!!\n");
        return -1;
    }
    TRACE0 ("WinSock initialized successfully\n");
strCERTF = "gameclient-cert.pem";  /*客户端的证书(需经CA签名)*/
strKEYF = "gameclient-key.pem";   /*客户端的私钥(建议加密存储)*/
strCACERT = "cacert.pem";    /*CA 的证书*/
int nret = InitCtx (false,0);
TRACE1("The Return of Ctx initialization is %d\n",nret);
    return nret;
}
int SSLClientSocket::InitCtx(bool bServer,int VerType)
{
OpenSSL_add_ssl_algorithms();     /*初始化*/
SSL_load_error_strings();      /*为打印调试信息作准备*/
if (bServer)         /*采用什么协议(SSLv2/SSLv3/TLSv1)在此指定*/
  meth = TLSv1_server_method();  
else
  meth = TLSv1_client_method();
ctx = SSL_CTX_new (meth);
if (ctx == NULL)
  return -2;
SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER, NULL);   /*验证与否*/
SSL_CTX_load_verify_locations (ctx, strCACERT.GetBuffer(), NULL); /*若验证,则放置CA证书*/
if (SSL_CTX_use_certificate_file (ctx, strCERTF.GetBuffer(), SSL_FILETYPE_PEM) ResetSocketState ();
//this->InitWinsock ();
}
SSLClientSocket::~SSLClientSocket ()
{
    if (this->_socket != 0)
    {
        TRACE0 ("SSLClientSocket being destructed. Closing socket...\n");
        this->Disconnect ();
    }
}
//
// Public Methods
//
bool SSLClientSocket::IsOpened () const
{
    return this->_socket != 0;
}
int SSLClientSocket::Poll ()
{
    if (this->_socket == 0)
        return -1;
    fd_set read_fds;
    fd_set write_fds;
    FD_ZERO (&read_fds);
    FD_ZERO (&write_fds);
    FD_SET (this->_socket, &read_fds);
    if (!this->_output_buf.IsEmpty ())
    {
        FD_SET (this->_socket, &write_fds);
    }
    timeval timeout = { 0, 0 };
    int nret = select (1, &read_fds, &write_fds, 0, &timeout);
    if (nret == SOCKET_ERROR)
        return -2;
    if (FD_ISSET (this->_socket, &write_fds))
    {
        int len = SSLsend (this->_output_buf.GetBuffer (), this->_output_buf.GetLength ());
        if (len > 0)
        {
            if (len == this->_output_buf.GetLength ())
            {
                this->_output_buf.Empty ();
            }
            else
            {
                this->_output_buf = this->_output_buf.Mid (len);
            }
        }
        else if (len == SOCKET_ERROR)
        {
            return -3;
        }
    }
    if (FD_ISSET (this->_socket, &read_fds))
    {
        const int BUF_SIZE = 1024;
        char buf[BUF_SIZE];
        int len = SSLrecv (buf, BUF_SIZE);
        if (len > 0)
        {
            this->_input_buf.Append (buf, len);
            this->ProcessInputBuffer ();
        }
        else if (len == 0 || len == SOCKET_ERROR)
        {
            // TODO: Check for connection reset
            this->Disconnect ();
            this->OnDisconnected ();
            return -4;
        }
    }
    return 0;
}
void SSLClientSocket::Disconnect ()
{
    if (this->_socket != 0)
    {
        shutdown (this->_socket, 2);
        closesocket (this->_socket);
  return;
        this->_socket = 0;
        this->ResetSocketState ();
  if (ssl != NULL) SSL_free (ssl);
  if (ctx != NULL) SSL_CTX_free (ctx);
    }
}
int SSLClientSocket::Connect(const CString& host, int port)
{
    if (this->_socket != 0)
    {
        TRACE0 ("Attempt to connect with existing connection. Closing socket...\n");
        this->Disconnect ();
    }
    _socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (_socket == INVALID_SOCKET)
    {
        int nret = WSAGetLastError ();
        return -255;
    }
LPHOSTENT hostEntry;
// Specifying the server by its name;
    // another option is gethostbyaddr() (see below)
hostEntry = gethostbyname (host);
if (!hostEntry) {
  int nret = WSAGetLastError ();
  //ReportError(nret, "gethostbyname()"); // Report the error as before
  return -256;
}
    // Fill a SOCKADDR_IN struct with address information
SOCKADDR_IN serverInfo;
serverInfo.sin_family = AF_INET;
// At this point, we've successfully retrieved vital information about the server,
// including its hostname, aliases, and IP addresses.  Wait; how could a single
// computer have multiple addresses, and exactly what is the following line doing?
// See the explanation below.
   
serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);
    // Change to network-byte order and
    // insert into port field
serverInfo.sin_port = htons(port);
// Connect to the server
int nret = connect (this->_socket, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr));
    if (nret == SOCKET_ERROR)
    {
        nret = WSAGetLastError ();
        return -257;
    }
  /* TCP 链接已建立.开始 SSL 握手过程.......................... */
nret = this->InitWinsock ();
    if (nret != 0)
        return -257 + nret;
TRACE0("Begin SSL negotiation \n");
ssl = SSL_new (ctx);
if (ssl == NULL) {
  TRACE0("Failed to create a new ssl \n");
  return -1;
}
SSL_set_fd (ssl, (int)_socket);
err = SSL_connect (ssl);
if (err _socket, FIONBIO, &arg);
    // Disable SO_LINGER on socket
    int arg2 = 1;
    setsockopt (this->_socket, SOL_SOCKET, SO_DONTLINGER, (char*)&arg2, sizeof(int));
    this->OnConnected ();
    return 0;
}
//
// Helper Method
//
int SSLClientSocket::SendData (const CString& buf)
{
    if (this->_socket == 0)
        return -1;
    this->_output_buf.Append (buf);
    return this->_output_buf.GetLength ();
}
void SSLClientSocket::ResetSocketState ()
{
    this->_input_buf = "";
    this->_output_buf = "";
    this->_is_reading_body = false;
    this->_body_bytes_to_read = 0;
}
int SSLClientSocket::ProcessInputBuffer ()
{
    int stop = 0;
    int offset = 0;
    while (stop == 0 && offset _input_buf.GetLength ())
    {
        if (!this->_is_reading_body)
        {
            while (stop == 0 && offset _input_buf.GetLength ())
            {
                if (this->_input_buf[offset] == MXMessage::HEADER_LINE_DELIMITER)
                {
                    this->_body_bytes_to_read = this->_tmp_message.GetBodyLength ();
                    if (this->_body_bytes_to_read _body_bytes_to_read);
                        return -1;
                    }
                    else
                    {
                        TRACE1 ("Body length is %d bytes\n", this->_body_bytes_to_read);
                    }

                    this->_is_reading_body = true;
                    offset++;
                    if (this->_body_bytes_to_read == 0)
                    {
                        TRACE0 ("No body to read. Begin processing request\n");
                        this->OnMessage (this->_tmp_message);
                        this->_tmp_message.Clear ();
                        this->_is_reading_body = false;
                    }
                    else
                    {
                        TRACE1 ("Will need to read body of %d bytes.\n", this->_body_bytes_to_read);
                        break;
                    }
                }
                else
                {
                    int i = this->_input_buf.Find (MXMessage::HEADER_LINE_DELIMITER, offset);
                    if (i != -1)
                    {
                        // Parse header key-value
                        if (this->ParseHeaderLine (this->_input_buf.Mid (offset, i - offset)) != 0)
                        {
                            return -1;
                        }
                        offset = i + 1;
                    }
                    else // if (i == -1)
                    {
                        /* this->_input_buf does not contain MXMessage::HEADER_LINE_DELIMITER,
                           so stop processing input */
                        stop = 1;
                        break;
                    }
                }
            }
        }
        else // if (this->_is_reading_body)
        {
            if (this->_body_bytes_to_read > 0)
            {
                int len = this->_input_buf.GetLength () - offset;
                if (len _body_bytes_to_read)
                {
                    this->_tmp_message.GetBody () += this->_input_buf.Mid (offset);
                    this->_body_bytes_to_read -= len;
                    offset = this->_input_buf.GetLength ();
                    stop = 1;
                    TRACE2 ("Read %d bytes for body. %d bytes remaining to read for body\n", len, this->_body_bytes_to_read);
                }
                else // if (len >= this->_body_bytes_to_read)
                {
                    TRACE1 ("Read %d bytes for body. 0 byte remaining to read for body\n", this->_body_bytes_to_read);
                    
                    this->_tmp_message.GetBody () += this->_input_buf.Mid (offset, this->_body_bytes_to_read);
                    offset += this->_body_bytes_to_read;
                    this->_body_bytes_to_read = 0;
                    this->OnMessage (this->_tmp_message);
                    this->_tmp_message.Clear ();
                    this->_is_reading_body = false;
                }
            }
            else
            {
                // TODO: process_request(incoming_temp_message)
                this->OnMessage (this->_tmp_message);
                this->_tmp_message.Clear ();
                this->_is_reading_body = false;
            }
        }
    }
    if (offset _input_buf.GetLength ())
    {
        this->_input_buf.Delete (0, offset);
    }
    else
    {
        this->_input_buf.Empty ();
    }
    TRACE1 ("Input buffer now contains %d bytes\n", this->_input_buf.GetLength ());
    return 0;
}
int SSLClientSocket::ParseHeaderLine (const CString &line)
{
    int pos = line.Find (MXMessage::HEADER_DELIMITER);
    if (pos != -1)
    {
        if (pos == 0)
        {
            TRACE1 ("Empty header key: %s\n", line);
            return -1;
        }
        else if (pos == line.GetLength () - 1)
        {
            CString key = line.Left (pos);
            // TRACE1 ("Adding %s -> empty to header table\n", key);
            this->_tmp_message.GetHeaderMap ().SetAt (key, "");
        }
        else
        {
            CString key = line.Left (pos);
            CString value = line.Mid (pos + 1);
            // TRACE2 ("Adding %s -> %s to header table\n", key, value);
            this->_tmp_message.GetHeaderMap ().SetAt (key, value);
        }
        return 0;
    }
    else
    {
        TRACE1 ("Cannot parse header line: %s\n", line);
        return -1;
    }
}
//
// Virtual Methods
//
int SSLClientSocket::SSLrecv (char *buf, int len)
{
int k=0;
do
{
  while (1)
  {
   k = SSL_read(SSLClientSocket::ssl,buf,len);
   if (k


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/59726/showart_625681.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP