Develop Note

Azure IoT X.509 인증을 위한 인증서 생성 본문

개발 (Ko)

Azure IoT X.509 인증을 위한 인증서 생성

Chalsu 2022. 12. 16. 16:56

Azure IoT를 위한 X.509 인증서를 다시 생성하면서, 과정을 정리해 둔다.

환경

Windows의 WSL2 환경에서 OpenSSL을 사용하였다.

생성 및 사용할 인증서는 다음과 같다.

  • Root CA
  • Sub CA (IoT Hub에 등록할 인증서)
    • Verify certificate
  • Device certificate

과정은 Azure 공식 가이드에 설명되어 있는 부분을 따른 것이다.

 

Root CA

$ vi rootca.conf

디렉터리 구조 생성

  • certs: 새 인증서 저장
  • db: 인증서 데이터베이스에 사용
  • private: CA 프라이빗 키 저장
~$ mkdir rootca
~$ cd rootca/
~/rootca$ mkdir certs db private

~/rootca$ touch db/index
~/rootca$ openssl rand -hex 16 > db/serial
~/rootca$ echo 1001 > db/crlnumber

Root CA config file 생성

**# rootca.conf 파일 작성 - 인증서 이름 변경 (commonName)**
~/rootca$ vi 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               = "Pico Device 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

Root CA 생성

~/rootca$ openssl req -new -config rootca.conf -out rootca.csr -keyout private/rootca.key
~/rootca$ openssl ca -selfsign -config rootca.conf -in rootca.csr -out rootca.crt -extensions ca_ext

Subordinate CA (Optional)

subordinate CA는 필수는 아니지만 인증서 계층 구조를 만들고 사용하기 위해 생성했다.

하위 CA가 있으면 루트 CA가 오프라인으로 유지되고 하위 CA에서 클라이언트 인증서를 발급하는 실제 인증서 계층 구조를 모방합니다.

디렉터리 구조 생성

~/rootca$ cd ..
~$ ls
~$ mkdir subca
~$ cd subca/
~/subca$ mkdir certs db private
~/subca$ touch db/index
~/subca$ openssl rand -hex 16 > db/serial
~/subca$ echo 1001 > db/crlnumber

Sub CA config file 생성

**# 인증서 이름 변경 (commonName 값 수정)**
~/subca$ vi subca.conf

[default]
name                     = subca
domain_suffix            = https://inmile.tistory.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               = "Pico Device 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

Sub CA 생성

~/subca$ openssl req -new -config subca.conf -out subca.csr -keyout private/subca.key
~/subca$ openssl ca -config ../rootca/rootca.conf -in subca.csr -out subca.crt -extensions sub_ca_ext

인증서 변환 (crt → pem)

커맨드를 사용하여 인증서 형태를 변환할 수 있다.

 

openssl x509 -in subca.crt -out subca.pem -outform PEM

 

IoT Hub에 인증서 등록 및 Verification

Azure Portal → IoT Hub → Certificate 메뉴 진입 + Add 버튼 클릭

 

 

앞서 생성한 subca.pem 파일을 IoT Hub에 등록한다.

Generate verification code 버튼을 클릭해 확인 코드를 생성하고 복사한다.

openssl을 사용하여 verify 인증서를 생성한다. 이 때 생성된 확인 코드를 Common Name 값으로 입력한다.

~/subca$ openssl genpkey -out verify.key -algorithm RSA -pkeyopt rsa_keygen_bits:2048
~/subca$ openssl req -new -key verify.key -out verify.csr

**** Common Name에 확인 코드 붙여넣기**

~/subca$ openssl ca -config subca.conf -in verify.csr -out verify.crt -extensions client_ext

인증서를 PEM 형태로 변환

openssl x509 -in verify.crt -out verify.pem -outform PEM

 

Portal 창에서 Verify 버튼을 클릭하여 나타나는 파일 선택 팝업 창에서 앞서 생성한 verfiy 인증서(.pem)를 선택한다.

 

IoT Hub 디바이스 생성

Azure Portal에서 IoT Hub로 이동하여 새 IoT 디바이스를 생성한다.

이 때, Device ID는 인증서의 Common Name과 일치하는 이름을 주어야 한다.

유형은 X.509 CA Signed를 선택한다.

Device cert

  • 디바이스 인증서를 생성한다.
  • Common Name은 IoT Hub Device ID와 동일하게 입력
$ cd subca

# 키 생성
$ openssl genpkey -out picoDevice.key -algorithm RSA -pkeyopt rsa_keygen_bits:2048

# 키에 대한 CSR(인증서 서명 요청) 생성 ==> 디바이스 ID 입력
$ openssl req -new -key picoDevice.key -out picoDevice.csr

--> Common Name (e.g. server FQDN or YOUR name) []: picoDevice

# CSR 확인 (certificate signing request)
$ openssl req -text -in picoDevice.csr -noout

# 인증서 계층 구조에 서명: CSR을 Sub CA에 보냄
$ openssl ca -config subca.conf -in picoDevice.csr -out picoDevice.crt -extensions client_ext

인증서를 PEM 형식으로 변환

openssl x509 -in picoDevice.crt -out picoDevice.pem -outform PEM

 

Comments