← Documents Documentation/process/maintainer-pgp-guide.rst GitHub 원문 ↗

Linux 6.18.37 · Maintainer

Kernel maintainer PGP guide

Infrastructure가 아니라 developer identity를 검증하기 위한 PGP key, subkey와 offline backup, smartcard, signed tag·commit·patch workflow를 설명합니다.

Source pathDocumentation/process/maintainer-pgp-guide.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

Developer identity와 release provenance

maintainer-pgp-guide.rst:4-59

Kernel workflow에서 PGP는 server나 mail infrastructure 자체보다 특정 developer가 tag, commit 또는 patch를 승인했다는 identity chain을 검증한다. Repository mirror가 여러 곳이어도 signed object와 trusted key를 검증해 maintainer handoff provenance를 확인한다.

Certify primary key와 signing subkey 분리

maintainer-pgp-guide.rst:60-235

GnuPG 2.4 이상과 gpg-agent를 사용하고 강한 passphrase를 설정한다. Primary key의 Certify capability는 새 subkey와 identity를 승인하는 root이므로 일상 machine에서 분리하고, 실제 tag·commit signing은 별도 signing subkey로 수행한다.

Certify key는 offline encrypted storage에 복구 가능하게 backup하고 전체 GnuPG directory backup도 검증한다. Backup은 존재만 확인하지 말고 별도 환경에서 key listing과 restore 절차를 test한다.

Certify key 제거와 smartcard

maintainer-pgp-guide.rst:236-572

Workstation homedir에는 public primary key와 필요한 subkey만 남기고 Certify private key material을 offline storage로 이동한다. Keygrip와 private-keys-v1.d file을 확인한 뒤 제거하므로 잘못된 file 삭제를 피하고 backup을 먼저 검증한다.

Signing·authentication subkey를 smartcard나 hardware token으로 옮기면 private material이 device 밖으로 나오지 않는다. Device admin PIN, user PIN과 reset code를 안전하게 설정하고 transfer 뒤 local secret stub와 실제 signing을 확인한다.

Smartcard는 backup이 아니다. Device 분실·고장 때 새 subkey를 발급할 수 있도록 offline Certify key와 revoke·rotation 절차가 필요하다.

Expiration 연장과 work directory 갱신

maintainer-pgp-guide.rst:573-638

Key expiration을 바꾸려면 offline Certify key를 안전하게 mount하고 subkey expiry를 갱신한 뒤 public key를 다시 배포한다. Workstation keyring과 smartcard stub가 새 metadata를 보는지 확인한다. gpg-agent forwarding over SSH는 remote host가 agent operation을 요청할 수 있다는 trust boundary를 이해하고 제한적으로 사용한다.

Signed tag와 commit

maintainer-pgp-guide.rst:639-765

Git user.signingKey와 gpg program을 설정하고 maintainer pull request의 annotated tag를 sign한다. Consumer는 tag object signature, tag가 가리키는 commit과 expected key identity를 모두 확인한다. 단순히 'Good signature'만 보고 key trust를 생략하지 않는다.

Commit signing은 repository policy에 맞게 사용하며 모든 commit을 sign하는 것과 maintainer integration point를 signed tag로 인증하는 목적을 구분한다. git log --show-signature와 verify-tag·verify-commit으로 검증한다.

Patatt signed patch와 key discovery

maintainer-pgp-guide.rst:766-911

Patatt는 mail body가 전달 과정에서 유지됐는지 developer signature로 attest한다. 설치·설정 뒤 outgoing patch에 signature header를 넣고 b4·patatt tooling으로 archive message를 검증한다.

WKD와 DANE를 통한 auto key retrieval을 설정할 수 있지만 가져온 key의 identity trust는 별도 문제다. Web of Trust와 TOFU의 차이를 이해하고 kernel.org web-of-trust repository와 직접 확인한 fingerprint를 이용해 maintainer identity를 검증한다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. _pgpguide:
2
3 ===========================
4 Kernel Maintainer PGP guide
5 ===========================
6
7 :Author: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
8
9 This document is aimed at Linux kernel developers, and especially at
10 subsystem maintainers. It contains a subset of information discussed in
11 the more general "`Protecting Code Integrity`_" guide published by the
12 Linux Foundation. Please read that document for more in-depth discussion
13 on some of the topics mentioned in this guide.
14
15 .. _`Protecting Code Integrity`: https://github.com/lfit/itpol/blob/master/protecting-code-integrity.md
16
17 The role of PGP in Linux Kernel development
18 ===========================================
19
20 PGP helps ensure the integrity of the code that is produced by the Linux
21 kernel development community and, to a lesser degree, establish trusted
22 communication channels between developers via PGP-signed email exchange.
23
24 The Linux kernel source code is available in two main formats:
25
26 - Distributed source repositories (git)
27 - Periodic release snapshots (tarballs)
28
29 Both git repositories and tarballs carry PGP signatures of the kernel
30 developers who create official kernel releases. These signatures offer a
31 cryptographic guarantee that downloadable versions made available via
32 kernel.org or any other mirrors are identical to what these developers
33 have on their workstations. To this end:
34
35 - git repositories provide PGP signatures on all tags
36 - tarballs provide detached PGP signatures with all downloads
37
38 .. _devs_not_infra:
39
40 Trusting the developers, not infrastructure
41 -------------------------------------------
42
43 Ever since the 2011 compromise of core kernel.org systems, the main
44 operating principle of the Kernel Archives project has been to assume
45 that any part of the infrastructure can be compromised at any time. For
46 this reason, the administrators have taken deliberate steps to emphasize
47 that trust must always be placed with developers and never with the code
48 hosting infrastructure, regardless of how good the security practices
49 for the latter may be.
50
51 The above guiding principle is the reason why this guide is needed. We
52 want to make sure that by placing trust into developers we do not merely
53 shift the blame for potential future security incidents to someone else.
54 The goal is to provide a set of guidelines developers can use to create
55 a secure working environment and safeguard the PGP keys used to
56 establish the integrity of the Linux kernel itself.
57
58 .. _pgp_tools:
59
60 PGP tools
61 =========
62
63 Use GnuPG 2.4 or later
64 ----------------------
65
66 Your distro should already have GnuPG installed by default, you just
67 need to verify that you are using a reasonably recent version of it.
68 To check, run::
69
70 $ gpg --version | head -n1
71
72 If you have version 2.4 or above, then you are good to go. If you have
73 an earlier version, then you are using a release of GnuPG that is no
74 longer maintained and some commands from this guide may not work.
75
76 Configure gpg-agent options
77 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
78
79 The GnuPG agent is a helper tool that will start automatically whenever
80 you use the ``gpg`` command and run in the background with the purpose
81 of caching the private key passphrase. There are two options you should
82 know in order to tweak when the passphrase should be expired from cache:
83
84 - ``default-cache-ttl`` (seconds): If you use the same key again before
85 the time-to-live expires, the countdown will reset for another period.
86 The default is 600 (10 minutes).
87 - ``max-cache-ttl`` (seconds): Regardless of how recently you've used
88 the key since initial passphrase entry, if the maximum time-to-live
89 countdown expires, you'll have to enter the passphrase again. The
90 default is 30 minutes.
91
92 If you find either of these defaults too short (or too long), you can
93 edit your ``~/.gnupg/gpg-agent.conf`` file to set your own values::
94
95 # set to 30 minutes for regular ttl, and 2 hours for max ttl
96 default-cache-ttl 1800
97 max-cache-ttl 7200
98
99 .. note::
100
101 It is no longer necessary to start gpg-agent manually at the
102 beginning of your shell session. You may want to check your rc files
103 to remove anything you had in place for older versions of GnuPG, as
104 it may not be doing the right thing any more.
105
106 .. _protect_your_key:
107
108 Protect your PGP key
109 ====================
110
111 This guide assumes that you already have a PGP key that you use for Linux
112 kernel development purposes. If you do not yet have one, please see the
113 "`Protecting Code Integrity`_" document mentioned earlier for guidance
114 on how to create a new one.
115
116 You should also make a new key if your current one is weaker than 2048
117 bits (RSA).
118
119 Understanding PGP Subkeys
120 -------------------------
121
122 A PGP key rarely consists of a single keypair -- usually it is a
123 collection of independent subkeys that can be used for different
124 purposes based on their capabilities, assigned at their creation time.
125 PGP defines four capabilities that a key can have:
126
127 - **[S]** keys can be used for signing
128 - **[E]** keys can be used for encryption
129 - **[A]** keys can be used for authentication
130 - **[C]** keys can be used for certifying other keys
131
132 The key with the **[C]** capability is often called the "master" key,
133 but this terminology is misleading because it implies that the Certify
134 key can be used in place of any of other subkey on the same chain (like
135 a physical "master key" can be used to open locks made for other keys).
136 Since this is not the case, this guide will refer to it as "the Certify
137 key" to avoid any ambiguity.
138
139 It is critical to fully understand the following:
140
141 1. All subkeys are fully independent from each other. If you lose a
142 private subkey, it cannot be restored or recreated from any other
143 private key on your chain.
144 2. With the exception of the Certify key, there can be multiple subkeys
145 with identical capabilities (e.g. you can have 2 valid encryption
146 subkeys, 3 valid signing subkeys, but only one valid certification
147 subkey). All subkeys are fully independent -- a message encrypted to
148 one **[E]** subkey cannot be decrypted with any other **[E]** subkey
149 you may also have.
150 3. A single subkey may have multiple capabilities (e.g. your **[C]** key
151 can also be your **[S]** key).
152
153 The key carrying the **[C]** (certify) capability is the only key that
154 can be used to indicate relationship with other keys. Only the **[C]**
155 key can be used to:
156
157 - add or revoke other keys (subkeys) with S/E/A capabilities
158 - add, change or revoke identities (uids) associated with the key
159 - add or change the expiration date on itself or any subkey
160 - sign other people's keys for web of trust purposes
161
162 By default, GnuPG creates the following when generating new keys:
163
164 - One subkey carrying both Certify and Sign capabilities (**[SC]**)
165 - A separate subkey with the Encryption capability (**[E]**)
166
167 If you used the default parameters when generating your key, then that
168 is what you will have. You can verify by running ``gpg --list-secret-keys``,
169 for example::
170
171 sec ed25519 2022-12-20 [SC] [expires: 2024-12-19]
172 000000000000000000000000AAAABBBBCCCCDDDD
173 uid [ultimate] Alice Dev <adev@kernel.org>
174 ssb cv25519 2022-12-20 [E] [expires: 2024-12-19]
175
176 The long line under the ``sec`` entry is your key fingerprint --
177 whenever you see ``[fpr]`` in the examples below, that 40-character
178 string is what it refers to.
179
180 Ensure your passphrase is strong
181 --------------------------------
182
183 GnuPG uses passphrases to encrypt your private keys before storing them on
184 disk. This way, even if your ``.gnupg`` directory is leaked or stolen in
185 its entirety, the attackers cannot use your private keys without first
186 obtaining the passphrase to decrypt them.
187
188 It is absolutely essential that your private keys are protected by a
189 strong passphrase. To set it or change it, use::
190
191 $ gpg --change-passphrase [fpr]
192
193 Create a separate Signing subkey
194 --------------------------------
195
196 Our goal is to protect your Certify key by moving it to offline media,
197 so if you only have a combined **[SC]** key, then you should create a
198 separate signing subkey::
199
200 $ gpg --quick-addkey [fpr] ed25519 sign
201
202 Back up your Certify key for disaster recovery
203 ----------------------------------------------
204
205 The more signatures you have on your PGP key from other developers, the
206 more reasons you have to create a backup version that lives on something
207 other than digital media, for disaster recovery reasons.
208
209 A good way to create a printable hardcopy of your private key is by
210 using the ``paperkey`` software written for this very purpose. See ``man
211 paperkey`` for more details on the output format and its benefits over
212 other solutions. Paperkey should already be packaged for most
213 distributions.
214
215 Run the following command to create a hardcopy backup of your private
216 key::
217
218 $ gpg --export-secret-key [fpr] | paperkey -o /tmp/key-backup.txt
219
220 Print out that file, then take a pen and write your passphrase on the
221 margin of the paper. **This is strongly recommended** because the key
222 printout is still encrypted with that passphrase, and if you ever change
223 it you will not remember what it used to be when you had created the
224 backup -- *guaranteed*.
225
226 Put the resulting printout and the hand-written passphrase into an envelope
227 and store in a secure and well-protected place, preferably away from your
228 home, such as your bank vault.
229
230 .. note::
231
232 The key is still encrypted with your passphrase, so printing out
233 even to "cloud-integrated" modern printers should remain a
234 relatively safe operation.
235
236 Back up your whole GnuPG directory
237 ----------------------------------
238
239 .. warning::
240
241 **!!!Do not skip this step!!!**
242
243 It is important to have a readily available backup of your PGP keys
244 should you need to recover them. This is different from the
245 disaster-level preparedness we did with ``paperkey``. You will also rely
246 on these external copies whenever you need to use your Certify key --
247 such as when making changes to your own key or signing other people's
248 keys after conferences and summits.
249
250 Start by getting an external media card (preferably two!) that you will
251 use for backup purposes. You will need to create an encrypted partition
252 on this device using LUKS -- refer to your distro's documentation on how
253 to accomplish this.
254
255 For the encryption passphrase, you can use the same one as on your
256 PGP key.
257
258 Once the encryption process is over, re-insert your device and make sure
259 it gets properly mounted. Copy your entire ``.gnupg`` directory over to
260 the encrypted storage::
261
262 $ cp -a ~/.gnupg /media/disk/foo/gnupg-backup
263
264 You should now test to make sure everything still works::
265
266 $ gpg --homedir=/media/disk/foo/gnupg-backup --list-key [fpr]
267
268 If you don't get any errors, then you should be good to go. Unmount the
269 device, distinctly label it so you don't overwrite it by accident, and
270 put in a safe place -- but not too far away, because you'll need to use
271 it every now and again for things like editing identities, adding or
272 revoking subkeys, or signing other people's keys.
273
274 Remove the Certify key from your homedir
275 ----------------------------------------
276
277 The files in our home directory are not as well protected as we like to
278 think. They can be leaked or stolen via many different means:
279
280 - by accident when making quick homedir copies to set up a new workstation
281 - by systems administrator negligence or malice
282 - via poorly secured backups
283 - via malware in desktop apps (browsers, pdf viewers, etc)
284 - via coercion when crossing international borders
285
286 Protecting your key with a good passphrase greatly helps reduce the risk
287 of any of the above, but passphrases can be discovered via keyloggers,
288 shoulder-surfing, or any number of other means. For this reason, the
289 recommended setup is to remove your Certify key from your home directory
290 and store it on offline storage.
291
292 .. warning::
293
294 Please see the previous section and make sure you have backed up
295 your GnuPG directory in its entirety. What we are about to do will
296 render your key useless if you do not have a usable backup!
297
298 First, identify the "keygrip" of your Certify key::
299
300 $ gpg --with-keygrip --list-key [fpr]
301
302 The output will be something like this::
303
304 pub ed25519 2022-12-20 [SC] [expires: 2022-12-19]
305 000000000000000000000000AAAABBBBCCCCDDDD
306 Keygrip = 1111000000000000000000000000000000000000
307 uid [ultimate] Alice Dev <adev@kernel.org>
308 sub cv25519 2022-12-20 [E] [expires: 2022-12-19]
309 Keygrip = 2222000000000000000000000000000000000000
310 sub ed25519 2022-12-20 [S]
311 Keygrip = 3333000000000000000000000000000000000000
312
313 Find the keygrip entry that is beneath the ``pub`` line (right under the
314 Certify key fingerprint). This will correspond directly to a file in your
315 ``~/.gnupg`` directory::
316
317 $ cd ~/.gnupg/private-keys-v1.d
318 $ ls
319 1111000000000000000000000000000000000000.key
320 2222000000000000000000000000000000000000.key
321 3333000000000000000000000000000000000000.key
322
323 It is sufficient to remove the .key file that corresponds to the Certify
324 key keygrip::
325
326 $ cd ~/.gnupg/private-keys-v1.d
327 $ rm 1111000000000000000000000000000000000000.key
328
329 Now, if you issue the ``--list-secret-keys`` command, it will show that
330 the Certify key is missing (the ``#`` indicates it is not available)::
331
332 $ gpg --list-secret-keys
333 sec# ed25519 2022-12-20 [SC] [expires: 2024-12-19]
334 000000000000000000000000AAAABBBBCCCCDDDD
335 uid [ultimate] Alice Dev <adev@kernel.org>
336 ssb cv25519 2022-12-20 [E] [expires: 2024-12-19]
337 ssb ed25519 2022-12-20 [S]
338
339 You should also remove any ``secring.gpg`` files in the ``~/.gnupg``
340 directory, which may be left over from previous versions of GnuPG.
341
342 If you don't have the "private-keys-v1.d" directory
343 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
344
345 If you do not have a ``~/.gnupg/private-keys-v1.d`` directory, then your
346 secret keys are still stored in the legacy ``secring.gpg`` file used by
347 GnuPG v1. Making any changes to your key, such as changing the
348 passphrase or adding a subkey, should automatically convert the old
349 ``secring.gpg`` format to use ``private-keys-v1.d`` instead.
350
351 Once you get that done, make sure to delete the obsolete ``secring.gpg``
352 file, which still contains your private keys.
353
354 .. _smartcards:
355
356 Move the subkeys to a dedicated crypto device
357 =============================================
358
359 Even though the Certify key is now safe from being leaked or stolen, the
360 subkeys are still in your home directory. Anyone who manages to get
361 their hands on those will be able to decrypt your communication or fake
362 your signatures (if they know the passphrase). Furthermore, each time a
363 GnuPG operation is performed, the keys are loaded into system memory and
364 can be stolen from there by sufficiently advanced malware (think
365 Meltdown and Spectre).
366
367 A good way to completely protect your keys is to move them to a
368 specialized hardware device that is capable of smartcard operations.
369
370 The benefits of smartcards
371 --------------------------
372
373 A smartcard contains a cryptographic chip that is capable of storing
374 private keys and performing crypto operations directly on the card
375 itself. Because the key contents never leave the smartcard, the
376 operating system of the computer into which you plug in the hardware
377 device is not able to retrieve the private keys themselves. This is very
378 different from the encrypted media storage device we used earlier for
379 backup purposes -- while that device is plugged in and mounted, the
380 operating system is able to access the private key contents.
381
382 Using external encrypted media is not a substitute to having a
383 smartcard-capable device.
384
385 Available smartcard devices
386 ---------------------------
387
388 Unless all your laptops and workstations have smartcard readers, the
389 easiest is to get a specialized USB device that implements smartcard
390 functionality. There are several options available:
391
392 - `Nitrokey Start`_: Open hardware and Free Software, based on FSI
393 Japan's `Gnuk`_. One of the cheapest options, but offers fewest
394 security features (such as resistance to tampering or some
395 side-channel attacks).
396 - `Nitrokey 3`_: Similar to the Nitrokey Start, but more
397 tamper-resistant and offers more security features and USB
398 form-factors. Supports ECC cryptography (ED25519 and NISTP).
399 - `Yubikey 5`_: proprietary hardware and software, but cheaper than
400 Nitrokey with a similar set of features. Supports ECC cryptography
401 (ED25519 and NISTP).
402
403 Your choice will depend on cost, shipping availability in your
404 geographical region, and open/proprietary hardware considerations.
405
406 .. note::
407
408 If you are listed in MAINTAINERS or have an account at kernel.org,
409 you `qualify for a free Nitrokey Start`_ courtesy of The Linux
410 Foundation.
411
412 .. _`Nitrokey Start`: https://www.nitrokey.com/products/nitrokeys
413 .. _`Nitrokey 3`: https://www.nitrokey.com/products/nitrokeys
414 .. _`Yubikey 5`: https://www.yubico.com/products/yubikey-5-overview/
415 .. _Gnuk: https://www.fsij.org/doc-gnuk/
416 .. _`qualify for a free Nitrokey Start`: https://www.kernel.org/nitrokey-digital-tokens-for-kernel-developers.html
417
418 Configure your smartcard device
419 -------------------------------
420
421 Your smartcard device should Just Work (TM) the moment you plug it into
422 any modern Linux workstation. You can verify it by running::
423
424 $ gpg --card-status
425
426 If you see full smartcard details, then you are good to go.
427 Unfortunately, troubleshooting all possible reasons why things may not
428 be working for you is way beyond the scope of this guide. If you are
429 having trouble getting the card to work with GnuPG, please seek help via
430 usual support channels.
431
432 To configure your smartcard, you will need to use the GnuPG menu system, as
433 there are no convenient command-line switches::
434
435 $ gpg --card-edit
436 [...omitted...]
437 gpg/card> admin
438 Admin commands are allowed
439 gpg/card> passwd
440
441 You should set the user PIN (1), Admin PIN (3), and the Reset Code (4).
442 Please make sure to record and store these in a safe place -- especially
443 the Admin PIN and the Reset Code (which allows you to completely wipe
444 the smartcard). You so rarely need to use the Admin PIN, that you will
445 inevitably forget what it is if you do not record it.
446
447 Getting back to the main card menu, you can also set other values (such
448 as name, gender, login data, etc), but it's not necessary and will
449 additionally leak information about your smartcard should you lose it.
450
451 .. note::
452
453 Despite having the name "PIN", neither the user PIN nor the admin
454 PIN on the card need to be numbers.
455
456 .. warning::
457
458 Some devices may require that you move the subkeys onto the device
459 before you can change the passphrase. Please check the documentation
460 provided by the device manufacturer.
461
462 Move the subkeys to your smartcard
463 ----------------------------------
464
465 Exit the card menu (using "q") and save all changes. Next, let's move
466 your subkeys onto the smartcard. You will need both your PGP key
467 passphrase and the admin PIN of the card for most operations::
468
469 $ gpg --edit-key [fpr]
470
471 Secret subkeys are available.
472
473 pub ed25519/AAAABBBBCCCCDDDD
474 created: 2022-12-20 expires: 2024-12-19 usage: SC
475 trust: ultimate validity: ultimate
476 ssb cv25519/1111222233334444
477 created: 2022-12-20 expires: never usage: E
478 ssb ed25519/5555666677778888
479 created: 2017-12-07 expires: never usage: S
480 [ultimate] (1). Alice Dev <adev@kernel.org>
481
482 gpg>
483
484 Using ``--edit-key`` puts us into the menu mode again, and you will
485 notice that the key listing is a little different. From here on, all
486 commands are done from inside this menu mode, as indicated by ``gpg>``.
487
488 First, let's select the key we'll be putting onto the card -- you do
489 this by typing ``key 1`` (it's the first one in the listing, the **[E]**
490 subkey)::
491
492 gpg> key 1
493
494 In the output, you should now see ``ssb*`` on the **[E]** key. The ``*``
495 indicates which key is currently "selected." It works as a *toggle*,
496 meaning that if you type ``key 1`` again, the ``*`` will disappear and
497 the key will not be selected any more.
498
499 Now, let's move that key onto the smartcard::
500
501 gpg> keytocard
502 Please select where to store the key:
503 (2) Encryption key
504 Your selection? 2
505
506 Since it's our **[E]** key, it makes sense to put it into the Encryption
507 slot. When you submit your selection, you will be prompted first for
508 your PGP key passphrase, and then for the admin PIN. If the command
509 returns without an error, your key has been moved.
510
511 **Important**: Now type ``key 1`` again to unselect the first key, and
512 ``key 2`` to select the **[S]** key::
513
514 gpg> key 1
515 gpg> key 2
516 gpg> keytocard
517 Please select where to store the key:
518 (1) Signature key
519 (3) Authentication key
520 Your selection? 1
521
522 You can use the **[S]** key both for Signature and Authentication, but
523 we want to make sure it's in the Signature slot, so choose (1). Once
524 again, if your command returns without an error, then the operation was
525 successful::
526
527 gpg> q
528 Save changes? (y/N) y
529
530 Saving the changes will delete the keys you moved to the card from your
531 home directory (but it's okay, because we have them in our backups
532 should we need to do this again for a replacement smartcard).
533
534 Verifying that the keys were moved
535 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
536
537 If you perform ``--list-secret-keys`` now, you will see a subtle
538 difference in the output::
539
540 $ gpg --list-secret-keys
541 sec# ed25519 2022-12-20 [SC] [expires: 2024-12-19]
542 000000000000000000000000AAAABBBBCCCCDDDD
543 uid [ultimate] Alice Dev <adev@kernel.org>
544 ssb> cv25519 2022-12-20 [E] [expires: 2024-12-19]
545 ssb> ed25519 2022-12-20 [S]
546
547 The ``>`` in the ``ssb>`` output indicates that the subkey is only
548 available on the smartcard. If you go back into your secret keys
549 directory and look at the contents there, you will notice that the
550 ``.key`` files there have been replaced with stubs::
551
552 $ cd ~/.gnupg/private-keys-v1.d
553 $ strings *.key | grep 'private-key'
554
555 The output should contain ``shadowed-private-key`` to indicate that
556 these files are only stubs and the actual content is on the smartcard.
557
558 Verifying that the smartcard is functioning
559 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
560
561 To verify that the smartcard is working as intended, you can create a
562 signature::
563
564 $ echo "Hello world" | gpg --clearsign > /tmp/test.asc
565 $ gpg --verify /tmp/test.asc
566
567 This should ask for your smartcard PIN on your first command, and then
568 show "Good signature" after you run ``gpg --verify``.
569
570 Congratulations, you have successfully made it extremely difficult to
571 steal your digital developer identity!
572
573 Other common GnuPG operations
574 -----------------------------
575
576 Here is a quick reference for some common operations you'll need to do
577 with your PGP key.
578
579 Mounting your safe offline storage
580 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
581
582 You will need your Certify key for any of the operations below, so you
583 will first need to mount your backup offline storage and tell GnuPG to
584 use it::
585
586 $ export GNUPGHOME=/media/disk/foo/gnupg-backup
587 $ gpg --list-secret-keys
588
589 You want to make sure that you see ``sec`` and not ``sec#`` in the
590 output (the ``#`` means the key is not available and you're still using
591 your regular home directory location).
592
593 Extending key expiration date
594 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
595
596 The Certify key has the default expiration date of 2 years from the date
597 of creation. This is done both for security reasons and to make obsolete
598 keys eventually disappear from keyservers.
599
600 To extend the expiration on your key by a year from current date, just
601 run::
602
603 $ gpg --quick-set-expire [fpr] 1y
604
605 You can also use a specific date if that is easier to remember (e.g.
606 your birthday, January 1st, or Canada Day)::
607
608 $ gpg --quick-set-expire [fpr] 2038-07-01
609
610 Remember to send the updated key back to keyservers::
611
612 $ gpg --send-key [fpr]
613
614 Updating your work directory after any changes
615 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
616
617 After you make any changes to your key using the offline storage, you will
618 want to import these changes back into your regular working directory::
619
620 $ gpg --export | gpg --homedir ~/.gnupg --import
621 $ unset GNUPGHOME
622
623 Using gpg-agent over ssh
624 ~~~~~~~~~~~~~~~~~~~~~~~~
625
626 You can forward your gpg-agent over ssh if you need to sign tags or
627 commits on a remote system. Please refer to the instructions provided
628 on the GnuPG wiki:
629
630 - `Agent Forwarding over SSH`_
631
632 It works more smoothly if you can modify the sshd server settings on the
633 remote end.
634
635 .. _`Agent Forwarding over SSH`: https://wiki.gnupg.org/AgentForwarding
636
637 .. _pgp_with_git:
638
639 Using PGP with Git
640 ==================
641
642 One of the core features of Git is its decentralized nature -- once a
643 repository is cloned to your system, you have full history of the
644 project, including all of its tags, commits and branches. However, with
645 hundreds of cloned repositories floating around, how does anyone verify
646 that their copy of linux.git has not been tampered with by a malicious
647 third party?
648
649 Or what happens if malicious code is discovered in the kernel and the
650 "Author" line in the commit says it was done by you, while you're pretty
651 sure you had `nothing to do with it`_?
652
653 To address both of these issues, Git introduced PGP integration. Signed
654 tags prove the repository integrity by assuring that its contents are
655 exactly the same as on the workstation of the developer who created the
656 tag, while signed commits make it nearly impossible for someone to
657 impersonate you without having access to your PGP keys.
658
659 .. _`nothing to do with it`: https://github.com/jayphelps/git-blame-someone-else
660
661 Configure git to use your PGP key
662 ---------------------------------
663
664 If you only have one secret key in your keyring, then you don't really
665 need to do anything extra, as it becomes your default key. However, if
666 you happen to have multiple secret keys, you can tell git which key
667 should be used (``[fpr]`` is the fingerprint of your key)::
668
669 $ git config --global user.signingKey [fpr]
670
671 How to work with signed tags
672 ----------------------------
673
674 To create a signed tag, pass the ``-s`` switch to the tag command::
675
676 $ git tag -s [tagname]
677
678 Our recommendation is to always sign git tags, as this allows other
679 developers to ensure that the git repository they are pulling from has
680 not been maliciously altered.
681
682 How to verify signed tags
683 ~~~~~~~~~~~~~~~~~~~~~~~~~
684
685 To verify a signed tag, use the ``verify-tag`` command::
686
687 $ git verify-tag [tagname]
688
689 If you are pulling a tag from another fork of the project repository,
690 git should automatically verify the signature at the tip you're pulling
691 and show you the results during the merge operation::
692
693 $ git pull [url] tags/sometag
694
695 The merge message will contain something like this::
696
697 Merge tag 'sometag' of [url]
698
699 [Tag message]
700
701 # gpg: Signature made [...]
702 # gpg: Good signature from [...]
703
704 If you are verifying someone else's git tag, you will first need to
705 import their PGP key. Please refer to the ":ref:`verify_identities`"
706 section below.
707
708 Configure git to always sign annotated tags
709 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
710
711 Chances are, if you're creating an annotated tag, you'll want to sign
712 it. To force git to always sign annotated tags, you can set a global
713 configuration option::
714
715 $ git config --global tag.forceSignAnnotated true
716
717 How to work with signed commits
718 -------------------------------
719
720 It is also possible to create signed commits, but they have limited
721 usefulness in Linux kernel development. The kernel contribution workflow
722 relies on sending in patches, and converting commits to patches does not
723 preserve git commit signatures. Furthermore, when rebasing your own
724 repository on a newer upstream, PGP commit signatures will end up
725 discarded. For this reason, most kernel developers don't bother signing
726 their commits and will ignore signed commits in any external
727 repositories that they rely upon in their work.
728
729 That said, if you have your working git tree publicly available at some
730 git hosting service (kernel.org, infradead.org, ozlabs.org, or others),
731 then the recommendation is that you sign all your git commits even if
732 upstream developers do not directly benefit from this practice.
733
734 We recommend this for the following reasons:
735
736 1. Should there ever be a need to perform code forensics or track code
737 provenance, even externally maintained trees carrying PGP commit
738 signatures will be valuable for such purposes.
739 2. If you ever need to re-clone your local repository (for example,
740 after reinstalling your system), this lets you verify the repository
741 integrity before resuming your work.
742 3. If someone needs to cherry-pick your commits, this allows them to
743 quickly verify their integrity before applying them.
744
745 Creating signed commits
746 ~~~~~~~~~~~~~~~~~~~~~~~
747
748 To create a signed commit, pass the ``-S`` flag to the ``git commit``
749 command (it's capital ``-S`` due to collision with another flag)::
750
751 $ git commit -S
752
753 Configure git to always sign commits
754 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
755
756 You can tell git to always sign commits::
757
758 git config --global commit.gpgSign true
759
760 .. note::
761
762 Make sure you configure ``gpg-agent`` before you turn this on.
763
764 .. _verify_identities:
765
766 How to work with signed patches
767 -------------------------------
768
769 It is possible to use your PGP key to sign patches sent to kernel
770 developer mailing lists. Since existing email signature mechanisms
771 (PGP-Mime or PGP-inline) tend to cause problems with regular code
772 review tasks, you should use the tool kernel.org created for this
773 purpose that puts cryptographic attestation signatures into message
774 headers (a-la DKIM):
775
776 - `Patatt Patch Attestation`_
777
778 .. _`Patatt Patch Attestation`: https://pypi.org/project/patatt/
779
780 Installing and configuring patatt
781 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
782
783 .. note::
784
785 If you use B4 to send in your patches, patatt is already installed
786 and integrated into your workflow.
787
788 Patatt is packaged for many distributions already, so please check there
789 first. You can also install it from pypi using "``pip install patatt``".
790
791 If you already have your PGP key configured with git (via the
792 ``user.signingKey`` configuration parameter), then patatt requires no
793 further configuration. You can start signing your patches by installing
794 the git-send-email hook in the repository you want::
795
796 patatt install-hook
797
798 Now any patches you send with ``git send-email`` will be automatically
799 signed with your cryptographic signature.
800
801 Checking patatt signatures
802 ~~~~~~~~~~~~~~~~~~~~~~~~~~
803
804 If you are using ``b4`` to retrieve and apply patches, then it will
805 automatically attempt to verify all DKIM and patatt signatures it
806 encounters, for example::
807
808 $ b4 am 20220720205013.890942-1-broonie@kernel.org
809 [...]
810 Checking attestation on all messages, may take a moment...
811 ---
812 ✓ [PATCH v1 1/3] kselftest/arm64: Correct buffer allocation for SVE Z registers
813 ✓ [PATCH v1 2/3] arm64/sve: Document our actual ABI for clearing registers on syscall
814 ✓ [PATCH v1 3/3] kselftest/arm64: Enforce actual ABI for SVE syscalls
815 ---
816 ✓ Signed: openpgp/broonie@kernel.org
817 ✓ Signed: DKIM/kernel.org
818
819 .. note::
820
821 Patatt and b4 are still in active development and you should check
822 the latest documentation for these projects for any new or updated
823 features.
824
825 .. _kernel_identities:
826
827 How to verify kernel developer identities
828 =========================================
829
830 Signing tags and commits is straightforward, but how does one go about
831 verifying that the key used to sign something belongs to the actual
832 kernel developer and not to a malicious imposter?
833
834 Configure auto-key-retrieval using WKD and DANE
835 -----------------------------------------------
836
837 If you are not already someone with an extensive collection of other
838 developers' public keys, then you can jumpstart your keyring by relying
839 on key auto-discovery and auto-retrieval. GnuPG can piggyback on other
840 delegated trust technologies, namely DNSSEC and TLS, to get you going if
841 the prospect of starting your own Web of Trust from scratch is too
842 daunting.
843
844 Add the following to your ``~/.gnupg/gpg.conf``::
845
846 auto-key-locate wkd,dane,local
847 auto-key-retrieve
848
849 DNS-Based Authentication of Named Entities ("DANE") is a method for
850 publishing public keys in DNS and securing them using DNSSEC signed
851 zones. Web Key Directory ("WKD") is the alternative method that uses
852 https lookups for the same purpose. When using either DANE or WKD for
853 looking up public keys, GnuPG will validate DNSSEC or TLS certificates,
854 respectively, before adding auto-retrieved public keys to your local
855 keyring.
856
857 Kernel.org publishes the WKD for all developers who have kernel.org
858 accounts. Once you have the above changes in your ``gpg.conf``, you can
859 auto-retrieve the keys for Linus Torvalds and Greg Kroah-Hartman (if you
860 don't already have them)::
861
862 $ gpg --locate-keys torvalds@kernel.org gregkh@kernel.org
863
864 If you have a kernel.org account, then you should `add the kernel.org
865 UID to your key`_ to make WKD more useful to other kernel developers.
866
867 .. _`add the kernel.org UID to your key`: https://korg.wiki.kernel.org/userdoc/mail#adding_a_kernelorg_uid_to_your_pgp_key
868
869 Web of Trust (WOT) vs. Trust on First Use (TOFU)
870 ------------------------------------------------
871
872 PGP incorporates a trust delegation mechanism known as the "Web of
873 Trust." At its core, this is an attempt to replace the need for
874 centralized Certification Authorities of the HTTPS/TLS world. Instead of
875 various software makers dictating who should be your trusted certifying
876 entity, PGP leaves this responsibility to each user.
877
878 Unfortunately, very few people understand how the Web of Trust works.
879 While it is still an important part of the OpenPGP specification,
880 recent versions of GnuPG (2.2 and above) have implemented an alternative
881 mechanism called "Trust on First Use" (TOFU). You can think of TOFU as
882 "the SSH-like approach to trust." With SSH, the first time you connect
883 to a remote system, its key fingerprint is recorded and remembered. If
884 the key changes in the future, the SSH client will alert you and refuse
885 to connect, forcing you to make a decision on whether you choose to
886 trust the changed key or not. Similarly, the first time you import
887 someone's PGP key, it is assumed to be valid. If at any point in the
888 future GnuPG comes across another key with the same identity, both the
889 previously imported key and the new key will be marked for verification
890 and you will need to manually figure out which one to keep.
891
892 We recommend that you use the combined TOFU+PGP trust model (which is
893 the new default in GnuPG v2). To set it, add (or modify) the
894 ``trust-model`` setting in ``~/.gnupg/gpg.conf``::
895
896 trust-model tofu+pgp
897
898 Using the kernel.org web of trust repository
899 --------------------------------------------
900
901 Kernel.org maintains a git repository with developers' public keys as a
902 replacement for replicating keyserver networks that have gone mostly
903 dark in the past few years. The full documentation for how to set up
904 that repository as your source of public keys can be found here:
905
906 - `Kernel developer PGP Keyring`_
907
908 If you are a kernel developer, please consider submitting your key for
909 inclusion into that keyring.
910
911 .. _`Kernel developer PGP Keyring`: https://korg.docs.kernel.org/pgpkeys.html
912

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Linux 커널 개발에서 PGP의 역할

1-56

이 문서는 Linux 커널 개발자, 특히 하위 시스템 maintainer를 위한 PGP 안내서다. Linux Foundation의 Protecting Code Integrity 문서에서 커널 작업에 필요한 부분을 추려 설명하며, 각 주제의 더 깊은 배경은 원문 안내서에서 확인할 수 있다.

PGP의 첫 번째 목적은 커널 개발 공동체가 생산한 코드의 무결성을 보장하는 것이다. 두 번째로 PGP 서명 이메일을 이용해 개발자 사이의 신뢰 가능한 통신 경로를 만드는 데 도움을 준다.

Linux 커널 소스는 분산 Git 저장소와 정기 release tarball의 두 형태로 배포된다. 공식 release를 만드는 개발자는 Git tag에 PGP 서명을 넣고, tarball에는 detached PGP signature를 함께 제공한다. 이 서명은 kernel.org나 mirror에서 받은 내용이 release 개발자의 workstation에 있던 내용과 동일하다는 암호학적 근거가 된다.

2011년 kernel.org 핵심 시스템 침해 이후 Kernel Archives 프로젝트는 인프라의 어느 부분도 언제든 침해될 수 있다고 가정한다. 호스팅 시스템의 보안 수준과 무관하게 신뢰의 종착점은 서버가 아니라 개발자와 개발자의 키여야 한다.

그러나 신뢰 대상을 개발자로 옮기는 것만으로는 사고 책임을 개인에게 전가하는 결과가 될 수 있다. 이 안내서의 목적은 개발자가 안전한 작업 환경을 만들고 커널 무결성을 증명하는 PGP 키를 보호할 수 있도록 구체적인 운용 규칙을 제공하는 것이다.

GnuPG와 gpg-agent

58-104

배포판에 기본 설치된 GnuPG의 버전을 먼저 확인한다. 이 문서는 GnuPG 2.4 이상을 기준으로 하며, 더 오래된 release는 유지보수가 끝났고 일부 명령이 동작하지 않을 수 있다.

$ gpg --version | head -n1

gpg-agent는 gpg 명령을 사용할 때 자동으로 시작되어 백그라운드에서 private key passphrase를 cache한다. default-cache-ttl은 마지막 키 사용 뒤 cache가 유지되는 시간이며, 만료 전에 같은 키를 사용하면 countdown이 다시 시작된다. 기본값은 600초다.

max-cache-ttl은 최초 passphrase 입력 이후의 절대 최대 cache 시간이다. 그 사이에 키를 계속 사용했더라도 이 시간이 지나면 다시 passphrase를 입력해야 한다. 기본값은 30분이다.

# ~/.gnupg/gpg-agent.conf
# 일반 TTL 30분, 최대 TTL 2시간
default-cache-ttl 1800
max-cache-ttl 7200

현대 GnuPG에서는 shell session을 시작할 때 gpg-agent를 수동 실행할 필요가 없다. 이전 버전을 위해 rc 파일에 넣어 둔 agent 시작 코드가 있다면 현재 동작과 충돌하지 않는지 확인하고 제거한다.

subkey 구조와 passphrase

106-201

이 문서는 이미 커널 개발용 PGP 키가 있다고 가정한다. 키가 없으면 Protecting Code Integrity의 생성 절차를 따르고, 기존 RSA 키가 2048비트보다 약하다면 새 키를 만든다.

PGP key는 보통 하나의 keypair가 아니라 서로 독립된 여러 subkey의 묶음이다. 생성할 때 각 subkey에 capability를 부여한다. [S]는 서명, [E]는 암호화, [A]는 인증, [C]는 다른 키를 인증하는 용도다.

[C] capability를 가진 키를 흔히 master key라고 부르지만, 다른 subkey를 대신할 수 있다는 오해를 부른다. 실제로 [C] 키가 [E] 또는 [S] 키의 private operation을 대신할 수 없으므로 이 문서는 Certify key라고 부른다.

  • 각 private subkey는 완전히 독립적이다. 하나를 잃어버리면 같은 key chain의 다른 private key로 복원하거나 다시 만들 수 없다.
  • Certify key를 제외하면 같은 capability의 유효한 subkey를 여러 개 둘 수 있다. 한 [E] subkey로 암호화한 메시지를 다른 [E] subkey로 복호화할 수는 없다.
  • 하나의 subkey가 여러 capability를 가질 수 있다. 예를 들어 [C]와 [S]를 함께 가진 [SC] 키가 가능하다.

Certify key만 key chain의 관계를 바꿀 수 있다. S/E/A subkey 추가와 폐기, UID 추가·변경·폐기, 자신과 subkey의 만료일 변경, Web of Trust를 위한 다른 사람 키 서명을 수행한다.

GnuPG 기본 생성 결과는 Certify와 Sign을 함께 가진 [SC] key 하나와 별도 [E] subkey 하나다. gpg --list-secret-keys 출력의 sec 아래 긴 40자리 문자열이 fingerprint이며, 아래 명령에서 [fpr]로 표시한 자리에 이 값을 사용한다.

sec   ed25519 2022-12-20 [SC] [expires: 2024-12-19]
      000000000000000000000000AAAABBBBCCCCDDDD
uid           [ultimate] Alice Dev <adev@kernel.org>
ssb   cv25519 2022-12-20 [E] [expires: 2024-12-19]

GnuPG는 disk에 저장하는 private key를 passphrase로 암호화한다. .gnupg 디렉터리 전체가 유출되어도 공격자가 passphrase를 얻지 못하면 private key를 바로 사용할 수 없다. 따라서 강한 passphrase는 필수이며 다음 명령으로 설정하거나 바꾼다.

$ gpg --change-passphrase [fpr]

# [SC]만 있다면 독립된 signing subkey 생성
$ gpg --quick-addkey [fpr] ed25519 sign

목표는 Certify key를 offline media로 옮기고 일상 signing 작업에는 별도 [S] subkey를 쓰는 것이다. [SC] 결합 키만 있다면 먼저 signing subkey를 추가한다.

PGP key chain의 권한 분리
Certify [C]: offlinesubkey 추가·폐기UID·만료일 관리다른 사람 키 서명
Signing [S]: smartcardGit tag·commit 서명patch attestation
Encryption [E]: smartcard수신 메시지 복호화
Authentication [A]: 선택인증 작업

Certify key는 관계와 수명을 관리하고, 일상 작업은 독립 subkey가 맡는다.

Certify key의 종이 재해 복구본

202-235

다른 개발자에게 받은 서명이 많을수록 key identity를 잃었을 때의 복구 비용이 커진다. 디지털 저장장치 전체가 손상되는 재해에 대비해 private key의 종이 백업을 만든다.

paperkey는 private key의 핵심 데이터를 출력 가능한 형식으로 만드는 도구다. 형식과 다른 방식보다 나은 점은 man paperkey에서 확인하며, 대부분의 배포판에서 package로 제공한다.

$ gpg --export-secret-key [fpr] | paperkey -o /tmp/key-backup.txt

파일을 출력하고 그 당시의 passphrase를 종이 여백에 손으로 기록하는 것을 강하게 권장한다. 출력된 key material도 passphrase로 암호화되어 있으며, 이후 passphrase를 바꾸면 백업을 만들던 때의 값을 기억하지 못할 가능성이 높다.

출력물과 수기 passphrase를 봉투에 넣어 집과 떨어진 은행 금고 같은 안전한 장소에 둔다. key data가 passphrase로 암호화되어 있으므로 cloud 연동 printer를 통한 출력도 상대적으로 안전하다고 원문은 설명한다.

전체 GnuPG 디렉터리 백업

236-273

이 단계는 생략하면 안 된다. 이후 Certify key를 working homedir에서 제거하므로, 검증된 전체 백업이 없으면 key chain을 사용할 수 없게 만들 수 있다.

paperkey는 재해 수준의 최후 복구본이고, 일상적인 key 변경에 사용할 수 있는 외부 백업은 별도로 필요하다. UID 편집, subkey 추가·폐기, 만료일 변경, conference나 summit 뒤 다른 사람 키 서명에는 Certify key가 든 이 복사본을 사용한다.

가급적 두 개의 외부 media를 준비하고 배포판 안내에 따라 LUKS 암호화 partition을 만든다. 암호화 passphrase는 PGP key와 같은 값을 사용할 수 있다고 원문은 제안한다. 장치를 mount한 다음 .gnupg 전체를 속성과 함께 복사한다.

$ cp -a ~/.gnupg /media/disk/foo/gnupg-backup

# 복사본을 직접 사용해 읽기 시험
$ gpg --homedir=/media/disk/foo/gnupg-backup --list-key [fpr]

오류 없이 key가 표시되는지 반드시 시험한다. 장치를 unmount하고 실수로 덮어쓰지 않도록 분명히 표시해 안전한 곳에 보관한다. 다만 Certify 작업 때마다 꺼내야 하므로 재해 복구용 종이보다 접근 가능한 위치여야 한다.

working homedir에서 Certify key 제거

274-353

home directory는 새 workstation을 위한 임시 복사, 시스템 관리자의 실수나 악의, 취약한 backup, browser·PDF viewer 같은 desktop app의 malware, 국경 통과 중 강제 조사 등 여러 경로로 유출될 수 있다.

강한 passphrase는 위험을 낮추지만 keylogger, 어깨너머 관찰과 다른 수단으로 노출될 수 있다. 따라서 Certify key는 일상 homedir에서 제거해 offline storage에만 둔다. 이 작업 전에 전체 .gnupg 백업이 정상 동작하는지 다시 확인해야 한다.

먼저 Certify key의 keygrip을 찾는다. 출력에서 pub 줄과 Certify fingerprint 바로 아래에 있는 Keygrip이 대상이다. 각 keygrip은 ~/.gnupg/private-keys-v1.d의 같은 이름 .key 파일에 대응한다.

$ gpg --with-keygrip --list-key [fpr]

pub   ed25519 2022-12-20 [SC] [expires: 2022-12-19]
      000000000000000000000000AAAABBBBCCCCDDDD
      Keygrip = 1111000000000000000000000000000000000000
uid           [ultimate] Alice Dev <adev@kernel.org>
sub   cv25519 2022-12-20 [E] [expires: 2022-12-19]
      Keygrip = 2222000000000000000000000000000000000000
sub   ed25519 2022-12-20 [S]
      Keygrip = 3333000000000000000000000000000000000000
$ cd ~/.gnupg/private-keys-v1.d
$ ls
1111000000000000000000000000000000000000.key
2222000000000000000000000000000000000000.key
3333000000000000000000000000000000000000.key

# 백업을 검증한 뒤 Certify key 파일만 제거
$ rm 1111000000000000000000000000000000000000.key

이후 gpg --list-secret-keys에서 sec#가 표시되어야 한다. #은 public 정보는 있지만 해당 private key가 현재 homedir에 없다는 뜻이다. [E]와 새 [S] subkey는 ssb로 계속 표시된다.

$ gpg --list-secret-keys
sec#  ed25519 2022-12-20 [SC] [expires: 2024-12-19]
      000000000000000000000000AAAABBBBCCCCDDDD
uid           [ultimate] Alice Dev <adev@kernel.org>
ssb   cv25519 2022-12-20 [E] [expires: 2024-12-19]
ssb   ed25519 2022-12-20 [S]

이전 GnuPG가 남긴 ~/.gnupg/secring.gpg에도 private key가 들어 있을 수 있으므로 제거한다. private-keys-v1.d가 없다면 아직 GnuPG v1의 legacy secring.gpg를 쓰는 상태다. passphrase 변경이나 subkey 추가 같은 key 변경을 수행하면 새 형식으로 자동 변환되며, 변환과 백업 확인 뒤 obsolete secring.gpg를 삭제한다.

smartcard의 보안 경계와 장치 선택

354-416

Certify key를 offline으로 옮겨도 [S]와 [E] subkey가 homedir에 남아 있으면 passphrase를 아는 공격자가 서명을 위조하거나 통신을 복호화할 수 있다. GnuPG operation 때 private key가 system memory에 올라오므로 Meltdown과 Spectre 같은 고급 공격으로 memory에서 탈취될 가능성도 고려해야 한다.

smartcard는 private key를 chip 안에 저장하고 암호 연산을 card 자체에서 수행한다. key 내용이 card 밖으로 나오지 않으므로 연결된 computer OS가 private key 자체를 읽을 수 없다. mount 중인 암호화 외장 media에서는 OS가 private key를 읽을 수 있다는 점과 근본적으로 다르다. 암호화 media는 smartcard의 대체재가 아니다.

장치특징
Nitrokey StartFSI Japan Gnuk 기반 open hardware와 Free Software. 저렴하지만 tamper 및 일부 side-channel 저항 기능은 적음
Nitrokey 3Start와 유사하지만 더 강한 tamper 저항, 다양한 USB form factor, ED25519와 NISTP ECC 지원
Yubikey 5proprietary hardware/software, 유사 기능의 Nitrokey보다 저렴할 수 있으며 ED25519와 NISTP ECC 지원

가격, 지역 배송 가능성, open 또는 proprietary hardware에 대한 요구를 기준으로 선택한다. MAINTAINERS에 등재되었거나 kernel.org 계정이 있는 개발자는 Linux Foundation이 제공하는 무료 Nitrokey Start 대상이 될 수 있다.

private key가 노출되는 범위
저장 방식OS가 key를 읽을 수 있는 때용도
01 LUKS 외장 mediamount 후 GnuPG가 private key를 읽음Certify 작업과 복구
02 smartcardprivate key는 chip 밖으로 나오지 않음서명·복호화 operation
03 paperkey사람이 복원 절차를 수행할 때만최후 재해 복구

암호화 backup과 smartcard는 목적이 다르다. backup은 복구 가능성을, smartcard는 일상 operation 중 key 비노출을 제공한다.

smartcard 설정과 subkey 이전

418-532

현대 Linux workstation에서는 smartcard USB 장치를 연결하면 보통 바로 인식된다. gpg --card-status로 card 세부 정보가 표시되는지 확인한다. 인식 실패 원인 분석은 장치와 배포판별 지원 문서를 따른다.

$ gpg --card-status

$ gpg --card-edit
[...omitted...]
gpg/card> admin
Admin commands are allowed
gpg/card> passwd

card menu에서 user PIN(1), Admin PIN(3), Reset Code(4)를 설정하고 안전한 장소에 기록한다. 특히 자주 쓰지 않는 Admin PIN과 card를 완전히 초기화할 수 있는 Reset Code를 잊지 않게 보관해야 한다. 이름, 성별, login data 같은 값은 필수가 아니며 card 분실 시 불필요한 개인정보를 노출할 수 있다. PIN이라는 이름과 달리 숫자만 사용할 필요는 없다.

일부 장치는 passphrase를 바꾸기 전에 subkey를 먼저 장치로 옮겨야 할 수 있으므로 제조사 문서를 확인한다. card menu에서 q로 나가 변경을 저장한 뒤, PGP passphrase와 card Admin PIN을 준비하고 key edit menu를 연다.

$ gpg --edit-key [fpr]

Secret subkeys are available.

pub  ed25519/AAAABBBBCCCCDDDD
     created: 2022-12-20  expires: 2024-12-19  usage: SC
     trust: ultimate      validity: ultimate
ssb  cv25519/1111222233334444
     created: 2022-12-20  expires: never       usage: E
ssb  ed25519/5555666677778888
     created: 2017-12-07  expires: never       usage: S
[ultimate] (1). Alice Dev <adev@kernel.org>

gpg>

gpg> menu에서 key 1은 첫 번째 [E] subkey를 선택한다. 출력의 ssb* 별표가 현재 선택된 key를 나타내며 같은 명령을 다시 입력하면 선택이 해제되는 toggle이다. keytocard를 실행하고 Encryption key slot 2를 선택한다. PGP passphrase와 Admin PIN 입력 뒤 오류가 없으면 이전된 것이다.

gpg> key 1
gpg> keytocard
Please select where to store the key:
   (2) Encryption key
Your selection? 2

다음 key를 옮기기 전에 key 1을 다시 입력해 [E] 선택을 반드시 해제하고 key 2로 [S]를 선택한다. [S] key를 Signature와 Authentication에 모두 쓸 수 있어도 이 절차에서는 Signature slot 1에 넣는다.

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

gpg> q
Save changes? (y/N) y

변경을 저장하면 card로 옮긴 private subkey가 homedir에서 삭제된다. 교체 card에 다시 넣어야 할 때는 앞에서 만든 검증된 offline backup을 사용한다.

smartcard 이전 결과 검증

534-571

gpg --list-secret-keys를 다시 실행하면 Certify key는 sec#, card의 subkey는 ssb>로 표시된다. >는 private subkey가 smartcard에만 있다는 뜻이다.

$ gpg --list-secret-keys
sec#  ed25519 2022-12-20 [SC] [expires: 2024-12-19]
      000000000000000000000000AAAABBBBCCCCDDDD
uid           [ultimate] Alice Dev <adev@kernel.org>
ssb>  cv25519 2022-12-20 [E] [expires: 2024-12-19]
ssb>  ed25519 2022-12-20 [S]

private-keys-v1.d의 .key 파일은 실제 key가 아니라 card 위치를 가리키는 stub으로 바뀐다. strings 출력에 shadowed-private-key가 있으면 실제 내용은 smartcard에 있다는 뜻이다.

$ cd ~/.gnupg/private-keys-v1.d
$ strings *.key | grep 'private-key'

실제 서명으로 card 동작을 시험한다. 첫 명령에서 smartcard PIN을 요구하고, verify 결과에 Good signature가 나와야 한다.

$ echo "Hello world" | gpg --clearsign > /tmp/test.asc
$ gpg --verify /tmp/test.asc

offline Certify key 운용

573-635

Certify 작업을 시작할 때 암호화된 offline storage를 mount하고 GNUPGHOME을 그 백업 디렉터리로 지정한다. gpg --list-secret-keys에서 sec#가 아니라 sec가 표시되어 실제 Certify private key를 읽고 있는지 확인한다.

$ export GNUPGHOME=/media/disk/foo/gnupg-backup
$ gpg --list-secret-keys

Certify key의 기본 만료 기간은 생성 후 2년이다. 키가 무기한 유효하지 않게 하는 보안 목적과, 사용하지 않는 key가 keyserver에서 결국 사라지게 하는 목적이 있다. 현재 날짜에서 1년 연장하거나 기억하기 쉬운 특정 날짜를 지정할 수 있다.

$ gpg --quick-set-expire [fpr] 1y
$ gpg --quick-set-expire [fpr] 2038-07-01
$ gpg --send-key [fpr]

변경한 public key를 keyserver로 다시 보낸다. offline storage에서 변경한 내용을 평소 working keyring으로 export/import한 뒤 GNUPGHOME을 해제한다.

$ gpg --export | gpg --homedir ~/.gnupg --import
$ unset GNUPGHOME

원격 system에서 tag나 commit을 서명해야 한다면 gpg-agent를 SSH로 forwarding할 수 있다. 원격 sshd 설정을 수정할 수 있을 때 더 원활하며, 구체적인 socket forwarding 절차는 GnuPG wiki를 따른다.

Git 설정과 signed tag

637-716

Git 저장소를 clone하면 tag, commit, branch를 포함한 전체 history가 로컬에 생긴다. 여러 곳에 복제된 linux.git 가운데 어떤 사본이 악의적으로 바뀌지 않았는지, commit Author에 자신의 이름을 넣은 코드가 실제 자신이 만든 것인지 확인하려면 별도 암호학적 증거가 필요하다.

signed tag는 그 tag가 가리키는 repository 내용이 tag를 만든 개발자의 workstation과 동일하다는 무결성 기준점을 제공한다. signed commit은 공격자가 private key 없이 개발자를 사칭하기 어렵게 한다.

secret key가 하나뿐이면 기본 key로 선택된다. 여러 key가 있다면 Git이 사용할 fingerprint를 전역 설정한다.

$ git config --global user.signingKey [fpr]

$ git tag -s [tagname]

다른 개발자가 pull할 repository의 변조 여부를 확인할 수 있도록 모든 Git tag에 서명하는 것을 권장한다. tag는 git verify-tag로 직접 검증한다. 다른 fork에서 tag를 pull하면 Git은 merge 과정에서 tip의 signature를 자동 검증하고 결과를 merge message에 넣는다.

$ git verify-tag [tagname]
$ git pull [url] tags/sometag

Merge tag 'sometag' of [url]

[Tag message]

# gpg: Signature made [...]
# gpg: Good signature from [...]

다른 사람의 tag를 검증하려면 먼저 그 개발자의 public key를 가져와 identity를 검증해야 한다. annotated tag를 항상 서명하도록 강제하려면 tag.forceSignAnnotated를 설정한다.

$ git config --global tag.forceSignAnnotated true

signed commit의 용도와 한계

717-763

커널 개발 workflow에서는 commit을 patch로 변환해 mailing list로 보내는데, 이 변환은 Git commit signature를 보존하지 않는다. upstream을 기준으로 rebase해도 기존 commit object가 새로 생성되어 서명이 사라진다. 이 때문에 많은 커널 개발자는 commit signing을 필수로 보지 않고 외부 저장소의 signed commit도 workflow 증거로 사용하지 않는다.

그럼에도 kernel.org, infradead.org, ozlabs.org 같은 공개 hosting에 working tree를 제공한다면 모든 commit에 서명할 것을 권장한다. 훗날 code provenance와 forensic 분석이 필요할 때 외부 tree의 signature도 증거가 되며, system 재설치 후 다시 clone한 저장소 무결성을 확인할 수 있고, 다른 사람이 cherry-pick 전에 commit을 빠르게 검증할 수 있다.

# 한 commit 서명: 소문자 -s와 다른 옵션이므로 대문자 -S
$ git commit -S

# 모든 commit 자동 서명
$ git config --global commit.gpgSign true

자동 commit signing을 켜기 전에 gpg-agent의 passphrase cache와 smartcard 동작을 먼저 구성한다.

patch attestation과 patatt

764-823

커널 mailing list로 보내는 patch도 PGP key로 서명할 수 있다. PGP-MIME이나 PGP-inline은 일반 code review와 patch 적용을 방해할 수 있으므로, kernel.org가 만든 patatt를 이용해 DKIM과 비슷한 cryptographic attestation을 message header에 넣는다.

B4로 patch를 전송한다면 patatt가 이미 설치되어 workflow에 통합되어 있다. 그 밖에는 배포판 package를 우선 확인하고 필요하면 pip install patatt로 설치한다. Git user.signingKey를 이미 설정했다면 추가 key 설정 없이 repository에 git-send-email hook을 설치할 수 있다.

$ pip install patatt
$ patatt install-hook

이후 git send-email로 보내는 patch에는 자동으로 cryptographic signature가 붙는다. b4로 patch를 가져와 적용하면 발견한 DKIM과 patatt signature를 자동으로 검증한다.

$ b4 am 20220720205013.890942-1-broonie@kernel.org
[...]
Checking attestation on all messages, may take a moment...
---
  [PATCH v1 1/3] kselftest/arm64: Correct buffer allocation for SVE Z registers
  [PATCH v1 2/3] arm64/sve: Document our actual ABI for clearing registers on syscall
  [PATCH v1 3/3] kselftest/arm64: Enforce actual ABI for SVE syscalls
  ---
  Signed: openpgp/broonie@kernel.org
  Signed: DKIM/kernel.org

patatt와 b4는 계속 개발되고 있으므로 현재 project 문서에서 새 기능과 변경된 사용법을 확인한다.

WKD와 DANE로 개발자 key 찾기

825-867

서명이 수학적으로 유효하다는 사실만으로 그 key가 실제 커널 개발자의 것임을 증명할 수는 없다. 공격자가 같은 이름과 이메일로 새 key를 만들 수 있으므로, public key 획득 경로와 identity binding을 검증해야 한다.

다른 개발자 public key collection이 충분하지 않다면 GnuPG의 자동 발견을 이용할 수 있다. WKD와 DANE는 각각 TLS와 DNSSEC이라는 위임된 신뢰 기술을 통해 public key를 찾고 가져온다.

# ~/.gnupg/gpg.conf
auto-key-locate wkd,dane,local
auto-key-retrieve

DANE는 public key를 DNS에 게시하고 DNSSEC-signed zone으로 보호한다. WKD는 HTTPS 조회를 사용한다. GnuPG는 자동으로 가져온 key를 local keyring에 추가하기 전에 DANE에서는 DNSSEC을, WKD에서는 TLS certificate를 검증한다.

kernel.org는 계정이 있는 모든 개발자의 WKD를 게시한다. 설정 뒤 Linus Torvalds와 Greg Kroah-Hartman의 key를 이메일 주소로 찾을 수 있다. kernel.org 계정이 있다면 자신의 key에 kernel.org UID를 추가해 다른 개발자의 WKD 검색을 돕는다.

$ gpg --locate-keys torvalds@kernel.org gregkh@kernel.org

Web of Trust와 TOFU

869-897

PGP의 Web of Trust는 HTTPS/TLS의 중앙 Certification Authority를 대신하려는 분산 trust delegation 방식이다. software vendor가 신뢰할 인증자를 정하는 대신 각 사용자가 누구의 인증을 신뢰할지 결정한다.

Web of Trust의 실제 운용은 이해하기 어렵다. GnuPG 2.2 이상은 대안으로 Trust on First Use를 제공한다. SSH가 첫 연결의 host key fingerprint를 기억하고 이후 변경을 경고하듯, TOFU는 처음 가져온 identity-key 연결을 기록한다.

나중에 같은 identity를 가진 다른 key가 나타나면 기존 key와 새 key를 모두 검증 대상으로 표시하고 사용자가 어느 것을 유지할지 판단하게 한다. 문서는 GnuPG v2의 새 기본값인 TOFU+PGP 결합 trust model을 권장한다.

# ~/.gnupg/gpg.conf
trust-model tofu+pgp

kernel.org 개발자 keyring

898-911

기존 복제형 keyserver network가 최근 수년 동안 대부분 제대로 동작하지 않게 되자 kernel.org는 개발자 public key를 모은 Git repository를 운영한다. 이 저장소를 public key source로 구성하는 전체 절차는 Kernel developer PGP Keyring 문서에 있다.

커널 개발자라면 다른 개발자가 자신의 서명을 검증할 수 있도록 해당 keyring에 public key를 제출하는 것을 검토한다.