教程:使用 OpenSSL 创建测试证书

对于生产环境,建议从公共根证书颁发机构 (CA) 购买 X.509 CA 证书。 但是,自行创建测试证书层次结构足以测试 IoT 中心设备身份验证。 有关如何从公共根 CA 获取 X.509 CA 证书的详细信息,请参阅使用 X.509 CA 证书验证设备身份获取 X.509 CA 证书部分。

以下示例使用 OpenSSLOpenSSL 指南创建证书颁发机构 (CA)、从属 CA 和设备证书。 然后,该示例将从属 CA 和设备证书签名到证书层次结构中。 此示例仅用于演示目的。

注意

Microsoft 提供了 PowerShell 和 Bash 脚本来帮助你了解如何创建你自己的 x.509 证书,并将在 IoT 中心进行身份验证。 这些脚本包含在适用于 C 的 Azure IoT 中心设备 SDK 中。这些脚本仅用于演示目的。 所创建的证书不得用于生产。 证书包含硬编码密码(“1234”)并在 30 天后过期。 必须使用自己的最佳做法在生产环境中创建证书并管理生存期。 有关详细信息,请参阅适用于 C 的 Azure IoT 中心设备 SDK 的 GitHub 存储库中的管理测试 CA 证书示例和教程

步骤 1 - 创建根 CA 目录结构

为证书颁发机构创建目录结构。

  • certs 目录用于存储新证书。
  • db 目录存储证书数据库。
  • 专用目录用于存储 CA 私钥。
  mkdir rootca
  cd rootca
  mkdir certs db private
  touch db/index
  openssl rand -hex 16 > db/serial
  echo 1001 > db/crlnumber

步骤 2 - 创建根 CA 配置文件

创建 CA 之前,请先创建一个配置文件,并在 rootca 目录中将其另存为 rootca.conf。

[default]
name                     = rootca
domain_suffix            = example.com
aia_url                  = http://$name.$domain_suffix/$name.crt
crl_url                  = http://$name.$domain_suffix/$name.crl
default_ca               = ca_default
name_opt                 = utf8,esc_ctrl,multiline,lname,align

[ca_dn]
commonName               = "Test Root CA"

[ca_default]
home                     = ../rootca
database                 = $home/db/index
serial                   = $home/db/serial
crlnumber                = $home/db/crlnumber
certificate              = $home/$name.crt
private_key              = $home/private/$name.key
RANDFILE                 = $home/private/random
new_certs_dir            = $home/certs
unique_subject           = no
copy_extensions          = none
default_days             = 3650
default_crl_days         = 365
default_md               = sha256
policy                   = policy_c_o_match

[policy_c_o_match]
countryName              = optional
stateOrProvinceName      = optional
organizationName         = optional
organizationalUnitName   = optional
commonName               = supplied
emailAddress             = optional

[req]
default_bits             = 2048
encrypt_key              = yes
default_md               = sha256
utf8                     = yes
string_mask              = utf8only
prompt                   = no
distinguished_name       = ca_dn
req_extensions           = ca_ext

[ca_ext]
basicConstraints         = critical,CA:true
keyUsage                 = critical,keyCertSign,cRLSign
subjectKeyIdentifier     = hash

[sub_ca_ext]
authorityKeyIdentifier   = keyid:always
basicConstraints         = critical,CA:true,pathlen:0
extendedKeyUsage         = clientAuth,serverAuth
keyUsage                 = critical,keyCertSign,cRLSign
subjectKeyIdentifier     = hash

[client_ext]
authorityKeyIdentifier   = keyid:always
basicConstraints         = critical,CA:false
extendedKeyUsage         = clientAuth
keyUsage                 = critical,digitalSignature
subjectKeyIdentifier     = hash

步骤 3 - 创建根 CA

首先,在 rootca 目录中生成私钥和证书签名请求 (CSR)。

  openssl req -new -config rootca.conf -out rootca.csr -keyout private/rootca.key

接下来,创建自签名 CA 证书。 自签名适用于测试目的。 在命令行上指定 ca_ext 配置文件扩展名。 这些扩展名表示证书适用于根 CA,可用于签署证书和证书吊销列表 (CRL)。 签署证书,并将其提交至数据库。

  openssl ca -selfsign -config rootca.conf -in rootca.csr -out rootca.crt -extensions ca_ext

步骤 4 - 创建从属 CA 目录结构

为从属 CA 创建一个与 rootca 目录同级的目录结构。

  mkdir subca
  cd subca
  mkdir certs db private
  touch db/index
  openssl rand -hex 16 > db/serial
  echo 1001 > db/crlnumber

步骤 5 - 创建从属 CA 配置文件

创建配置文件并在 subca 目录中将其另存为 subca.conf。

[default]
name                     = subca
domain_suffix            = example.com
aia_url                  = http://$name.$domain_suffix/$name.crt
crl_url                  = http://$name.$domain_suffix/$name.crl
default_ca               = ca_default
name_opt                 = utf8,esc_ctrl,multiline,lname,align

[ca_dn]
commonName               = "Test Subordinate CA"

[ca_default]
home                     = .
database                 = $home/db/index
serial                   = $home/db/serial
crlnumber                = $home/db/crlnumber
certificate              = $home/$name.crt
private_key              = $home/private/$name.key
RANDFILE                 = $home/private/random
new_certs_dir            = $home/certs
unique_subject           = no
copy_extensions          = copy
default_days             = 365
default_crl_days         = 90
default_md               = sha256
policy                   = policy_c_o_match

[policy_c_o_match]
countryName              = optional
stateOrProvinceName      = optional
organizationName         = optional
organizationalUnitName   = optional
commonName               = supplied
emailAddress             = optional

[req]
default_bits             = 2048
encrypt_key              = yes
default_md               = sha256
utf8                     = yes
string_mask              = utf8only
prompt                   = no
distinguished_name       = ca_dn
req_extensions           = ca_ext

[ca_ext]
basicConstraints         = critical,CA:true
keyUsage                 = critical,keyCertSign,cRLSign
subjectKeyIdentifier     = hash

[sub_ca_ext]
authorityKeyIdentifier   = keyid:always
basicConstraints         = critical,CA:true,pathlen:0
extendedKeyUsage         = clientAuth,serverAuth
keyUsage                 = critical,keyCertSign,cRLSign
subjectKeyIdentifier     = hash

[client_ext]
authorityKeyIdentifier   = keyid:always
basicConstraints         = critical,CA:false
extendedKeyUsage         = clientAuth
keyUsage                 = critical,digitalSignature
subjectKeyIdentifier     = hash

步骤 6 - 创建从属 CA

此示例演示如何创建从属 CA 或注册 CA。 由于可以使用根 CA 签署证书,因此不一定要创建从属 CA。 但是,拥有从属 CA 确实可以模拟真实的证书层次结构,在该层次结构中,根 CA 处于脱机状态,从属 CA 为客户端颁发证书。

在 subca 目录中,使用配置文件生成私钥和证书签名请求 (CSR)。

  openssl req -new -config subca.conf -out subca.csr -keyout private/subca.key

将 CSR 提交到根 CA,使用根 CA 颁发并签署从属 CA 证书。 在命令行上为扩展开关指定 sub_ca_ext。 这些扩展表明,此证书适用于可签署证书和证书吊销列表 (CRL) 的 CA。 出现提示时,请签署证书,并将其提交到数据库。

  openssl ca -config ../rootca/rootca.conf -in subca.csr -out subca.crt -extensions sub_ca_ext

步骤 7 - 展示所有权证明

现在,你同时拥有根 CA 证书和从属 CA 证书。 你可以使用其中任何一个来签署设备证书。 必须将你选择的证书上传到 IoT 中心。 以下步骤假定你使用的是从属 CA 证书。 若要将从属 CA 证书上传至 IoT 中心并进行注册,请执行以下操作:

  1. 在 Azure 门户中,导航到 IoT 中心,选择“设置”>“证书”。

  2. 选择“添加”,以添加新的从属 CA 证书。

  3. 在“证书名称”字段中输入显示名称,并选择之前创建的 PEM 证书文件。

    注意

    上面创建的 .crt 证书与 .pem 证书相同。 只需在为证明所有权而上传证书时更改扩展,或使用以下 OpenSSL 命令:

    openssl x509 -in mycert.crt -out mycert.pem -outform PEM
    
  4. 选择“保存”。 此时证书显示在证书列表中,状态为“未验证”。 此验证过程将证明你已拥有证书。

  5. 选择证书以查看“证书详细信息”对话框。

  6. 选择“生成验证码”。 有关详细信息,请参阅证明对 CA 证书的所有权

  7. 将验证码复制到剪贴板。 必须将验证码设置为证书使用者。 例如,如果验证码为 BB0C656E69AF75E3FB3C8D922C1760C58C1DA5B05AAA9D0A,请将其添加为证书使用者,如步骤 9 所示。

  8. 生成私钥。

    openssl genpkey -out pop.key -algorithm RSA -pkeyopt rsa_keygen_bits:2048
    
  9. 从私钥中生成证书签名请求 (CSR)。 添加验证码作为证书使用者。

    openssl req -new -key pop.key -out pop.csr
    
      -----
      Country Name (2 letter code) [XX]:.
      State or Province Name (full name) []:.
      Locality Name (eg, city) [Default City]:.
      Organization Name (eg, company) [Default Company Ltd]:.
      Organizational Unit Name (eg, section) []:.
      Common Name (eg, your name or your server hostname) []:BB0C656E69AF75E3FB3C8D922C1760C58C1DA5B05AAA9D0A
      Email Address []:
    
      Please enter the following 'extra' attributes
      to be sent with your certificate request
      A challenge password []:
      An optional company name []:
    
    
  10. 使用从属 CA 配置文件和所有权证明证书的 CSR 创建证书。

    openssl ca -config subca.conf -in pop.csr -out pop.crt -extensions client_ext
    
  11. 在“证书详细信息”视图中选择新证书。 若要查找 PEM 文件,请导航到“certs”文件夹。

  12. 上传证书后,选择“验证”。 CA 证书状态应更改为“已验证”。

步骤 8 - 在 IoT 中心创建设备

在 Azure 门户中,导航到 IoT 中心,并使用以下值创建新 IoT 设备标识:

  1. 提供与设备证书的使用者名称匹配的设备 ID。

  2. 选择“X.509 CA 签名”身份验证类型。

  3. 选择“保存”。

步骤 9 - 创建客户端设备证书

若要生成客户端证书,必须首先生成私钥。 以下命令演示如何使用 OpenSSL 创建私钥。 在 subca 目录中创建密钥。

openssl genpkey -out device.key -algorithm RSA -pkeyopt rsa_keygen_bits:2048

为密钥创建证书签名请求 (CSR)。 无需输入质询密码或可选公司名称。 但是,必须在“公用名”字段中输入设备 ID。 还可以为其他参数(例如“国家/地区名称”、“组织名称”等)输入自定义值。

openssl req -new -key device.key -out device.csr

-----
Country Name (2 letter code) [XX]:.
State or Province Name (full name) []:.
Locality Name (eg, city) [Default City]:.
Organization Name (eg, company) [Default Company Ltd]:.
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server hostname) []:`<your device ID>`
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

检查 CSR 是否符合预期。

openssl req -text -in device.csr -noout

将 CSR 发送到从属 CA,以登录到证书层次结构。 在 -extensions 开关中指定 client_ext。 请注意,已颁发证书中的 Basic Constraints 表示此证书不适用于 CA。 若要签署多个证书,请确保在使用 openssl rand -hex 16 > db/serial 命令生成每个证书之前更新序列号。

openssl ca -config subca.conf -in device.csr -out device.crt -extensions client_ext

后续步骤

转到教程:测试证书身份验证,以确定证书是否可在 IoT 中心用于对设备进行身份验证。 该页上的代码要求使用 PFX 证书。 使用以下 OpenSSL 命令将设备 .crt 证书转换为 .pfx 格式。

openssl pkcs12 -export -in device.crt -inkey device.key -out device.pfx