windows mobile 下访问通过openssl 访问https 站点

本文介绍如何使用OpenSSL在Windows Mobile平台上实现HTTPS访问功能。通过移植OpenSSL库,并使用MFC进行编程,实现了与Windows平台相似的功能。同时提供了客户端代码及必要的资源下载链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

年前写了一些关于windows 下c++通过openssl访问https站点的东西,有兴趣的可以看看http://blog.youkuaiyun.com/shangwei97/archive/2011/01/30/6170258.aspx

其实我的目的最终是在windows mobile 上实现访问https的功能。

通过openssl可以访问https的站点后,其实移植到wm上是很简单的事,知道重新编译openssl在evc下生成可以在wm下使用的dll就行。我没有编译而是从网上找来一个可以使用的dll,其实为了更好的控制程序,dll最好还是把源码把握在自己手里,这样方便查明问题的所在。

废话不多说了,把程序代码贴出来,和相关的下载地址也贴出来。

下面是wm下可以使用的openssl的程序http://u.115.com/file/f3396b0792#Openssl0.98g_lib_ARMV4_dll.zip

在程序正常调试还需要一个include文件包,其中包含了openssl要用到的头文件

下载地址http://u.115.com/file/f3996c187a#include.rar

wm下的代码基本上和windows下没有区别只是个别的头文件名称不一致下面是程序的源码,是在mfc程序下的,这里只列出头文件和具体的访问事件里的内容。

/**************************************************************/

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <Winbase.h>
//#include <sys/types.h>
#include <winsock.h>
#include <winsock2.h>

#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"

#pragma comment(lib, "libeay32.lib")
#pragma comment(lib, "ssleay32.lib")
#pragma comment(lib, "ws2.lib")
//#pragma comment(lib, "ws2_32.lib")
//ws2_32.lib libeay32.lib ssleay32.lib
/*所有需要的参数信息都在此处以#define的形式提供*/
#define PORT 5555 /*服务端的端口*/
#define SERVER_ADDR "172.16.140.216" /*服务段的IP地址*/

#define CHK_NULL(x) if ((x)==NULL) exit (-1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(-2); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(-3); }

using namespace std;

 

 

//具体的事件,GetByte是为了发送多数据而设计的这里没有用到

long GetByte(byte* byData)
{
 HANDLE hfile = INVALID_HANDLE_VALUE;

    //BYTE pByte[4096] = {0};
    unsigned long bytesRead = 0;
 char pByte[4096];         

 LPCWSTR szFileName = L"//Program Files//HttpsTest//test.txt";
    DWORD lowerFileSize = 0;

    hfile = CreateFile(szFileName, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
    if (INVALID_HANDLE_VALUE == hfile)
        return 0;
  
    lowerFileSize = GetFileSize (hfile, NULL);

    ReadFile(hfile , (LPVOID)pByte, lowerFileSize+1, &bytesRead ,NULL );

    memcpy(byData,pByte,lowerFileSize);
 byData[lowerFileSize] = 0;
    return lowerFileSize;

}
void CHttpsTestDlg::OnBnClickedBtGo()
{
 int err;
 int sd;
 struct sockaddr_in sa;
 SSL_CTX* ctx;
 SSL* ssl;
 X509* server_cert;
 char* str;
 char buf [4096];
 SSL_METHOD *meth;
 int seed_int[100]; /*存放随机序列*/
   
 byte byData[4096];
    memset(byData,0,4096);
    int iLen = GetByte(byData);

 WSADATA wsaData;

 if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0)
 {
  printf("WSAStartup()fail:%d/n",GetLastError());
  return ;
 }

 OpenSSL_add_ssl_algorithms(); /*初始化*/
 SSL_load_error_strings(); /*为打印调试信息作准备*/

 meth = TLSv1_client_method(); /*采用什么协议(SSLv2/SSLv3/TLSv1)在此指定*/
 ctx = SSL_CTX_new (meth);
 CHK_NULL(ctx);

 /*构建随机数生成机制,WIN32平台必需*/
 //srand( (unsigned)time( NULL ) );
 for( int i = 0; i < 100;i++ )
 seed_int[i] = rand();
 RAND_seed(seed_int, sizeof(seed_int));

 /*以下是正常的TCP socket建立过程 .............................. */
 printf("Begin tcp socket.../n");

 sd = socket (AF_INET, SOCK_STREAM, 0);
 //CHK_ERR(sd, "socket");

 memset (&sa, '/0', sizeof(sa));
 sa.sin_family = AF_INET;
 sa.sin_addr.s_addr = inet_addr (SERVER_ADDR); /* Server IP */
 sa.sin_port = htons (PORT); /* Server Port number */

 err = connect(sd, (struct sockaddr*) &sa,sizeof(sa));
 //CHK_ERR(err, "connect");

 /* TCP 链接已建立.开始 SSL 握手过程.......................... */
 printf("Begin SSL negotiation /n");
    //system("pasue");
 ssl = SSL_new (ctx);
 CHK_NULL(ssl);

 SSL_set_fd (ssl, sd);
 err = SSL_connect (ssl);
 CHK_SSL(err);

 /*打印所有加密算法的信息(可选)*/
 printf ("SSL connection using %s/n", SSL_get_cipher (ssl));

 /*得到服务端的证书并打印些信息(可选) */
 server_cert = SSL_get_peer_certificate (ssl);
 CHK_NULL(server_cert);
 printf ("Server certificate:/n");

 str = X509_NAME_oneline (X509_get_subject_name (server_cert),0,0);
 CHK_NULL(str);
 printf ("/t subject: %s/n", str);
 //free (str);

 str = X509_NAME_oneline (X509_get_issuer_name (server_cert),0,0);
 CHK_NULL(str);
 printf ("/t issuer: %s/n", str);
 //free (str);

 X509_free (server_cert); /*如不再需要,需将证书释放 */

 /* 数据交换开始,用SSL_write,SSL_read代替write,read */
 printf("Begin SSL data exchange/n");

 err = SSL_write (ssl, "Knock/r/n", strlen("Knock/r/n"));
 //err = SSL_write (ssl, (LPVOID)byData,iLen);
 CHK_SSL(err);

 err = SSL_read (ssl, buf, sizeof(buf) - 1);
 CHK_SSL(err);

 buf[err] = '/0';
 printf ("Got %d chars:'%s'/n", err, buf);
 SSL_shutdown (ssl); /* send SSL/TLS close_notify */

 /* 收尾工作 */
 shutdown (sd,2);
 SSL_free (ssl);
 SSL_CTX_free (ctx);
}

/**********************************************************/

// 下面是server端的程序,是用java写的证书的生成过程,可以参考以前我先前写的那个贴子。是结合keytool和openssl来生成的

//java服务 代码

 

 import  java.io. * ;
 import  java.net. * ;
 import  com.sun.net.ssl.KeyManagerFactory;
 import  com.sun.net.ssl.KeyManager;
 import  com.sun.net.ssl.TrustManagerFactory;
 import  com.sun.net.ssl.TrustManager;
 import  com.sun.net.ssl.SSLContext;
 import  javax.net.ServerSocketFactory;
 import  java.security.KeyStore;

 public   class  svr  implements  Runnable {
 
   public   static   final   int  PORT  =   5555 ;
   public   static   final  String HOST  =  "localhost";
   public   static   final  String QUESTION  ="Knock";
   public   static   final  String ANSWER  =  "I am 140.129,Who's there?";

   //  The new constants that are used during setup.
    public   static   final  String KEYSTORE_FILE  =  "mycerts"; //"server_keystore";
    public   static   final  String ALGORITHM  =  "sunx509";
   public   static   final  String PASSWORD  =  "111111";
 
   public   static   void  main(String[] args) {
     new  Thread( new  svr()).start();
  }
 
   public   void  run() {
    ServerSocket ss  =   null ;
     try   {

       //  Local references used for clarity. Their presence
       //  here is part of the reason we need to import
       //  so many classes.
       KeyManagerFactory kmf;
      KeyManager[] km;
      KeyStore ks;
      TrustManagerFactory tmf;
      TrustManager[] tm;
      SSLContext sslc;
     
       //  Create a keystore that will read the JKS (Java KeyStore)
       //  file format which was created by the keytool utility.
       ks  =  KeyStore.getInstance("JKS");
     
       //  Load the keystore object with the binary keystore file and
       //  a byte array representing its password.
       ks.load( new  FileInputStream(KEYSTORE_FILE), PASSWORD.toCharArray());
     
       //  Gives us a factory for key managers that will let
       //  us handle the asymetric keys we created earlier.
       kmf  =  KeyManagerFactory.getInstance(ALGORITHM);

       //  Initialize the key manager factory with the keystore object,
       //  again using the same password for security since it is going to
       //  access the private key.
       kmf.init(ks, PASSWORD.toCharArray());
     
       //  Now we can get the key managers from the factory, since it knows
       //  what type we are using now.
       km  =  kmf.getKeyManagers();
     
       //  Next, create a trust manager factory using the same algorithm.
       //  This is to avoid using the certificates in cacerts that
       //  represent an authentication security risk.
       tmf  =  TrustManagerFactory.getInstance(ALGORITHM);
     
       //  then initialize it with the keystore object. This time we don't
       //  need the keystore password. This is because trusted certificates
       //  are not a sensitive element in the keystore, unlike the
       //  private keys.
       tmf.init(ks);
     
       //  Once that's initialized, get the trust managers from the factory.
       tm  =  tmf.getTrustManagers();
     
       //  Almost done, we need a context object that will get our
       //  server socket factory. We specify TLS to indicate that we will
       //  need a server socket factory that supports SSL.
       sslc  =  SSLContext.getInstance("TLS");
     
       //  Initialize the context object with the key managers and trust
       //  managers we got earlier. The third parameter is an optional
       //  SecureRandom object. By passing in null, we are letting the
       //  context object create its own.
       sslc.init(km, tm,  null );
     
       //  Finally, we get the ordinary-looking server socket factory
       //  from the context object.
       ServerSocketFactory ssf  =  sslc.getServerSocketFactory();
     
       //  From the factory, we simply ask for an ordinary-looking
       //  server socket on the port we wish.
       ss  =  ssf.createServerSocket(PORT);

      listen(ss);
    }
      catch (Exception e) {
      e.printStackTrace();
    }
      finally {
       if (ss != null ) {
         try {
          ss.close();
        }
          catch (IOException e) {
           //  oh, well
         }
      }
      System.exit( 0 );
    }
  }
 
   static   void  listen(ServerSocket ss)  throws  Exception {
    System.out.println("Ready for connections.");
     while ( true ) {
      Socket s  =  ss.accept();
      BufferedWriter bw  =   new  BufferedWriter(
         new  OutputStreamWriter(s.getOutputStream()));
      BufferedReader br  =   new  BufferedReader(
         new  InputStreamReader(s.getInputStream()));
      String q  =  br.readLine();
       while ( ! QUESTION.equals(q)) {
         //throw   new  RuntimeException("Wrong question: /"" + q + "/"");
         System.out.println("Wrong question: /"" + q + "/"");
      }
      System.out.println("Question: /"" + q + "/"");
      bw.write(ANSWER +"/n");
      bw.flush();
      s.close();
    }
  }
}

/*******************************************************************/

 

希望能给正在做https或者正在用openssl的朋友一点帮助

如果下载过期了,可以发邮件到shangwei97@163.com 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值