LYnLab 로고

블로그취미로그

게시물의 썸네일 이미지

GPG와 YubiKey 함께 사용하기

여러 PC에서 GPG를 사용하는 경우 각 PC마다 비밀 키를 저장해야하는 번거로움이 있습니다. 이 글에서는 YubiKey에 비밀 키를 보관하는 방법에 대해 알아보겠습니다.

2022-08-07#GPG#프로그래밍#보안

💡 이 글은 작성된지 1년 이상 지났습니다. 정보글의 경우 최신 내용이 아닐 수 있음에 유의해주세요.

이전에 GPG 키를 이용해 Git 커밋에 서명하는 방법에 대해 작성한 적이 있습니다. 다만 저처럼 여러 PC를 옮겨가며 작업하는 경우 각 PC마다 서명을 위한 비밀 키를 보관해야하는 번거로움이 있습니다.

이번 글에서는 YubiKey에 GPG 비밀 키를 보관하는 방법에 대해 알아보겠습니다.

동작 원리

YubiKey와 GPG를 함께 사용하는 것은 과정이 복잡해 직관적으로 와닿지 않을 수 있습니다. 따라서 이론적인 내용을 간단히 짚고 넘어갑시다. 이론에 관심없는 분들은 "서명 키 만들기" 문단으로 넘어가주세요.

이 글에서는 gpg의 keytocard 명령어를 사용하여 키를 옮깁니다. Git 서명을 위한 키를 옮기는 것이 목적이므로 비밀 키를 YubiKey에 옮길 것입니다.

GPG 키를 YubiKey로 옮기는 과정

위 그림은 이 글에서 작업할 내용을 간단히 나타낸 것입니다.

키를 옮기고 나면 호스트 PC의 공개 키에는 비밀 키가 옮겨간 카드 번호(=YubiKey의 시리얼 번호)가 저장됩니다. 이후 이 비밀 키를 찾기 위해서는 카드 번호가 저장되어있는 공개 키가 필요합니다. 즉, 다른 PC에서 YubiKey 안의 비밀 키를 이용하기 위해서는 단순히 YubiKey를 꽂기만해서는 안되며, PC에 카드 번호가 저장되어있는 공개 키가 존재해야합니다.

또한 주의해야 할 점은, YubiKey로 옮긴 비밀 키는 다시는 YubiKey 밖으로 꺼내올 수 없습니다! 하나 뿐인 비밀 키가 담겨있는 YubiKey를 잃어버리면 곤란해지기 때문에 이 글에서는 서명에 사용할 보조키(subkey)를 만들어 해당 보조키를 옮길 것입니다.

마지막으로, 이 내용은 YubiKey의 PGP 기능을 이용하는 것이며 OTP 혹은 FIDO 인증 기능과는 무관합니다. 따라서 일반적인 사용 방법과는 달리 YubiKey의 골드 디스크(노란색 버튼)를 누르지 않습니다. 이건 크게 중요하지 않지만 제가 "왜 유비키를 쓰는데 골드 디스크를 누르지 않지?" 하고 궁금해 했었기 때문에 적어봤습니다.

서명 키 만들기

macOS의 터미널 환경에서 GPG 명령어를 사용하기 위해서는 다음 환경변수 등록이 필요합니다. 평소에도 자주 사용하게 되므로 ~/.zshrc 등에 추가해두면 편리합니다.

export GPG_TTY=$(tty)

우선 키 편집 모드에 들어갑니다.

$ gpg --list-keys --keyid-format LONG
pub   rsa4096/8A82A50A2DF52EE4 2018-02-23 [SC] [expires: 2034-02-19]
uid                 [ultimate] Do Hoerin <[email protected]>
sub   rsa4096/YYYYYYYYYYYYYYYY 2018-02-23 [E] [expires: 2034-02-19]

# 편집할 키 ID를 입력합니다.
$ gpg --expert --edit-key 8A82A50A2DF52EE4

? 명령어를 통해 편집 모드에서 사용할 수 있는 명령어 목록을 확인할 수 있습니다. 다음과 같이 보조키를 생성할 수 있습니다.

gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
  (14) Existing key from card
Your selection? 10

Git 서명에 사용할 키는 서명 키(sign key) 중에 하나를 선택합니다. OS 및 버전에 따라 지원하는 알고리즘의 목록이 조금씩 다를 수 있습니다.

이 글에서는 더 짧은 키 길이로 높은 보안 수준을 제공하는 ECC 알고리즘을 사용합니다. ECC 알고리즘이 지원되지 않는다면 RSA 알고리즘을 사용하는 것이 좋습니다.

Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 1

Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 1y
Key expires at 일  8/ 6 22:02:18 2023 KST
Is this correct? (y/N) y
Really create? (y/N) y

서브 키는 추후 교체(rotation)가 가능하므로 무제한으로 설정하기보다는 적당한 유효 기간을 설정하는 것이 좋습니다.

이후 비밀 키의 암호를 입력하면 다음과 같이 서명 키가 생성된 것을 확인할 수 있습니다.

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

sec  rsa4096/8A82A50A2DF52EE4
     created: 2018-02-23  expires: 2034-02-19  usage: SC
     trust: unknown       validity: ultimate
ssb  rsa4096/YYYYYYYYYYYYYYYY
     created: 2018-02-23  expires: 2034-02-19  usage: E
ssb  ed25519/ZZZZZZZZZZZZZZZZ
     created: 2022-08-06  expires: 2023-08-06  usage: S
[ultimate] (1). Do Hoerin <[email protected]>

서명 키를 YubiKey로 옮기기

방금 만든 서명 키를 YubiKey로 옮겨봅시다.

gpg> key 2
sec  rsa4096/8A82A50A2DF52EE4
     created: 2018-02-23  expires: 2034-02-19  usage: SC
     trust: unknown       validity: ultimate
ssb  rsa4096/YYYYYYYYYYYYYYYY
     created: 2018-02-23  expires: 2034-02-19  usage: E
ssb* ed25519/ZZZZZZZZZZZZZZZZ
     created: 2022-08-06  expires: 2023-08-06  usage: S
[ultimate] (1). Do Hoerin <[email protected]>

ssb 옆의 * 표시를 통해 어떤 키가 선택되었는지 알 수 있습니다. keytocard 명령어를 통해 선택한 키를 YubiKey로 옮깁니다.

gpg> keytocard
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1

sec  rsa4096/8A82A50A2DF52EE4
     created: 2018-02-23  expires: 2034-02-19  usage: SC
     trust: unknown       validity: unknown
ssb  rsa4096/YYYYYYYYYYYYYYYY
     created: 2018-02-23  expires: 2034-02-19  usage: E
ssb* ed25519/ZZZZZZZZZZZZZZZZ
     created: 2022-08-06  expires: 2023-08-06  usage: S
[ unknown] (1). Do Hoerin <[email protected]>

기존 비밀 키에 암호가 존재하는 경우 해당 암호를 입력해줍니다. 추가로 Admin PIN 번호를 묻는 경우, 여러분이 따로 설정하지 않았다면 기본값은 12345678 입니다.

저장 후 키가 정상적으로 옮겨갔는지 확인해봅시다.

gpg> save

$ gpg --card-status
...
General key info..: sub  ed25519/ZZZZZZZZZZZZZZZZ 2022-08-06 Do Hoerin <[email protected]>
sec#  rsa4096/8A82A50A2DF52EE4  created: 2018-02-23  expires: 2034-02-19
ssb#  rsa4096/YYYYYYYYYYYYYYYY  created: 2018-02-23  expires: 2034-02-19
ssb>  ed25519/ZZZZZZZZZZZZZZZZ  created: 2022-08-06  expires: 2023-08-06
                                card-no: XXXX XXXXXXXX

키가 정상적으로 옮겨간 것을 확인할 수 있습니다.

Git, GitHub 그리고 Keybase 설정 업데이트

위 과정을 통해 만든 서명 키를 git에 설정해줍니다.

$ git config --global user.signingkey ZZZZZZZZZZZZZZZZ

이후 새로운 커밋을 할 때는 YubiKey를 삽입하라는 안내가 나오게 됩니다.

YubiKey 삽입 알림

또한 동작 원리 문단에서 설명했듯이, 서명 키를 찾기 위해서는 카드 번호가 저장된 공개 키가 필요합니다. 이는 서명할 때 뿐만 아니라 서명을 검증할 때도 마찬가지입니다. 따라서 GitHub에 등록된 공개 키도 업데이트 해주어야합니다.

다음과 같이 공개 키를 내보내고 해당 값을 GitHub의 GPG 키 설정 화면에서 등록해줍니다.

$ gpg --armor --export XXXXXXXXXXXXXXXX

GitHub에 보조키가 등록된 모습

방금 생성한 보조키가 등록된 것을 알 수 있습니다.

마지막으로, keybase를 사용한다면 업데이트 된 공개 키를 업로드할 수 있습니다.

$ keybase pgp update

이후 다른 PC를 사용할 때 공개 키를 파일로 옮길 필요 없이, keybase를 통해 내려받을 수 있어 편리합니다.

관련된 글

Rails와 GitHub Actions에 커버리지 레포트를 달아보자

이 블로그의 CMS이기도 한 Shiori를 대폭 리팩토링하면서 테스트가 얼마나 잘 작성되어있는지 궁금해졌습니다.

Rails Global ID로 전역 객체 식별하기

Global ID는 Rails의 모든 객체를 식별할 수 있는 URI(Uniform Resource Identifier)입니다.

Ruby on WebAssembly: 살짝 맛보기

Ruby 3.2에 추가된 WebAssembly 지원을 간단하게 테스트해봅시다.

작성한 댓글은 giscus를 통해 GitHub Discussion에 저장됩니다.

크리에이티브 커먼즈 라이선스크리에이티브 커먼즈 저작자표시크리에이티브 커먼즈 동일조건변경허락

본 사이트의 저작물은 별도의 언급이 없는 한 크리에이티브 커먼즈 저작자표시-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.

LYnLab, 2011 - 2024.