openssl證書生成和源碼wince編譯及其使用

OpenSSL

一、證書

1、  證書製作

1)  生成root 證書

 <server>

openssl genrsa -out server\server_root.key 2048

              openssl  req -x509 -new -key server\server_root.key-days 10000 -out server\server_root.crt -subj"/C=US/ST=California/L=Silicon Valley/O=CAcert.org/OU=CAcert/CN=server_root/[email protected]"

輸出:server\server_root.key server\server_root.crt

<client>

openssl genrsa -out client\client_root.key 2048

openssl req -x509 -new -key client\client_root.key -days 10000 -outclient\client_root.crt -subj "/C=US/ST=California/L=SiliconValley/O=CAcert.org/OU=CAcert/CN=client_root/[email protected]"

輸出:client\client_root.key client\client_root.crt

2)  生成CA證書

<server>

openssl genrsa -out server\ford_server.key 2048

openssl req -new -key server\ford_server.key -days 10000 -outserver\ford_server.crt.req -subj"/C=US/ST=Michigan/L=Detroit/O=FORD_SERVER/OU=FORD_SDL_SERVER/CN=FORD/[email protected]"

openssl x509 -hash -req -in server\ford_server.crt.req -CAserver\server_root.crt -CAkey server\server_root.key -CAcreateserial -outserver\ford_server.crt -days 10000

輸出:server\ford_server.key server\ford_server.crt

<client>

openssl genrsa -out client\ford_client.key 2048

openssl req -new -key client\ford_client.key -days 10000 -outclient\ford_client.crt.req -subj"/C=US/ST=Michigan/L=Detroit/O=FORD_CLIENT/OU=FORD_SDL_CLIENT/CN=FORD_CLIENT/[email protected]"

openssl x509 -hash -req -in client\ford_client.crt.req -CAclient\client_root.crt -CAkey client\client_root.key -CAcreateserial -outclient\ford_client.crt -days 10000

輸出:client\ford_client.key  client\ford_client.crt

3)  分別合併

輸出:server\ server_verification_ca_cetrificates.crt client\ client_verification_ca_cetrificates.crt

 

4)  生成簽名加密證書

<server>

openssl genrsa -out server\server.key 2048

openssl req -new -key server\server.key -days 10000 -out server\server.crt.req-subj "/C=RU/ST=Russia/L=St.Petersburg/O=Luxoft/OU=Mobile/CN=server/[email protected]/serialNumber=SPT"

openssl x509 -hash -req -in server\server.crt.req -CA server\ford_server.crt-CAkey server\ford_server.key -CAcreateserial -out server\server.crt -days10000

openssl pkcs12 -export -out server\spt_credential.p12 -inkey server\server.key-in server\server.crt -name "SPT key and certificates" -CAfile client\client_verification_ca_cetrificates.crt  -passout pass:

輸出:server\server.key server\server.crt  server\spt_credential.p12

<client>

openssl genrsa -out client\client.key 2048

openssl req -new -key client\client.key -days 10000 -out client\client.crt.req-subj "/C=RU/ST=Russia/L=St.Petersburg/O=Luxoft/OU=HeadUnit/CN=client/[email protected]/serialNumber=SPT"

openssl x509 -hash -req -in client\client.crt.req -CA client\ford_client.crt-CAkey client\ford_client.key -CAcreateserial -out client\client.crt -days10000

輸出:client\client.key client\client.crt

5)  生成無簽名證書

<server>

openssl req -x509 -new -key server\server.key -days 10000 -outserver\server_unsigned.crt -subj "/C=RU/ST=Russia/L=St.Petersburg/O=Luxoft/OU=Mobile_unsigned/CN=server/[email protected]/serialNumber=SPT"

openssl pkcs12 -export -out server\spt_credential_unsigned.p12 -inkeyserver\server.key -in server\server_unsigned.crt -name "SPT key andcertificates" -CAfile  client\client_verification_ca_cetrificates.crt  -passout pass:

openssl req -new -key server\server.key -days 10000 -outserver\server_expired.crt.req -subj "/C=RU/ST=Russia/L=St.Petersburg/O=Luxoft/OU=Mobile_expired/CN=server/[email protected]/serialNumber=SPT"

輸出:server\server_unsigned.crt  server\spt_credential_unsigned.p12  server\server_expired.crt.req server\spt_credential_unsigned.p12.enc (base64編碼)

<client>

openssl req -x509 -new -key client\client.key -days 10000 -out client\client_unsigned.crt-subj "/C=RU/ST=Russia/L=St.Petersburg/O=Luxoft/OU=Mobile_unsigned/CN=client/[email protected]/serialNumber=SPT"

openssl pkcs12 -export -out client\client_credential_unsigned.p12 -inkeyclient\client.key -in client\client_unsigned.crt -name "SPT key andcertificates" -CAfile server\server_verification_ca_cetrificates.crt  -passout pass:

1> --== Client pkcs12 expiredcertificate generating ==--

openssl req -new -key client\client.key -days 10000 -out client\client_expired.crt.req-subj "/C=RU/ST=Russia/L=St.Petersburg/O=Luxoft/OU=Mobile_expired/CN=client/[email protected]/serialNumber=SPT"

輸出:client\client_unsigned.crt client\client_credential_unsigned.p12 client\client_expired.crt.req client\client_credential_unsigned.p12.enc(base64編碼)

 

二、編譯

1) 下載openssl  :git clone https://github.com/openssl/openssl.git

2)  下載並編譯wcecompat,wince openssl依賴它的頭文件和庫

地址:git clone https://github.com/mauricek/wcecompat.git

編譯wcecompat ,直接使用Qt打開wcecompat.pro用Qt編譯即可完成

然後把編譯好的.lib 文件和include 文件夾放到c盤c:\wcecompat

3)  下載並安裝Microsoft eMbedded C++ 4.0

4)  安裝WCE SDK,例如CHSINT SDK For WinCE(ARMV4I)

5)  下載並安裝perl

6)  編譯openssl:

a)  找到C:\Program Files (x86)\Microsoft eMbedded C++ 4.0\EVC\WCE400\BIN\WCEARMV4I.BAT用文本編輯器打開,修改以下內容:

REM   PLATFORM=CHSINT SDK For WinCE 6.0

REM        OSVERSION=WCE600

REM        WCEROOT=C:\Program Files(x86)\Microsoft eMbedded C++ 4.0 

REM        SDKROOT=C:\Program Files (x86)\WindowsCE Tools

 

setPATH=%WCEROOT%\COMMON\EVC\bin;%WCEROOT%\EVC\WCE400\bin;C:\Program Files(x86)\Microsoft Visual Studio 9.0\VC\ce\bin\x86_arm;C:\Program Files(x86)\Microsoft Visual Studio 9.0\VC\bin;C:\Program Files (x86)\MicrosoftVisual Studio 9.0\Common7\Tools;C:\Program Files (x86)\Microsoft Visual Studio9.0\Common7\IDE;%path%

setINCLUDE=%SDKROOT%\%OSVERSION%\%PLATFORM%\include\ARMV4I;%SDKROOT%\%OSVERSION%\%PLATFORM%\MFC\include;%SDKROOT%\%OSVERSION%\%PLATFORM%\ATL\include;C:\ProgramFiles (x86)\Microsoft Visual Studio 9.0\VC\ce\include;C:\Program Files(x86)\Microsoft Visual Studio 9.0\VC\ce\atlmfc\include;

set LIB=%SDKROOT%\%OSVERSION%\%PLATFORM%\lib\ARMV4I;%SDKROOT%\%OSVERSION%\%PLATFORM%\MFC\lib\ARMV4I;%SDKROOT%\%OSVERSION%\%PLATFORM%\ATL\lib\ARMV4I;C:\ProgramFiles (x86)\Microsoft Visual Studio 9.0\VC\ce\lib\armv4i;C:\Program Files(x86)\Microsoft Visual Studio 9.0\VC\ce\atlmfc\lib\armv4i;

 

b)  運行cmd,執行剛纔修改的WCEARMV4I.BAT 文件

c)  設置WCECOMPAT的路徑,否則openssl找不到相關頭文件和依賴的庫。執行 set WCECOMPAT=C:\wcecompat

需要注意的是 wcecompat  源碼下 time.c 裏面涉及struct tm的需要修改,這是個bug,

struct tm
{
	int tm_sec;
	int tm_min;
	int tm_hour;
	int tm_mday;
	int tm_mon;
	int tm_year;
	int tm_wday;
	int tm_yday;
	int tm_isdst;
};


tm_year 的值=實際年份-1900

tm_mon=實際月份-1

比如2016年8月20日,那麼它的值應該是: 

tm_year=2016-1900=116;

tm_mon=8-1=7

如果不改,可能導致openssl 校驗證書時會出現“format error in certificate's notBefore field” 錯誤,實際上證書沒錯,只是wcecompat裏面gmtime錯了,導致openssl裏面調用的時候 tm_year=2016 ,不在取值範圍內

d)  set OSVERSION=WCE600

e)  cd到openssl源碼目錄執行perl Configure VC-CE

f)  執行ms\do_ms 生成兩個mak文件,ms\ce.mak 和ms\cedll.mak,一個是靜態庫一個是動態庫

g)  刪除ms\ce.mak裏面的CFLAG 裏面的-WX,然後執行nmake –f ms\ce.mak 編譯完成。

 

三、使用openssl

1)   初始化

SSL_load_error_strings();

ERR_load_BIO_strings();

OpenSSL_add_all_algorithms();

   SSL_library_init();

2)   建立安全連接

server 端:以1.0版本協議爲例

// 設置SSL指針

SSL_CTX *ctx=SSL_CTX_new(SSLv1_server_method());

// 建立連接

SSL *conn = SSL_new(SSL_CTX* ctx);

void SSL_set_accept_state(SSL *);// server端使用

void SSL_set_connect_state(SSL *);// client端使用

3)   證書使用

// base64解碼

BIO* bio =BIO_new(BIO_f_base64());

                 BIO* bmem = BIO_new_mem_buf((char*)cert_data.c_str(), cert_data.length());

                  bmem = BIO_push(bio, bmem);

 

                char* buf = new char[cert_data.length()];

                int len =BIO_read(bmem, buf, cert_data.length());

BIO* bio_cert =BIO_new(BIO_s_mem());

                 int k = BIO_write(bio_cert, buf, len);

  PKCS12* p12 = d2i_PKCS12_bio(bio_cert, NULL);

                  EVP_PKEY* pkey = NULL;

                  X509* cert = NULL;

                  PKCS12_parse(p12, NULL, &pkey,&cert, NULL);

SSL_CTX_use_certificate(context_,cert);

asn1_time_to_tm(X509_get_notAfter(cert));

SSL_CTX_use_PrivateKey(context_,pkey);

SSL_CTX_check_private_key(context_);

 

// 加載信任證書

SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,

                                  const char *CApath);

CAfile是可信任證書文件名,CApath證書所在路徑

4)   讀寫操作

// 設置BIO,用於存放讀寫的緩存

void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio);

SSL_is_init_finished(a); //在通信之前有個握手操作,握手操作完成才能算初始化完成

int BIO_read(BIO *b, void *data, int len);

int BIO_write(BIO *b, const void *data, int len);

 

5)  握手操作

在通信之前有個握手操作,交換驗證證書

//握手操作

int SSL_do_handshake(SSL *s);

6)   結束處理

void  SSL_shutdown(SSL *);

void  free(SSL *);

void SSL_CTX_free(SSL_CTX *);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章