Issue custom certificates

Updated at:

When devices connect to the IoT Platform cloud gateway using the MQTT, GB/T 32960, JT/T 808, or SL 651 protocol over Transport Layer Security (TLS), they must use certificates for authentication. The IoT Platform cloud gateway supports certificates that use the RSA, ECC, and SM2 signature algorithms. You can use the Alibaba Cloud Private Certificate Authority (PCA) service or issue your own Certificate Authority (CA) certificates. This topic uses the RSA and SM2 algorithms as examples to describe how to issue custom CA certificates.

Before you begin

The steps in this topic are performed with regular user permissions. For operations that require administrator permissions, use the sudo command.

Background information

IoT Platform supports mutual authentication for certificates that use the RSA and ECC algorithms. It supports only one-way authentication for SM certificates. For more information about connecting devices to the cloud gateway using the MQTT, GB/T 32960, JT/T 808, and SL 651 protocols, see MQTT cloud gateway overview, GB/T 32960 cloud gateway overview, JT/T 808 cloud gateway overview, and SL 651 protocol overview.

For more information about the Private Certificate Authority (PCA) service, see PCA service description and usage.

Prerequisites

  • To issue a custom certificate that uses the RSA algorithm, you need the OpenSSL tool.

  • To issue an SM certificate that uses the SM2 algorithm, you need the Tongsuo tool.

    Tongsuo supports various Linux distributions, macOS, Android, iOS, and Windows.

This topic uses an Alibaba Cloud Linux ECS instance to demonstrate how to generate custom certificates. The OpenSSL tool is pre-installed on this operating system. For more information about how to purchase an ECS instance, see Create an instance.

Prepare the environment on your operating system. This topic uses Alibaba Cloud Linux as an example.

  1. Log on to the operating system. For more information about how to log on to an ECS instance, see Select a method to connect to an ECS instance.

  2. Run the following command to install the make compiler tool.

    sudo yum install make
  3. Run the following command to install the C library and C compiler.

    sudo yum install gcc
  4. Run the following command to install unzip. You will use `unzip` to decompress the Tongsuo source package.

    Note

    If you do not plan to issue SM2 algorithm certificates, you do not need to install unzip.

    yum update
    yum install zip
  5. Run the following command to install Perl 5 and the Text::Template module. You will use them to install the Tongsuo source library.

    Note

    If you do not plan to issue SM2 algorithm certificates, you do not need to install Perl 5 and the Text::Template module.

    sudo yum install perl
    sudo yum install perl-core

Issue an RSA algorithm certificate

  1. In the operating system of the ECS instance, create a folder to store the generated certificates.

    mkdir /home/rsa_certs
    cd /home/rsa_certs
  2. Run the following command to generate the root-ca.crt root certificate file for the device and server.

    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
  3. Create a server-side certificate based on the root-ca.crt root certificate file.

    1. Run the following command to generate the server.key server-side key file.

      openssl genrsa -out server.key 2048
    2. Run the touch openssl.cnf command to create the openssl.cnf file.

    3. Run the vi openssl.cnf command to open the file. Add the following content, press the Esc key, and then enter :wq to save and close the file.

      [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
    4. Run the following command to generate the server.csr server-side request file.

      openssl req -new -key server.key -config openssl.cnf -out server.csr
    5. Run the following command to generate the server.crt server-side certificate file.

      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
    6. Run the following command to verify the server-side certificate.

      openssl verify -CAfile root-ca.crt server.crt
  4. Create a device-side certificate based on the root-ca.crt root certificate file.

    1. Run the following command to generate the client.key device-side key file.

      openssl genrsa -out client.key 2048
    2. Run the following command to generate the client.csr device-side certificate request file. In this example, CN is set to Client_123.

      openssl req -new -key client.key -out client.csr -subj "/CN=Client_123"
    3. Run the following command to generate the client.crt device-side certificate file.

      openssl x509 -req -days 365 -sha256 -in client.csr -CA root-ca.crt -CAkey root-ca.key -CAcreateserial -out client.crt
    4. Run the following command to verify the device-side certificate.

      openssl verify -CAfile root-ca.crt client.crt
  5. Run the `ls` command to view all the custom certificate files.

    The following certificate files are generated:

    • Root certificate: root-ca.crt.

    • Server-side certificate private key: server.key.

    • Server-side certificate: server.crt.

    • Device-side certificate private key: client.key.

    • Device-side certificate: client.crt.

Issue an SM2 algorithm certificate

Important
  • To issue an SM certificate that uses the SM2 algorithm, you must use Tongsuo. This example uses the `Tongsuo-8.4.0-pre3.zip` source package. The related files are in the `/test/certs/sm2` directory of the source package.

  • After you install Tongsuo, it replaces the original OpenSSL in the operating system.

  • This example builds a three-level SM certificate chain. When you issue a certificate signing request (`csr`) file for each level, the countryName, stateOrProvinceName, organizationName, and organizationalUnitName parameters must be the same. However, the commonName parameter must be unique.

  1. In the operating system of the ECS instance, create a folder to store the SM certificate files.

    mkdir /home/sm2
    cd /home/sm2
  2. Upload and install Tongsuo.

    1. Download the Tongsuo-8.4.0-pre3.zip package.

    2. Upload the local file to the sm2 directory in the operating system.

    3. Run the following command to decompress the package.

      unzip Tongsuo-8.4.0-pre3.zip
    4. Run the following commands to go to the `Tongsuo-8.4.0-pre3` directory and install Tongsuo.

      cd Tongsuo-8.4.0-pre3
      ./config
      make
      make install
    5. Run the `openssl version` command to confirm the installation.

      Note

      If the error message `openssl: error while loading shared libraries: libssl.so.3: cannot open shared object file: No such file or directory` is returned, run the `ldconfig /usr/local/lib64/` command and then run the `openssl version` command again.

      A message similar to the following is returned, which indicates that the installation is successful.

      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)
  3. Create the `gen-sm2-cert-sign-dir.sh` script to build the `sm2-ca` directory for managing the issued certificates.

    1. Run the `touch gen-sm2-cert-sign-dir.sh` command to create the `gen-sm2-cert-sign-dir.sh` script file.

    2. Run the `vi gen-sm2-cert-sign-dir.sh` command to open the file. Add the following content and then enter `:wq` to save and close the file.

      #!/bin/bash
      
      # Create the certs, db, private, crl, csr, and newcerts directories under the sm2-ca directory.
      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
      
      
    3. Run the `chmod +x gen-sm2-cert-sign-dir.sh` command to add execute permissions to the script file.

    4. Run the `./gen-sm2-cert-sign-dir.sh` command to run the script and build the `sm2-ca` directory.

  4. Run the `cd sm2-ca` command to go to the `sm2-ca` directory. Then, create the `openssl.cnf` and `openssl_middleca.cnf` configuration files using the `touch` and `vi` commands as described in the previous steps.

    Note

    To specify domain names, you can set them in the `[ alt_names ]` section of the `openssl.cnf` and `openssl_middleca.cnf` files.

    The file contents are as follows:

    openssl.cnf: Issue root and intermediate certificates

    [ ca ]
    # See the ca man page.
    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. Use SM3 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 sign only intermediate certificates that match.
    # See the POLICY FORMAT section of the ca man page.
    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 (see the req man page).
    default_bits        = 2048
    distinguished_name  = req_distinguished_name
    string_mask         = utf8only
    
    # SHA-1 is deprecated. 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 (see the x509v3_config man page).
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer
    basicConstraints = critical, CA:true
    keyUsage = critical, digitalSignature, cRLSign, keyCertSign
    
    [ v3_intermediate_ca ]
    # Extensions for a typical intermediate CA (see the x509v3_config man page).
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer
    basicConstraints = critical, CA:true, pathlen:0
    keyUsage = critical, digitalSignature, cRLSign, keyCertSign
    [ usr_cert ]
    # Extensions for client certificates (see the x509v3_config man page).
    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 (see the x509v3_config man page).
    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 (see the x509v3_config man page).
    authorityKeyIdentifier=keyid:always
    
    [ ocsp ]
    # Extension for OCSP signing certificates (see the ocsp man page).
    basicConstraints = CA:FALSE
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid,issuer
    keyUsage = critical, digitalSignature
    extendedKeyUsage = critical, OCSPSigning
    
    

    openssl_middleca.cnf: Issue a server-side certificate

    [ ca ]
    # See the ca man page.
    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. Use SM3 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 sign only intermediate certificates that match.
    # See the POLICY FORMAT section of the ca man page.
    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 (see the req man page).
    default_bits        = 2048
    distinguished_name  = req_distinguished_name
    string_mask         = utf8only
    
    # SHA-1 is deprecated. 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 (see the x509v3_config man page).
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer
    basicConstraints = critical, CA:true
    keyUsage = critical, digitalSignature, cRLSign, keyCertSign
    
    [ v3_intermediate_ca ]
    # Extensions for a typical intermediate CA (see the x509v3_config man page).
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer
    basicConstraints = critical, CA:true, pathlen:0
    keyUsage = critical, digitalSignature, cRLSign, keyCertSign
    [ usr_cert ]
    # Extensions for client certificates (see the x509v3_config man page).
    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 (see the x509v3_config man page).
    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 (see the x509v3_config man page).
    authorityKeyIdentifier=keyid:always
    
    [ ocsp ]
    # Extension for OCSP signing certificates (see the ocsp man page).
    basicConstraints = CA:FALSE
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid,issuer
    keyUsage = critical, digitalSignature
    extendedKeyUsage = critical, OCSPSigning
    
    
  5. Run the following commands to generate the `sm2-root.key` root certificate private key and the `sm2-root.crt` certificate.

    Important

    When you run the second command, set the signature parameters as prompted, such as countryName, stateOrProvinceName, organizationName, organizationalUnitName, and commonName. When you later issue the intermediate and server-side certificates, the values for countryName, stateOrProvinceName, organizationName, and organizationalUnitName must be the same as the values that you specify here. The commonName value must be unique.

    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/
  6. Run the following commands to generate the `sm2-intermediate-ca.key` intermediate certificate private key and the `sm2-intermediate-ca.crt` certificate.

    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/
  7. Run the following commands to generate the `sm2-leaf.key` server-side certificate private key and the `sm2-leaf.crt` certificate.

    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/

The certificate files are stored in the `/sm2-ca/certs` directory. The corresponding private key files are stored in the `/sm2-ca/private` directory.

  • Root certificate and private key: `sm2-root.crt`, `sm2-root.key`.

  • Intermediate certificate: `sm2-intermediate-ca.crt`, `sm2-intermediate-ca.key`.

  • Server-side certificate: `sm2-leaf.crt`, `sm2-leaf.key`.

References