# Create Smartcard-based PGP Key

### Requirements

- OpenPGP-compatible Hardware Security Key (Example: YubiKey 5(C))
- GnuPG CLI installed
- Smartcard-related Drivers installed

### Key Setup

#### Prepare Card

##### Ensure Card is recognized

```powershell
gpg --card-status
```

The Output should look something like this

```powershell
Reader ...........: Yubico YubiKey OTP FIDO CCID 0
Application ID ...: D2760001240100000006379790790000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
```

##### Configure Card

```powershell
gpg --card-edit
```

<p class="callout info">**If Command is preceeded by `gpg/card>`, you have to be in card edit Mode using `gpg --card-edit`**</p>

**Configure Pin**

<p class="callout info">**For YubiKeys, the default Pin is `123456` and default Puk is `4`**</p>

```
gpg/card> admin
gpg/card> passwd
```

- Press `1` to edit User-Pin
- Press `3` to edit Admin Pin
- Press `q` to quit

**Set Algorithm to ECC**

```
gpg/card> key-attr
```

Select Curve 25519 Slot

```
(1) RSA
(2) ECC

```

`(1) Curve 25519 <em>standard</em>(4) NIST P-384(6) Brainpool P-256`

```
```

- *ED25519* for Auth/Sign
- *CV25519* for Encryption

#### Generate Key

```
gpg/card> generate
```

<p class="callout info">**If asked to replace existing keys, confirm with `y` only if you intend to overwrite what's currently on the card**</p>

Follow the prompts:

- **Make off-card backup of encryption key?** → `Y` (this is the only key material that can be backed up — Signature and Authentication keys never leave the card)
- **Key validity period** → e.g. `2y` (avoid `0`/unlimited, to enforce periodic rotation)
- **Real name** → your name
- **Email address** → your primary email (can be extended later, see [Add additional User-IDs](#add-additional-user-ids))
- **Comment** → leave empty

GnuPG will generate all three subkeys (Signature, Encryption, Authentication) directly on the card.

<p class="callout info">**Key generation requires entropy — moving the mouse or typing in another window speeds this up**</p>

#### Verify

```powershell
gpg --card-status
```

Signature key, Encryption key and Authentication key should now show fingerprints instead of `[none]`.

```powershell
gpg --list-secret-keys --keyid-format=long
```

Secret keys should be marked `sec>` / `ssb>` — the `>` indicates the private key material resides on the card, not on disk.

#### Backup

**Export Public Key**

```powershell
gpg --armor --export <KEY-ID> > public-key.asc
```

**Revocation Certificate**

Automatically created during key generation, located at:

```
%APPDATA%\gnupg\openpgp-revocs.d\<KEY-ID>.rev
```

<p class="callout warning">**Store this file separately from the YubiKey (e.g. encrypted USB drive). Without it, a lost/broken card cannot be revoked.**</p>

**Encryption Key Backup**

Located at:

```
%APPDATA%\gnupg\private-keys-v1.d\
```

<p class="callout warning">**Unlike the other two keys, this file contains actual private key material (the Encryption subkey). Store it encrypted and separately — do not leave it unprotected on disk.**</p>

### Add Additional User-IDs

Additional identities (e.g. further email addresses) can be attached to the existing key without regenerating anything on the card.

```powershell
gpg --edit-key <KEY-ID>
```

```
gpg> adduid
```

- **Real name** → e.g. same as before
- **Email address** → additional address
- **Comment** → leave empty

Confirm with `O` (Okay), then:

```
gpg> save
```

Re-export the updated Public Key and re-upload it wherever the old one was registered (e.g. Forgejo):

```powershell
gpg --armor --export <KEY-ID> > public-key-v2.asc
```

### Git Integration

```powershell
git config --global user.signingkey <KEY-ID>
git config --global commit.gpgsign true
git config --global tag.gpgsign true
```

<p class="callout warning">**Git for Windows ships its own bundled `gpg.exe` (MSYS2), which uses a separate `GNUPGHOME` and will not see the card. Point Git explicitly to the system GnuPG installation:**</p>

```powershell
where.exe gpg
git config --global gpg.program "C:\Program Files (x86)\GnuPG\bin\gpg.exe"
```

**Verify**

```powershell
git commit --allow-empty -m "Test signed commit"
git log --show-signature -1
```

Expected output includes `gpg: Good signature`.