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

    技术2025-10-06  6

    年前写了一些关于windows 下c++通过openssl访问https站点的东西,有兴趣的可以看看http://blog.csdn.net/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 

    最新回复(0)