GnuPG의 기본적인 사용법을 살펴보고 이를 기반으로 SSH, Mutt 등 개발자의 일상 생활에 걸쳐 있는 보안에 대해서 짚어볼 수 있는 좋은 시리즈입니다. 원문 번역에 충실했으며, 제가 사용하는 GPG 버전과 원문에 있는 콘솔 출력 내용이 다르기 때문에, 제가 사용하는 버전에 맞추어 다시 쓴 것임을 알립니다. 본래 콘솔 내용은 당연히 원문에서 볼 수 있습니다.



1. GnuPG Keys

원문 링크


Keypair 생성하기

첫 걸음으로 4096-bit의 RSA keypair를 생성해볼 건데, 이는 보통 기준보다 훨씬 높은 암호화 수준이다. 여기서는 Debian 개발자들이 추천하는 몇몇 방식을 따라갈 것이다.

본인이 개인적인 용도로 쓰는 최신 데스크탑 컴퓨터를 사용해야 엔트로피를 수월하게 생성할 수 있다. 물론 SSH-only headless server 안에서도 key를 생성할 수 있긴 한데, 적정 수준의 무작위성을 생성하기 위해 암호학적으로 덜 좋은 방법론을 쓰는 점을 감안해야 할 것이다.

우선 ~/.gnupg/gpg.conf 파일을 만들어서 아래처럼 내용을 적어본다.

personal-digest-preferences SHA256
cert-digest-algo SHA256
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed

이는 GnuPG가 오래 전부터 문제가 있었던 SHA1보다 암호학적으로 더 강력한 SHA256 hashing 알고리즘으로 signature를 만들도록 설정한 것이다.


위 설정이 되었다면 이제 key를 만들어보자.

$ gpg --full-generate-key


그러면 생성하고자하는 keypair의 유형을 고르게 된다. RSA and RSA가 기본값인데, 이는 서명(signing)을 위한 master key와 암호화를 위한 subkey를 하나씩 생성한다는 의미이다.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 1


Key의 길이로는 가장 긴 옵션인 4096 bit로 정하겠다.

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits


Key의 만료일은 원하는 대로 정하면 된다. Private key에 접근할 수만 있다면, 심지어 그 key가 이미 만료되었더라도 언제든지 만료일을 원하는 만큼 변경할 수 있으므로 1년 정도로 유효 기간을 두는 것이 좋은 관습이다. 따라서 이번 예제에서는 유효 기간을 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 Mon 13 Jan 2020 02:02:07 PM KST
Is this correct? (y/N) y


그 다음으로는 key를 이름 짓는 기본적인 정보를 입력해야 한다. 현실 세계에서 당신이 당신임을 검증할 수 있는 개념을 쓰지 않는다면 public key는 장기적으로 봤을 때 더욱이 쓸모 없어지기 때문에, 웬만한 상황에서는 당신의 실명을 사용하는 것이 좋을 것이다. 코멘트에는 key의 목적이나 key의 공개적인 별명 등 관련된 정보를 입력하면 된다.

GnuPG needs to construct a user ID to identify your key.

Real name: Donggun Kim
Email address: dgkimdev@gmail.com
Comment: Test Key Only
You selected this USER-ID:
    "Donggun Kim (Test Key Only) <dgkimdev@gmail.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O 


Key 암호 (Passphrase)

이 key를 암호화하기 위해 필요한 passphrase를 입력할 시간이 왔다. 암호화가 된 key는 누군가에게 잘못 전달되었다 하더라도 passphrase를 모르면 사용할 수가 없다.

You need a Passphrase to protect your secret key.

당신이 쉽게 기억할 수 있는 특별한 문장을 사용하는 것이 좋은데, 길면 길수록 더 좋다. 명언이나 영화의 유명한 문구와 같이 찍어볼 수 있는 것들은 passphrase로 정하지 말자. 또한 passphrase의 정확한 글자들을 기억해야 하므로, 필자는 모두 소문자에 마침표는 없도록 하는 것을 추천한다. 위키피디아에도 이에 관련한 가이드라인이 있다.


엔트로피 생성

마지막 단계로, 시스템은 이제 엔트로피를 생성할 것이라고 우리에게 알려줄 것이다.

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.

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy! (Need 283 more bytes)

이는 컴퓨터가 충분히 랜덤한 데이터를 생성해서 private key가 생성된 후에 누군가에 의해 똑같이 생성될 수 없도록 보장하기 위해 필수적인 단계이다. 마우스 커서를 빙글빙글 돌리거나 키보드로 아무거나 입력하면 되는데, 사실 디스크를 읽는 것도 포함해서 어떠한 종류의 하드웨어 활동도 같은 효과를 줄 수 있다. (어느 누구나 쉽게 추측할 수 없는) 파일 시스템 위에서 대량의 find(1) 작업을 실행시키는 것도 도움이 된다.

이 단계가 끝나기를 참을성을 가지고 기다려야 한다. 인터넷에서 찾아보면 rngd(1) 대신에 non-blocking의 난수 생성 도구인 /dev/urandom를 사용하도록 강제하자는 논의가 있기도 하다. 그렇게 하면 분명히 속도 측면에서는 도움이 될 것이다. 하지만 필자는 가능하다면 컴퓨터와 상호작용 (위에서 언급한 마우스 돌리기, 아무거나 입력하기 등) 하고 하드웨어의 잡음을 사용해서 적절한 난수를 생성하는 것을 추천하고 싶다.

적정 수준의 엔트로피가 읽혀서 key 생성이 끝났다면, 서명을 위한 master keypair와 암호화를 위한 subkey pair의 자세한 정보를 출력받을 것이다. 또한 각 keypair의 private key와 public key가 자동적으로 당신이 사용하는 keyring에 둥록된다.

gpg: /home/don/.gnupg/trustdb.gpg: trustdb created
gpg: key 1E68947E07BAAF6E marked as ultimately trusted
gpg: revocation certificate stored as '/home/don/.gnupg/openpgp-revocs.d/22BF6314B3764EF3E0E0233E1E68947E07BAAF6E.rev'
public and secret key created and signed.

pub   rsa4096 2019-01-13 [SC] [expires: 2020-01-13]
      22BF6314B3764EF3E0E0233E1E68947E07BAAF6E
uid                      Donggun Kim (Test Key Only) <dgkimdev@gmail.com>
sub   rsa4096 2019-01-13 [E] [expires: 2020-01-13]


Key 관리

Key 생성이 완료되면, public/private keychain에 그 key가 추가되어 있게 된다.

$ gpg --list-secret-keys
/home/don/.gnupg/pubring.kbx
----------------------------
sec   rsa4096 2019-01-13 [SC] [expires: 2020-01-13]
      22BF6314B3764EF3E0E0233E1E68947E07BAAF6E
uid           [ultimate] Donggun Kim (Test Key Only) <dgkimdev@gmail.com>
ssb   rsa4096 2019-01-13 [E] [expires: 2020-01-13]

$ gpg --list-public-keys
/home/don/.gnupg/pubring.kbx
----------------------------
pub   rsa4096 2019-01-13 [SC] [expires: 2020-01-13]
      22BF6314B3764EF3E0E0233E1E68947E07BAAF6E
uid           [ultimate] Donggun Kim (Test Key Only) <dgkimdev@gmail.com>
sub   rsa4096 2019-01-13 [E] [expires: 2020-01-13]


~/.gnupg 경로에 관리하고 있는 key들이 들어있다. 이 경로를 비밀스럽게 보관하고 안전하게 백업해두는 것이 정말 매우 굉장히 중요하다. 분리 가능한 매체에 따로 저장해서 물리적으로도 안전한 장소에 보관하는 것이 가장 바람직하다. 잃어버리면 안 된다!

GnuPG의 대부분의 문맥에서 key는 그 소유자의 이름으로 가리킬 수 있고, 8자리의 hex ID로도 일치시킬 수 있다. 필자는 hex ID를 선호한다. 내 main key의 짧은 ID는 07BAAF6E임을 볼 수 있다 (역자 업데이트: 실제 hex ID 22BF6314B3764EF3E0E0233E1E68947E07BAAF6E의 마지막 8자리이다). 실제 어떠한 검증을 이 hex ID만으로 해선 안 되지만, 당신의 keyring 안에 등록된 key들에 한해서 구분 지을 정도로는 충분히 쓸 만 하다.

예를 들어 자신의 public key 복사본을 누구에게 주고 싶을 때의 편리한 방법으로 --armor 옵션을 통해 ASCII 형식으로 내보낼 (export) 수가 있는데, 이 때 짧은 hex ID면 충분히 key를 가리킬 수 있는 것이다.

$ gpg --armor --export 07BAAF6E > donggun-kim.public.asc


--export-secret-key을 사용해서 private key도 같은 방식으로 내보낼 수 있지만, private key를 누군가에게 전해주는 일은 절대 절대로 없어야 한다.


폐기를 위한 인증서

당신의 key를 생성한 후에는 필히 폐기를 위한 인증서를 생성해야 한다 (역자 업데이트: gpg --full-gen-key 과정에서 자동으로 폐기를 위한 인증서를 생성해준다).

$ gpg --output revoke.asc --gen-revoke 07BAAF6E

sec  rsa4096/1E68947E07BAAF6E 2019-01-13 Donggun Kim (Test Key Only) <dgkimdev@gmail.com>

Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here)
Your decision? 1
Enter an optional description; end it with an empty line:
> For test
>
Reason for revocation: Key has been compromised
For test
Is this okay? (y/N) y
ASCII armored output forced.
Revocation certificate created.

Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable.  But have some caution:  The print system of
your machine might store the data and make it available to others!

이렇게 생성된 revoke.asc 파일도 안전한 어딘가에 저장해두어야 한다. 나중에 언젠가 당신의 private key가 노출되었을 경우에 이 인증서를 사용해 key를 폐기해서 이 key가 더 이상 믿을 수 없음을 사람들에게 알도록 할 수 있다. gpg가 출력했듯이, 이 인증서를 종이로 출력해두는 것도 좋다.

여기까지의 작업을 마쳤다면 이제 GnuPG의 기본적인 기능을 사용할 수 있다. 이는 다음 글에서 이어질 것이다.


Subkeys

Key 목록을 보는 두 명령어의 결과에서 당신은 두 개의 private key와 두 개의 public key를 생성받았다는 것을 확인할 수 있다. sub로 시작하는 줄은 당신을 위해 자동으로 생성된 암호화를 위한 subkey를 가리킨다. Master key는 암호학적인 서명을 위해서 쓰이고, subkey는 암호화를 위해 쓰인다. 이는 GnuPG가 RSA keypair를 통해 기본적으로 하고자 하는 일이다.

보안을 더 신경쓰자면, master private key를 물리적으로 당신의 컴퓨터에서 떼어내고 그 대신 두 번째로 생성된 subkey를 파일에 서명하도록 할 수도 있다. 이렇게 하면 master key를 분리 가능한 매체에 안전하게 보관하도록 하고, 백업도 더 수월해질 수 있으며, 당신이 주로 사용하는 컴퓨터가 뚫렸을 경우에도 master key가 안전하기 때문이다.

즉, 파일을 서명하고 암호화하는 데 subkey면 충분하다는 말이다. 만약 subkey가 노출되거나 오염되었다면 즉시 폐기한 다음에 안전하게 보관되어 있는 master key를 통해서 새로운 subkey를 생성하면 된다. 당신의 public master key를 사용했던 다른 이들이 해당 key를 폐기하고 새로운 public key를 등록할 필요도 없다.

그래서 이렇게 어떻게 할 수 있냐? 에 대해서는 subkey 관리에 대한 Debian 위키를 참조하길 추천한다. 물론 기본적인 GPG 기능을 사용하기 위해 필수적인 단계는 아니다.