建置及執行安全 MQTT 用戶端範例 C 應用程式
根據 Windows 範例,您可以在可以為其編譯 C 原始檔的任何作業系統上,建立並執行安全範例 C 應用程式。 驗證您可以在 IBM® MessageSight 或 IBM WebSphere® MQ 作為 MQTT 伺服器上執行範例 C 應用程式。
開始之前
- 您必須能夠存取支援 MQTT protocol over SSL 的 MQTT version 3.1 伺服器。
- 如果用戶端與伺服器之間有防火牆,請確認它不會封鎖 MQTT 資料流量。
- 為許多作業系統提供適用於 C 的用戶端程式庫的二進位版本。 對於其中部分作業系統,未提供安全的用戶端版本作為二進位檔。 對於那些作業系統,您必須遵循 建置適用於 C 的 MQTT 用戶端程式庫中的指示。
- 為了解決問題, IBM 支援中心可能需要您在參照平台上執行 MQTT Client for C。
- SSL 通道必須已啟動。
如需受支援及參照平台的概觀,請參閱 IBM Mobile Messaging 和 M2M Client Pack的系統需求。 如需 C 用戶端支援的詳細資料,請參閱 WebSphere MQ V7.5 遙測的相關小節。
關於此作業
作為圖解,本文顯示如何從指令行編譯及執行 Windows 上的安全 MQTT 用戶端範例 C 應用程式 。 在圖解中,使用 Microsoft Visual Studio 2010 來編譯用戶端。 您可以修改指令行 Script ,以在其他作業系統上編譯並執行範例應用程式,例如 Linux® 及 iOS。
附註:
本文提供的 Windows Script 假設您從來源建置整個 OpenSSL 套件。 如果您選擇使用 IBM 提供的經過前置編譯的程式庫,則您還可能希望取得 OpenSSL 的經過前置編譯的二進位版本。 經過前置編譯的程式庫無法與 iOS搭配使用。使用憑證管理中心簽署的金鑰或自簽金鑰保護 SSL 通道。
程序
結果
結果類似於執行未受保護的用戶端。
用來執行安全 MQTT 用戶端範例 C 應用程式 的 Script
執行 範例 Script 以配置 Windows 的 SSL 憑證 中的 Script ,然後再執行這些 Script。
- 使用自簽憑證來保護 MQTT 用戶端範例 C 應用程式 的安全。
- 使用您透過執行 sscerts.bat Script 所建立的自簽憑證來執行此 Script。
- 使用憑證管理中心簽署的憑證執行 MQTT 安全用戶端範例 C 應用程式。
- 使用您透過執行 cacerts.bat Script 所建立的憑證管理中心簽署憑證來執行此 Script。
為 Windows配置 SSL 憑證的 Script 範例
範例
指令檔範例會建立憑證及憑證儲存庫,如作業中的步驟所述。 此外,此範例還會將 MQTT 用戶端佇列管理程式設定為使用伺服器憑證儲存庫。 範例會呼叫 IBM WebSphere MQ隨附的 SampleMQM.bat Script ,來刪除並重建佇列管理程式。
- initcert.bat
- initcert.bat 會設定 keytool 及 openSSL 指令所需之憑證及其他參數的名稱和路徑。 Script 中的註解說明了這些設定。
@echo off @rem Set the path where you installed the MQTT SDK @rem and short cuts to the samples directories. set SDKRoot=C:\MQTT set jsamppath=%SDKRoot%\sdk\clients\java\samples set csamppath=%SDKRoot%\sdk\clients\c\samples
@rem Set the paths to Version 7 of the JDK @rem and to the directory where you built the openSSL package. @rem Set short cuts to the tools. set javapath=C:\Program Files\IBM\Java70 set keytool="%javapath%\jre\bin\keytool.exe" set ikeyman="%javapath%\jre\bin\ikeyman.exe" set openssl=%SDKRoot%\openSSL set runopenssl="%openssl%\bin\openssl"
@rem Set the path to where certificates are to be stored, @rem and set global security parameters. @rem Omit set password, and the security tools prompt you for passwords. @rem Validity is the expiry time of the certificates in days. set certpath=%SDKRoot%\Certificates set password=password set validity=5000 set algorithm=RSA
@rem Set the certificate authority (CA) jks keystore and certificate parameters. @rem Omit this step, unless you are defining your own certificate authority. @rem The CA keystore contains the key-pair for your own certificate authority. @rem You must protect the CA keystore. @rem The CA certificate is the self-signed certificate authority public certificate. @rem It is commonly known as the CA root certificate. set caalias=caalias set cadname="CN=mqttca.ibm.id.com, OU=ID, O=IBM, L=Hursley, S=Hants, C=GB" set cakeypass=%password% @rem ca key store set cajkskeystore=%certpath%\cakeystore.jks set cajkskeystorepass=%password% @rem ca certificate (root certificate) set cacert=%certpath%\cacert.cer
@rem Set the server jks keystore and certificate parameters. @rem The server keystore contains the key-pair for the server. @rem You must protect the server keystore. @rem If you then export the server certificate it is self-signed. @rem Alternatively, if you export a certificate signing request (CSR) @rem from the server keystore for the server key, @rem and import the signed certificate back into the same keystore, @rem it forms a certificate chain. @rem The certificate chain links the server certificate to the CA. @rem When you now export the server certificate, @rem the exported certificate includes the certificate chain. set srvalias=srvalias set srvdname="CN=mqttserver.ibm.id.com, OU=ID, O=IBM, L=Hursley, S=Hants, C=GB" set srvkeypass=%password% @rem server key stores set srvjkskeystore=%certpath%\srvkeystore.jks set srvjkskeystorepass=%password% @rem server certificates set srvcertreq=%certpath%\srvcertreq.csr set srvcertcasigned=%certpath%\srvcertcasigned.cer set srvcertselfsigned=%certpath%\srvcertselfsigned.cer
@rem Set the client jks keystore and certificate parameters @rem Omit this step, unless you are authenticating clients. @rem The client keystore contains the key-pair for the client. @rem You must protect the client keystore. @rem If you then export the client certificate it is self-signed. @rem Alternatively, if you export a certificate signing request (CSR) @rem from the client keystore for the client key, @rem and import the signed certificate back into the same keystore, @rem it forms a certificate chain. @rem The certificate chain links the client certificate to the CA. @rem When you now export the client certificate, @rem the exported certificate includes the certificate chain. set cltalias=cltalias set cltdname="CN=mqttclient.ibm.id.com, OU=ID, O=IBM, L=Hursley, S=Hants, C=GB" set cltkeypass=%password% @rem client key stores set cltjkskeystore=%certpath%\cltkeystore.jks set cltjkskeystorepass=%password% set cltcertreq=%certpath%\cltcertreq.csr set cltcertcasigned=%certpath%\cltcacertsigned.cer set cltcertselfsigned=%certpath%\cltcertselfsigned.cer
@rem Set the paths to the client truststores signed by CA and signed by server key. @rem You only need to define one of the trust stores. @rem A trust store holds certificates that you trust, @rem which are used to authenticate untrusted certificates. @rem In this example, when the client authenticates the MQTT server it connects to, @rem it authenticates the certificate it is sent by the server @rem with the certificates in its trust store. @rem For example, the MQTT server sends its server certificate, @rem and the client authenticates it with either the same server certificate @rem that you have stored in the cltsrvtruststore.jks trust store, @rem or against the CA certificate, if the server certificate is signed by the CA. set cltcajkstruststore=%certpath%\cltcatruststore.jks set cltcajkstruststorepass=%password% set cltsrvjkstruststore=%certpath%\cltsrvtruststore.jks set cltsrvjkstruststorepass=%password%
@rem Set the paths to the client PKCS12 and PEM key and trust stores. @rem Omit this step, unless you are configuring a C or iOS client. @rem You only need to define either one of the trust stores for storing CA @rem or server signed server certificates. set cltp12keystore=%certpath%\cltkeystore.p12 set cltp12keystorepass=%password% set cltpemkeystore=%certpath%\cltkeystore.pem set cltpemkeystorepass=%password% set cltcap12truststore=%certpath%\cltcatruststore.p12 set cltcap12truststorepass=%password% set cltcapemtruststore=%certpath%\cltcatruststore.pem set cltcapemtruststorepass=%password% set cltsrvp12truststore=%certpath%\cltsrvtruststore.p12 set cltsrvp12truststorepass=%password% set cltsrvpemtruststore=%certpath%\cltsrvtruststore.pem set cltsrvpemtruststorepass=%password%
@rem set WMQ Variables set authopt=NEVER set authreq=REQUIRED set qm=MQXR_SAMPLE_QM set host=localhost set mcauser='Guest' set portsslopt=8884 set chlopt=SSLOPT set portsslreq=8885 set chlreq=SSLREQ set portws=1886 set chlws=PLAINWS set chlssloptws=SSLOPTWS set portssloptws=8886 set chlsslreqws=SSLREQWS set portsslreqws=8887 set mqlog=%certpath%\wmq.log
- cleancert.bat
- cleancert.bat Script 中的指令會刪除 MQTT 用戶端佇列管理程式,以確保伺服器憑證儲存庫未鎖定,然後刪除範例安全 Script 所建立的所有金鑰儲存庫及憑證。
@rem Delete the MQTT sample queue manager, MQXR_SAMPLE_QM call "%MQ_FILE_PATH%\bin\setmqenv" -s endmqm -i %qm% dltmqm %qm%
@rem Erase all the certificates and key stores created by the sample scripts. erase %cajkskeystore% erase %cacert% erase %srvjkskeystore% erase %srvcertreq% erase %srvcertcasigned% erase %srvcertselfsigned% erase %cltjkskeystore% erase %cltp12keystore% erase %cltpemkeystore% erase %cltcertreq% erase %cltcertcasigned% erase %cltcertselfsigned% erase %cltcajkstruststore% erase %cltcap12truststore% erase %cltcapemtruststore% erase %cltsrvjkstruststore% erase %cltsrvp12truststore% erase %cltsrvpemtruststore% erase %mqlog% @echo Cleared all certificates dir %certpath%\*.* /b
- genkeys.bat
- genkeys.bat Script 中的指令會為您的專用憑證管理中心、伺服器及用戶端建立金鑰組。
@rem @echo ________________________________________________________________________________ @echo Generate %caalias%, %srvalias%, and %cltalias% key-pairs in %cajkskeystore%, %srvjkskeystore%, and %cltjkskeystore% @rem @rem -- Generate a client certificate and a private key pair @rem Omit this step, unless you are authenticating clients. %keytool% -genkeypair -noprompt -alias %cltalias% -dname %cltdname% -keystore %cltjkskeystore% -storepass %cltjkskeystorepass% -keypass %cltkeypass% -keyalg %algorithm% -validity %validity%
@rem -- Generate a server certificate and private key pair %keytool% -genkeypair -noprompt -alias %srvalias% -dname %srvdname% -keystore %srvjkskeystore% -storepass %srvjkskeystorepass% -keypass %srvkeypass% -keyalg %algorithm% -validity %validity%
@rem Create CA, client and server key-pairs @rem -- Generate a CA certificate and private key pair - The extension asserts this is a certificate authority certificate, which is required to import into firefox %keytool% -genkeypair -noprompt -ext bc=ca:true -alias %caalias% -dname %cadname% -keystore %cajkskeystore% -storepass %cajkskeystorepass% -keypass %cakeypass% -keyalg %algorithm% -validity %validity%
- sscerts.bat
- sscerts.bat Script 中的指令會從其金鑰儲存庫匯出用戶端及伺服器自簽憑證,然後將伺服器憑證匯入用戶端信任儲存庫,並將用戶端憑證匯入伺服器金鑰儲存庫。 伺服器沒有信任儲存庫。 這些指令會從用戶端 JKS 信任儲存庫,以 PEM 的格式建立用戶端信任儲存庫。
@rem @echo ________________________________________________________________________________ @echo Export self-signed certificates: %srvcertselfsigned% and %cltcertselfsigned% @rem Export Server public certificate %keytool% -exportcert -noprompt -rfc -alias %srvalias% -keystore %srvjkskeystore% -storepass %srvjkskeystorepass% -file %srvcertselfsigned% @rem Export Client public certificate @rem Omit this step, unless you are authenticating clients. %keytool% -exportcert -noprompt -rfc -alias %cltalias% -keystore %cltjkskeystore% -storepass %cltjkskeystorepass% -file %cltcertselfsigned%
@rem @echo ________________________________________________________________________________ @echo Add selfsigned server certificate %srvcertselfsigned% to client trust store: %cltsrvjkstruststore% @rem Import the server certificate into the client-server trust store (for server self-signed authentication) %keytool% -import -noprompt -alias %srvalias% -file %srvcertselfsigned% -keystore %cltsrvjkstruststore% -storepass %cltsrvjkstruststorepass%
@rem @echo ________________________________________________________________________________ @echo Add selfsigned client certificate %cltcertselfsigned% to server trust store: %srvjkskeystore% @rem Import the client certificate into the server trust store (for client self-signed authentication) @rem Omit this step, unless you are authenticating clients. %keytool% -import -noprompt -alias %cltalias% -file %cltcertselfsigned% -keystore %srvjkskeystore% -storepass %srvjkskeystorepass%
@rem @echo ________________________________________________________________________________ @echo Create a pem client-server trust store from the jks client-server trust store: %cltsrvpemtruststore% @rem %keytool% -importkeystore -noprompt -srckeystore %cltsrvjkstruststore% -destkeystore %cltsrvp12truststore% -srcstoretype jks -deststoretype pkcs12 -srcstorepass %cltsrvjkstruststorepass% -deststorepass %cltsrvp12truststorepass% %openssl%\bin\openssl pkcs12 -in %cltsrvp12truststore% -out %cltsrvpemtruststore% -passin pass:%cltsrvp12truststorepass% -passout pass:%cltsrvpemtruststorepass%@rem @rem @echo ________________________________________________________________________________ @echo Create a pem client key store from the jks client keystore @rem Omit this step, unless you are configuring a C or iOS client. @rem %keytool% -importkeystore -noprompt -srckeystore %cltjkskeystore% -destkeystore %cltp12keystore% -srcstoretype jks -deststoretype pkcs12 -srcstorepass %cltjkskeystorepass% -deststorepass %cltp12keystorepass% %openssl%\bin\openssl pkcs12 -in %cltp12keystore% -out %cltpemkeystore% -passin pass:%cltp12keystorepass% -passout pass:%cltpemkeystorepass%
- cacerts.bat
- 此 Script 會將憑證管理中心主要憑證匯入專用金鑰儲存庫。 需要 CA 主要憑證,才可在主要憑證與已簽章的憑證之間建立金鑰鏈。 cacerts.bat Script 會從其金鑰儲存庫匯出用戶端及伺服器憑證申請。 Script 會使用 cajkskeystore.jks 金鑰儲存庫中專用憑證管理中心的金鑰,來簽署憑證申請,然後將已簽章的憑證匯回提出申請的同一個金鑰儲存庫。 匯入會使用 CA 主要憑證建立憑證鏈。 Script 會從用戶端 JKS 信任儲存庫,以 PEM 的格式建立用戶端信任儲存庫。
@rem @echo ________________________________________________________________________________ @echo Export self-signed certificates: %cacert% @rem @rem Export CA public certificate %keytool% -exportcert -noprompt -rfc -alias %caalias% -keystore %cajkskeystore% -storepass %cajkskeystorepass% -file %cacert%
@rem @echo ________________________________________________________________________________ @echo Add CA to server key and client key and trust stores: %srvjkskeystore%, %cltjkskeystore%, %cltcajkstruststore%, @rem The CA certificate is necessary to create key chains in the client and server key stores, @rem and to certify key chains in the server key store and the client trust store @rem @rem Import the CA root certificate into the server key store %keytool% -import -noprompt -alias %caalias% -file %cacert% -keystore %srvjkskeystore% -storepass %srvjkskeystorepass% @rem Import the CA root certificate into the client key store @rem Omit this step, unless you are authenticating clients. %keytool% -import -noprompt -alias %caalias% -file %cacert% -keystore %cltjkskeystore% -storepass %cltjkskeystorepass% @rem Import the CA root certificate into the client ca-trust store (for ca chained authentication) %keytool% -import -noprompt -alias %caalias% -file %cacert% -keystore %cltcajkstruststore% -storepass %cltcajkstruststorepass%
@rem @echo ________________________________________________________________________________ @echo Create certificate signing requests: %srvcertreq% and %cltcertreq% @rem @rem Create a certificate signing request (CSR) for the server key %keytool% -certreq -alias %srvalias% -file %srvcertreq% -keypass %srvkeypass% -keystore %srvjkskeystore% -storepass %srvjkskeystorepass% @rem Create a certificate signing request (CSR) for the client key %keytool% -certreq -alias %cltalias% -file %cltcertreq% -keypass %cltkeypass% -keystore %cltjkskeystore% -storepass %cltjkskeystorepass%
@rem @echo ________________________________________________________________________________ @echo Sign certificate requests: %srvcertcasigned% and %cltcertcasigned% @rem The requests are signed with the ca key in the cajkskeystore.jks keystore @rem @rem Sign server certificate request %keytool% -gencert -infile %srvcertreq% -outfile %srvcertcasigned% -alias %caalias% -keystore %cajkskeystore% -storepass %cajkskeystorepass% -keypass %cakeypass% @rem Sign client certificate request @rem Omit this step, unless you are authenticating clients. %keytool% -gencert -infile %cltcertreq% -outfile %cltcertcasigned% -alias %caalias% -keystore %cajkskeystore% -storepass %cajkskeystorepass% -keypass %cakeypass%
@rem @echo ________________________________________________________________________________ @echo Import the signed certificates back into the key stores to create the key chain: %srvjkskeystore% and %cltjkskeystore% @rem @rem Import the signed server certificate %keytool% -import -noprompt -alias %srvalias% -file %srvcertcasigned% -keypass %srvkeypass% -keystore %srvjkskeystore% -storepass %srvjkskeystorepass% @rem Import the signed client certificate and key chain back into the client keystore %keytool% -import -noprompt -alias %cltalias% -file %cltcertcasigned% -keypass %cltkeypass% -keystore %cltjkskeystore% -storepass %cltjkskeystorepass% @rem @rem The CA certificate is needed in the server key store, and the client trust store @rem to verify the key chain sent from the client or server @echo Delete the CA certificate from %cltjkskeystore%: it causes a problem in converting keystore to pem @rem Omit this step, unless you are authenticating clients. %keytool% -delete -alias %caalias% -keystore %cltjkskeystore% -storepass %cltjkskeystorepass%
@rem @echo ________________________________________________________________________________ @echo Create a pem client-ca trust store from the jks client-ca trust store: %cltcapemtruststore% @rem Omit this step, unless you are configuring a C or iOS client. @rem %keytool% -importkeystore -noprompt -srckeystore %cltcajkstruststore% -destkeystore %cltcap12truststore% -srcstoretype jks -deststoretype pkcs12 -srcstorepass %cltcajkstruststorepass% -deststorepass %cltcap12truststorepass% %openssl%\bin\openssl pkcs12 -in %cltcap12truststore% -out %cltcapemtruststore% -passin pass:%cltcap12truststorepass% -passout pass:%cltpemtruststorepass%
@rem @echo ________________________________________________________________________________ @echo Create a pem client key store from the jks client keystore @rem Omit this step, unless you are configuring a C or iOS client. @rem %keytool% -importkeystore -noprompt -srckeystore %cltjkskeystore% -destkeystore %cltp12keystore% -srcstoretype jks -deststoretype pkcs12 -srcstorepass %cltjkskeystorepass% -deststorepass %cltp12keystorepass% %openssl%\bin\openssl pkcs12 -in %cltp12keystore% -out %cltpemkeystore% -passin pass:%cltp12keystorepass% -passout pass:%cltpemkeystorepass%
- mqcerts.bat
- Script 會列出憑證目錄中的金鑰儲存庫及憑證。 然後,它會建立 MQTT 範例佇列管理程式,並配置安全遙測通道。
@echo ________________________________________________________________________________ @echo List keystores and certificates dir %certpath%\*.* /b
@rem @echo Create queue manager and define mqtt channels and certificate stores call "%MQ_FILE_PATH%\mqxr\Samples\SampleMQM" >> %mqlog% echo DEFINE CHANNEL(%chlreq%) CHLTYPE(MQTT) TRPTYPE(TCP) PORT(%portsslreq%) SSLCAUTH(%authreq%) SSLKEYR('%srvjkskeystore%') SSLKEYP('%srvjkskeystorepass%') MCAUSER(%mcauser%) | runmqsc %qm% >> %mqlog% echo DEFINE CHANNEL(%chlopt%) CHLTYPE(MQTT) TRPTYPE(TCP) PORT(%portsslopt%) SSLCAUTH(%authopt%) SSLKEYR('%srvjkskeystore%') SSLKEYP('%srvjkskeystorepass%') MCAUSER(%mcauser%) | runmqsc %qm% >> %mqlog% echo DEFINE CHANNEL(%chlsslreqws%) CHLTYPE(MQTT) TRPTYPE(TCP) PORT(%portsslreqws%) SSLCAUTH(%authreq%) SSLKEYR('%srvjkskeystore%') SSLKEYP('%srvjkskeystorepass%') MCAUSER(%mcauser%) PROTOCOL(HTTP) | runmqsc %qm% >> %mqlog% echo DEFINE CHANNEL(%chlssloptws%) CHLTYPE(MQTT) TRPTYPE(TCP) PORT(%portssloptws%) SSLCAUTH(%authopt%) SSLKEYR('%srvjkskeystore%') SSLKEYP('%srvjkskeystorepass%') MCAUSER(%mcauser%) PROTOCOL(HTTP) | runmqsc %qm% >> %mqlog% echo DEFINE CHANNEL(%chlws%) CHLTYPE(MQTT) TRPTYPE(TCP) PORT(%portws%) MCAUSER(%mcauser%) PROTOCOL(HTTP) | runmqsc %qm% >> %mqlog% @echo MQ logs saved in %mqlog%echo