設備端使用MQTT、GB/T 32960、JT/T 808或SL 651協議并采用TLS方式接入物聯網平臺云網關時,需要使用證書進行認證。物聯網平臺云網關支持使用的證書簽名算法有RSA、ECC和國密SM2,您可通過阿里云PCA服務或自行簽發需要的CA證書。本文以RSA算法和SM2算法為例,介紹如何簽發自定義CA證書。
使用前必讀
本文操作步驟以普通用戶權限為例。如果您在操作過程中涉及到管理員權限才能執行的操作,可嘗試使用sudo
命令執行。
背景信息
物聯網平臺支持RSA、ECC算法證書雙向認證,僅支持國密證書單向認證。使用云網關MQTT、GB/T 32960和JT/T 808協議接入設備的詳細內容,請參見MQTT協議云網關概述、GB/T 32960協議云網關概述、JT/T 808協議云網關概述和SL 651協議概述。
PCA(Private Certificate Authority,即私有CA)服務的詳細信息,請參見私有證書概述。
準備環境
簽發RSA算法的自定義證書,需要使用工具OpenSSL。
簽發SM2算法的國密證書,需要使用工具Tongsuo。
Tongsuo支持的操作系統有:各種Linux發行版、macOS、Android、iOS和Windows。
本文購買Alibaba Cloud Linux操作系統的ECS實例(默認已安裝OpenSSL工具),通過以下工具生成自定義證書。購買ECS實例的方法,請參見實例創建方式介紹。
您可參考以下步驟,在待使用的操作系統(本文使用Alibaba Cloud Linux)上,準備對應的環境。
登錄操作系統。ECS實例登錄方式,請參見連接方式概述。
執行以下命令,安裝make編譯工具。
sudo yum install make
執行以下命令,安裝C庫和C編譯器。
sudo yum install gcc
執行以下命令,安裝
unzip
,用于后續解壓Tongsuo源碼包。說明如果不簽發SM2算法證書,無需安裝
unzip
。yum update yum install zip
執行以下命令,安裝Perl 5以及Text::Template模塊,用于后續安裝Tongsuo源碼庫。
說明如果不簽發SM2算法證書,無需安裝Perl 5以及Text::Template模塊。
sudo yum install perl sudo yum install perl-core
簽發RSA算法的證書
在ECS實例的操作系統中創建一個文件夾存放生成的證書。
mkdir /home/rsa_certs cd /home/rsa_certs
執行以下命令生成設備端和服務端的根證書文件
root-ca.crt
。openssl req \ -new \ -newkey rsa:2048 \ -days 365 \ -nodes \ -x509 \ -subj "/C=CN/O=Aliyun IOT/CN=IoT CA" \ -keyout root-ca.key \ -out root-ca.crt
根據根證書文件
root-ca.crt
,自定義服務端證書。執行以下命令生成服務端密鑰文件
server.key
。openssl genrsa -out server.key 2048
執行命令
touch openssl.cnf
新建文件openssl.cnf
。執行命令
vi openssl.cnf
進入文件,填入以下內容后按Esc鍵,輸入:wq
保存。[policy_match] countryName = cn stateOrProvinceName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [req] default_bits = 2048 distinguished_name = req_distinguished_name req_extensions = req_ext x509_extensions = v3_req prompt = no [req_distinguished_name] commonName = Server [req_ext] subjectAltName = @alt_names [v3_req] subjectAltName = @alt_names [alt_names] DNS.1 = *.mqtt.iothub.aliyuncs.com DNS.2 = *.igw.iothub.aliyuncs.com
執行以下命令生成服務端請求文件
server.csr
。openssl req -new -key server.key -config openssl.cnf -out server.csr
執行以下命令生成服務端證書文件
server.crt
。openssl x509 -req -days 365 -sha256 -in server.csr -CA root-ca.crt -CAkey root-ca.key -CAcreateserial -out server.crt -extensions v3_req -extfile openssl.cnf
執行以下命令驗證服務端證書。
openssl verify -CAfile root-ca.crt server.crt
根據根證書文件
root-ca.crt
,自定義設備端證書。執行以下命令生成設備端密鑰文件
client.key
。openssl genrsa -out client.key 2048
執行以下命令生成設備端證書請求文件
client.csr
。本示例設置CN為Client_123
。openssl req -new -key client.key -out client.csr -subj "/CN=Client_123"
執行以下命令生成設備端證書文件
client.crt
。openssl x509 -req -days 365 -sha256 -in client.csr -CA root-ca.crt -CAkey root-ca.key -CAcreateserial -out client.crt
執行以下命令驗證設備端證書。
openssl verify -CAfile root-ca.crt client.crt
執行命令
ls
,可查看自定義證書的所有文件。證書文件為:
根證書:
root-ca.crt
。服務端證書私鑰:
server.key
。服務端證書:
server.crt
。設備端證書私鑰:
client.key
。設備端證書:
client.crt
。
簽發SM2算法的證書
簽發SM2算法的國密證書,需要使用Tongsuo。本示例下載源碼包
Tongsuo-8.4.0-pre3.zip
,相關文件位于源碼庫的/test/certs/sm2
目錄中。安裝Tongsuo成功后,Tongsuo會替換操作系統內原有的OpenSSL。
本示例構建一套包含三級證書鏈的國密證書,簽發每級證書簽名請求
csr
文件時,設置的countryName、stateOrProvinceName、organizationName、organizationalUnitName必須保持一致,但commonName必須保持唯一。
在ECS實例的操作系統中創建一個文件夾存放生成國密證書相關的文件。
mkdir /home/sm2 cd /home/sm2
按照以下步驟上傳并安裝Tongsuo。
執行以下命令解壓文件包。
unzip Tongsuo-8.4.0-pre3.zip
執行以下命令,進入文件目錄
Tongsuo-8.4.0-pre3
并完成安裝Tongsuo。cd Tongsuo-8.4.0-pre3 ./config make make install
執行命令
openssl version
確認安裝成功。說明如果報錯:
openssl: error while loading shared libraries: libssl.so.3: cannot open shared object file: No such file or directory
,可執行如下命令:ldconfig /usr/local/lib64/
后,重新執行命令openssl version
。返回類似如下信息,說明安裝成功。
Tongsuo: Tongsuo 8.4.0-pre3 (Library: Tongsuo 8.4.0-pre3) OpenSSL 3.0.3 3 May 2022 (Library: OpenSSL 3.0.3 3 May 2022)
新增路徑構建腳本
gen-sm2-cert-sign-dir.sh
,構建文件目錄sm2-ca
管理簽發的證書。執行命令
touch gen-sm2-cert-sign-dir.sh
,新建腳本文件gen-sm2-cert-sign-dir.sh
。執行命令
vi gen-sm2-cert-sign-dir.sh
進入文件,填入以下內容后輸入:wq
保存。#!/bin/bash # create dir certs db private crl csr newcerts under sm2-ca dir. if [ ! -d sm2-ca/certs ]; then mkdir -p sm2-ca/certs fi if [ ! -d sm2-ca/db ]; then mkdir -p sm2-ca/db touch sm2-ca/db/index openssl rand -hex 16 > sm2-ca/db/serial echo 1001 > sm2-ca/db/crlnumber fi if [ ! -d sm2-ca/private ]; then mkdir -p sm2-ca/private chmod 700 sm2-ca/private fi if [ ! -d sm2-ca/crl ]; then mkdir -p sm2-ca/crl fi if [ ! -d sm2-ca/newcerts ]; then mkdir -p sm2-ca/newcerts fi if [ ! -d sm2-ca/csr ]; then mkdir -p sm2-ca/csr fi
執行命令
chmod +x gen-sm2-cert-sign-dir.sh
為腳本文件添加執行權限。執行命令
./gen-sm2-cert-sign-dir.sh
運行腳本,完成構建文件目錄sm2-ca
。
執行命令
cd sm2-ca
進入文件目錄sm2-ca
,然后參考上一步驟中的touch
和vi
命令,新增配置文件openssl.cnf
、openssl_middleca.cnf
。說明如果需指定域名,可在配置文件
openssl.cnf
和openssl_middleca.cnf
中的[ alt_names ]
下設置。文件內容如下:
openssl.cnf:簽發根證書和中間證書
[ ca ] # `man ca` default_ca = CA_default [ CA_default ] # Directory and file locations. dir = ./ certs = $dir/certs crl_dir = $dir/crl new_certs_dir = $dir/newcerts database = $dir/db/index serial = $dir/db/serial RANDFILE = $dir/private/random # The root key and root certificate. private_key = $dir/private/sm2-root.key certificate = $dir/certs/sm2-root.crt # For certificate revocation lists. crlnumber = $dir/crl/crlnumber crl = $dir/crl/ca.crl.pem crl_extensions = crl_ext default_crl_days = 30 # SHA-1 is deprecated, so use SHA-2 instead. default_md = sm3 name_opt = ca_default cert_opt = ca_default default_days = 365 preserve = no policy = policy_strict [ policy_strict ] # The root CA should only sign intermediate certificates that match. # See the POLICY FORMAT section of `man ca`. countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [ policy_loose ] # Allow the intermediate CA to sign a more diverse range of certificates. # See the POLICY FORMAT section of the `ca` man page. countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] # Options for the `req` tool (`man req`). default_bits = 2048 distinguished_name = req_distinguished_name string_mask = utf8only # SHA-1 is deprecated, so use SHA-2 instead. default_md = sha256 # Extension to add when the -x509 option is used. x509_extensions = v3_ca req_extensions = v3_req [ req_distinguished_name ] # See <https://en.wikipedia.org/wiki/Certificate_signing_request>. countryName = optional stateOrProvinceName = optional localityName = optional 0.organizationName = optional organizationalUnitName = optional commonName = optional emailAddress = optional # Optionally, specify some defaults. countryName_default = CN stateOrProvinceName_default = China localityName_default = 0.organizationName_default = Alipay #organizationalUnitName_default = #emailAddress_default = [ v3_req ] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [ alt_names ] DNS.1 = *.mqtt.iothub.aliyuncs.com DNS.2 = *.igw.iothub.aliyuncs.com [ v3_ca ] # Extensions for a typical CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true keyUsage = critical, digitalSignature, cRLSign, keyCertSign [ v3_intermediate_ca ] # Extensions for a typical intermediate CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true, pathlen:0 keyUsage = critical, digitalSignature, cRLSign, keyCertSign [ usr_cert ] # Extensions for client certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = client, email nsComment = "OpenSSL Generated Client Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, emailProtection [ server_cert ] # Extensions for server certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = server nsComment = "OpenSSL Generated Server Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [ crl_ext ] # Extension for CRLs (`man x509v3_config`). authorityKeyIdentifier=keyid:always [ ocsp ] # Extension for OCSP signing certificates (`man ocsp`). basicConstraints = CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, digitalSignature extendedKeyUsage = critical, OCSPSigning
openssl_middleca.cnf:簽發服務端證書
[ ca ] # `man ca` default_ca = CA_default [ CA_default ] # Directory and file locations. dir = ./ certs = $dir/certs crl_dir = $dir/crl new_certs_dir = $dir/newcerts database = $dir/db/index serial = $dir/db/serial RANDFILE = $dir/private/random # The root key and root certificate. private_key = $dir/private/sm2-intermediate-ca.key certificate = $dir/certs/sm2-intermediate-ca.crt # For certificate revocation lists. crlnumber = $dir/crlnumber crl = $dir/crl/ca.crl.pem crl_extensions = crl_ext default_crl_days = 30 # SHA-1 is deprecated, so use SHA-2 instead. default_md = sm3 name_opt = ca_default cert_opt = ca_default default_days = 365 preserve = no policy = policy_strict [ policy_strict ] # The root CA should only sign intermediate certificates that match. # See the POLICY FORMAT section of `man ca`. countryName = optional stateOrProvinceName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [ policy_loose ] # Allow the intermediate CA to sign a more diverse range of certificates. # See the POLICY FORMAT section of the `ca` man page. countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] # Options for the `req` tool (`man req`). default_bits = 2048 distinguished_name = req_distinguished_name string_mask = utf8only # SHA-1 is deprecated, so use SHA-2 instead. default_md = sha256 # Extension to add when the -x509 option is used. x509_extensions = v3_ca req_extensions = v3_req [ req_distinguished_name ] # See <https://en.wikipedia.org/wiki/Certificate_signing_request>. countryName = optional stateOrProvinceName = optional localityName = optional 0.organizationName = optional organizationalUnitName = optional commonName = optional emailAddress = optional # Optionally, specify some defaults. countryName_default = CN stateOrProvinceName_default = China localityName_default = 0.organizationName_default = Alipay #organizationalUnitName_default = #emailAddress_default = [ v3_req ] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [ alt_names ] DNS.1 = *.mqtt.iothub.aliyuncs.com DNS.2 = *.igw.iothub.aliyuncs.com [ v3_ca ] # Extensions for a typical CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true keyUsage = critical, digitalSignature, cRLSign, keyCertSign [ v3_intermediate_ca ] # Extensions for a typical intermediate CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true, pathlen:0 keyUsage = critical, digitalSignature, cRLSign, keyCertSign [ usr_cert ] # Extensions for client certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = client, email nsComment = "OpenSSL Generated Client Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, emailProtection [ server_cert ] # Extensions for server certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = server nsComment = "OpenSSL Generated Server Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [ crl_ext ] # Extension for CRLs (`man x509v3_config`). authorityKeyIdentifier=keyid:always [ ocsp ] # Extension for OCSP signing certificates (`man ocsp`). basicConstraints = CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, digitalSignature extendedKeyUsage = critical, OCSPSigning
執行以下命令,生成根證書私鑰
sm2-root.key
和證書sm2-root.crt
。重要執行第2行命令時,需根據提示設置簽名參數,例如countryName、stateOrProvinceName、organizationName、organizationalUnitName和commonName等。后續簽發中間證書和服務端證書時,countryName、stateOrProvinceName、organizationName、organizationalUnitName設置必須此處設置保持一致,commonName設置必須保持唯一。
openssl ecparam -genkey -name SM2 -out sm2-root.key openssl req -new -key sm2-root.key -out sm2-root.csr -sm3 -sigopt "sm2_id:1234567812345678" mv sm2-root.key private/ && mv sm2-root.csr csr/ openssl ca -selfsign -config openssl.cnf -in csr/sm2-root.csr -extensions v3_ca -days 3650 -out sm2-root.crt mv sm2-root.crt certs/
執行以下命令,生成中間證書私鑰
sm2-intermediate-ca.key
和證書sm2-intermediate-ca.crt
。openssl ecparam -genkey -name SM2 -out sm2-intermediate-ca.key openssl req -new -key sm2-intermediate-ca.key -out sm2-intermediate-ca.csr -sm3 -sigopt "sm2_id:1234567812345678" mv sm2-intermediate-ca.key private/ && mv sm2-intermediate-ca.csr csr/ openssl ca -config openssl.cnf -extensions v3_intermediate_ca -days 3650 -in csr/sm2-intermediate-ca.csr -out sm2-intermediate-ca.crt -sigopt "sm2_id:1234567812345678" -sm2-id "1234567812345678" -md sm3 mv sm2-intermediate-ca.crt certs/
執行以下命令,生成服務端證書私鑰
sm2-leaf.key
和證書sm2-leaf.crt
。openssl ecparam -genkey -name SM2 -out sm2-leaf.key openssl req -new -key sm2-leaf.key -out sm2-leaf.csr -sm3 -sigopt "sm2_id:1234567812345678" mv sm2-leaf.key private/ && mv sm2-leaf.csr csr/ openssl ca -config openssl_middleca.cnf -extensions server_cert -days 3650 -in csr/sm2-leaf.csr -out sm2-leaf.crt -sigopt "sm2_id:1234567812345678" -sm2-id "1234567812345678" -md sm3 mv sm2-leaf.crt certs/
證書文件最終存放在/sm2-ca/certs
目錄下,對應私鑰文件存放在/sm2-ca/private
目錄下。
根證書和私鑰:
sm2-root.crt
、sm2-root.key
。中間證書:
sm2-intermediate-ca.crt
、sm2-intermediate-ca.key
。服務端證書:
sm2-leaf.crt
、sm2-leaf.key
。