KMS_YubiHSM 설정 | Cosmos Hub

Cosmos Testnet에서 tmkms+YubiHSM을 사용해 서명하기

J_Node A-Team
Node A-Team
15 min readAug 28, 2019

--

For English Version

1. KMS(Key Management System)란 무엇인가?

KMS는 간단하게 설명하면 이름 그대로 키를 관리하는 기능을 제공하는 서비스이다. Tendermint 기반인 Cosmos Hub에서는 Tendermint KMS(tmkms)로 사용할 수 있다.

2. Tendermint KMS(tmkms)란 무엇인가?

Tendermint를 사용하는 어플리케이션(Cosmos Hub, Terra, IRISnet 등)에서 활용할 수 있는 Rust 언어 기반으로 작성된 KMS이다. 현재 글을 작성하는 시점에서는 beta 버전이며 최신 버전은 v0.6.3이다. “Apache License, Version 2.0”를 따르는 오픈소스SW이기 때문에 자유롭게 사용이 가능하다.

Tendermint KMS를 사용하면 아래와 같은 이점을 얻을 수 있다.

  • 검증인 서명 키에 대한 고가용성(HA)
  • 이중서명 방지(Double Sign Protection)
  • HSM(Hardware Security Module) 사용

Tendermint KMS에 대한 자세한 내용은 Github 페이지로 확인할 수 있다.

출처: https://medium.com/irisnet-blog/key-management-choices-for-cosmos-validators-29b910af23c0

3. HSM(Hardware Security Module)

HSM은 암호화, 복호화, 서명, 검증 등의 작업을 제공하며 디지털 키를 보호하고 관리하는 물리적 장치 또는 클라우드 서비스이다. Tendermint를 사용하는 어플리케이션에서 검증인의 개인키(priv_validator_key.json)를 안전하게 보관하는데 활용할 수 있다.

현재 Tendermint KMS에서는 아래의 HSM을 지원한다

이제 Tendermint KMS와 YubiHSM2를 활용하여 Cosmos Testnet(gaia-13005)에 서명해보자

Test 환경은 아래와 같다:

  • Node Server: AWS EC2, ubuntu 18.04
  • KMS Server: 물리 서버(Dell), ubuntu 18.04
  • KMS: tmkms v0.6.3
  • HSM: YubiHSM2
  • Tendermint: v0.32.2
  • Gaiad/Gaiacli: v1.0.0
  • Cosmos Testnet: gaia-13005

Cosmos Testnet의 Node 설정 및 블록 싱크는 이미 맞춰진 것을 전제로 진행하며 Test 순서로 진행한다:

Test#1. Cosmos Testnet Node Setting(생략)

Test#2. YubiHSM2 초기화

Test#3. KMS Server 에 신규 사용자 생성

Test#4. KMS Server에 libusb, rust, pkg-config, tmkms 설치

Test#5. KMS Server에 tmkms 설정 파일(tmkms.toml) 생성

Test#6. YubiHSM2에 검증인 개인키(priv_validator_key.json) 추가

Test#7. tmkms 실행

Test#8. Cosmos Node에서 config 수정(config.toml)

Test#9. Cosmos Node 재실행

Test#10. 서명 확인

Test#11. KMS Server에 tmkms.service 등록하기

Test#1. Cosmos Testnet Node Setting(생략)

현재 gaia-13005에서 “ATEAM” 검증인 노드가 잘 돌고 있다.

Cosmos Testnet Explorer: https://gaia-13k5.bigdipper.live

Test#2. YubiHSM2 초기화

YubiHSM2 장비를 뺐다 끼면서 끝부분을 3초 이상 누르면 초기화 되며 초기화 될 때 깜빡이는 LED의 패턴이 바뀐다.(같은 YubiHSM2 장비이지만 LED 패턴이 눈에 띄게 바뀌는 경우와 눈에 띄지 않게 바뀌는 경우가 있다)

※ Windows PC에서도 같은 방법으로 진행 가능하며 장치관리자(devmgmt.msc)를 통해 확인하면 초기화 될 때 YubiHSM 관련 장치가 사라졌다 다시 나타난다.

Test#3. KMS Server 에 신규 사용자 생성

신규 사용자 생성 후 사용자가 YubiHSM2에 접근할 수 있도록 udev에 설정을 추가한다.

udev는 리눅스 커널용 장치 관리자로 /dev의 장치를 관리하며 장치를 추가하고 제거할 때 모든 사용자 공간 처리 동작을 관리한다.(출처: https://wiki.gentoo.org/wiki/Udev/ko)

root가 아닌 계정으로 udev에 설정을 추가하지 않고 YubiHSM2에 접근 시 다음과 같은 error 발생했다.

error: error connecting to YubiHSM2: protocol error: USB error: USB(bus=1,addr=22): error opening device: Access denied (insuffiient permissions))

udev 적용 후 아래의 명령어를 사용하면 바로 적용이 된다고 했는데, 명령어 사용 후에도 적용이 안 됐기 때문에 서버 재실행 진행한다.

# udevadm control — reload-rules && udevadm trigger

// root 계정으로 진행
# mkdir /data_tmkms
# useradd -m -d /data_tmkms/tmkms -G sudo tmkms -s /bin/bash
// udev에 규칙 추가
# vi /etc/udev/rules.d/10-yubihsm.rules
...
SUBSYSTEMS=="usb", ATTRS{product}=="YubiHSM", GROUP=="tmkms"
...
// 서버 재실행
# reboot

Test#4. KMS Server에 libusb, rust, pkg-config, tmkms 설치

// tmkms 계정으로 진행// libusb 설치
$ sudo apt install libusb-1.0-0-dev
// rust 설치
// 메뉴 선택 시 "1) Proceed with installation(default) 선택"
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ source $HOME/.cargo/env
$ cargo --version
// pkg-config 설치
$ sudo apt install pkg-config -y
// tmkms(v0.6.3) 설치
$ cd $HOME
$ git clone https://github.com/tendermint/kms.git
$ cd $HOME/kms
$ cargo install tmkms --features=yubihsm --version=0.6.3
$ tmkms version

Test#5. KMS Server에 tmkms 설정 파일(tmkms.toml) 생성

tmkms.toml 예시: https://github.com/tendermint/kms/blob/master/tmkms.toml.example

[[validator]]의 “addr” 부분에 검증인 정보를 입력하며 Port는 임의로 설정 가능하되 검증인의 config.toml에 설정한 “ priv_validator_laddr”에 설정한 Port와 같아야 한다

검증인 정보는[Test#8. Cosmos Node에서 config 수정(config.toml)] 참고

$ mkdir $HOME/kms/cosmos
$ cd $HOME/kms/cosmos
$ vi tmkms.toml
...
[[chain]]
id = "gaia-13005"
key_format = { type = "bech32", account_key_prefix = "cosmospub", consensus_key_prefix = "cosmosvalconspub" }
state_file = "/data_tmkms/tmkms/kms/cosmos/cosmoshub_priv_validator_state.json"
# state_hook = { cmd = ["/path/to/block/height_script", "--example-arg", "cosmoshub"] }
## Validator configuration
[[validator]]
addr = "tcp://49.247.215.16:46658"
# or addr = "unix:///path/to/socket"
chain_id = "gaia-13005"
reconnect = true # true is the default
secret_key = "/data_tmkms/tmkms/kms/cosmos/secret_connection.key"
## Signing provider configuration
# enable the `yubihsm` feature to use this backend
[[providers.yubihsm]]
adapter = { type = "usb" }
#auth = { key = 1, password_file = "/path/to/password" } # or pass raw password as `password`
auth = { key = 1, password = "password" }
keys = [{ chain_ids = ["gaia-13005"], key = 1 }]
...

Test#6. YubiHSM2에 검증인 개인키(priv_validator_key.json) 추가

검증인 노드에서 개인키(priv_validator_key.json) 가져온 후 YubiHSM2에 추가

$ cd $HOME/cosmos// 검증인 노드에서 개인키 가져오기
$ scp cosmos@49.247.215.16:/data_cosmos/cosmos/.gaiad/config/priv_validator_key.json ./
// YubiHSM2에 추가하기
$ tmkms yubihsm keys import -t json -i 1 priv_validator_key.json
// YubiHSM2에 추가된 Key 확인
// 결과에서 나오는 주소는 Cosmos Node에서 "gaiad tendermint show-validator" 명령어를 통해 확인할 수 있는 주소와 같다(Consensus public address)
& tmkms yubihsm keys list

“tmkms yubihsm keys import -t json -i 1 priv_validator_key.json” 설명

-t 옵션: Key type 설정(우리는 json 파일을 추가할 계획이기 때문에 “json”으로 설정)

-i 옵션: Key ID(tmkms.toml 설정의 [[providers.yubihsm]] 부분에서 설정한 Key ID 설정)

Test#7. tmkms 실행

tmkms를 실행하면 검증인 노드에서 아직 준비가 되지 않았기 때문에 error를 발생한다.

$ tmkms start -c $HOME/kms/cosmos/tmkms.toml

-c 옵션: config 파일(tmkms.toml)을 지정해서 실행

Test#8. Cosmos Node에서 config 수정(config.toml)

gaiad의 config.toml에서 “priv_validator_key_file” 관련 내용 주석 처리 후 “priv_validator_laddr”에 검증인 노드의 내부 IP 및 Port 입력(default: 26658)

$ vi $HOME/.gaiad/config/config.toml
...
#priv_validator_key_file = "config/priv_validator_key.json"
priv_validator_laddr = "tcp://10.4.0.4:46658"
...

priv_validator_laddr에 검증인 노드의 공인 IP, localhost, 127.0.0.1을 설정한 경우 Error가 발생했으며(ERROR: error with private validator socket client: failed to start private validator: accept tcp 127.0.0.1:46658: i/o timeout) 검증인 노드의 사설 IP를 입력했을 때 정상적으로 실행되었다.

Test#9. Cosmos Node 재실행

Test#8에서 변경한 config.toml을 적용하기 위해 gaiad를 재실행 한다.

// service로 등록한 경우
sudo systemctl restart gaiad.service

Test#10. 서명 확인

Cosmos 검증인 노드와 tmkms가 정상적으로 연결이 되면 tmkms 쪽에 PreVote 및 PreCommit 정보가 나타난다.

Test#11. KMS Server에 tmkms.service 등록하기

$ sudo vi /etc/systemd/system/tmkms.service
...
[Unit]
Description=Cosmos tmkms
After=network.target
[Service]
User=tmkms
WorkingDirectory=/data_tmkms/tmkms/.cargo/bin
ExecStart=/data_tmkms/tmkms/.cargo/bin/tmkms start -c /data_tmkms/tmkms/kms/cosmos/tmkms.toml
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=tmkms
RestartSec=3
LimitNOFILE=4096
[Install]
WantedBy=multi-user.target
...
$ sudo systemctl enable tmkms.service
$ sudo systemctl start tmkms.service

log는 /var/log/syslog에 기록되며 log를 실시간으로 확인 방법은 아래와 같다.

sudo tail -f /var/log/syslog

※ ETC

Test에서는 tmkms와 검증인 노드를 연결할 때 검증인 노드의 공인 IP를 사용하였지만 실제 구축 시에는 내부망으로 연결 후 사설 IP로 연결하는 것을 권장드립니다 :)

※ 참고 자료

Node A-Team (노드명: ATEAM)은 Cosmos, IRISnet, Terra를 포함한 Cosmos-SDK, 텐더민트 기반 블록체인의 검증인입니다. Node A-Team은 풍부한 경험을 바탕으로 코스모스 생태계에 기여하고 최고의 보안으로 노드를 운영하고 있습니다.

#ATEAM History

Cosmos: “Game of Stakes” — Never Jailed

IRISnet: “FUXI Betanet”, “Nyancat Testnet” — Reward Winner

Terra-project: “Genesis Drill” — Top Tier

#ATEAM Info

검증인 주소: cosmosvaloper14l0fp639yudfl46zauvv8rkzjgd4u0zk2aseys

Webpage: https://nodeateam.com/

Twitter: https://twitter.com/Node_Ateam

E-mail: contact@nodeateam.com

--

--

J_Node A-Team
Node A-Team

Validator[Cosmos, Terra, BandProtocol, Kava, IRISnet, Matic, E-money, Certik, Starname, Solana, Orbit]_https://nodeateam.com/