# Git GPG 密钥生成与迁移


在 GitHub 上，那个小小的绿色 "Verified" 徽章不仅仅是装饰，它是你代码提交的数字签名，代表着专业、安全与可信。它向世界宣告：**“这个提交确实是我本人发出的，并且内容未经篡改。”**

但当你换了一台新电脑，或者想在公司的设备和个人笔记本之间同步工作时，问题来了：如何让这个“身份徽章”跟着你走？

别担心！这篇指南将带你从零开始，完成两大任务：

1. **生成你的第一个 GPG 密钥**，并与 Git 和 GitHub 完美集成。
2. **安全地将它迁移到任何新设备**，实现无缝的跨设备签名。

让我们开始吧！

---

## **Part 1：奠定基石 —— 生成你的 GPG 密钥**

要拥有签名，首先你得有一支“笔”——也就是你的 GPG 密钥对。

### **第一步：安装 GPG 工具**

如果你的电脑还没安装 GPG，这是第一步。

- **macOS**: 使用 Homebrew 是最简单的方式。

  ```bash
  brew install gnupg
  ```

- **Windows**:

  下载并安装 [Gpg4win](https://www.gpg4win.org/)，它会提供你所需的一切。

  或者使用 scoop `scoop install gpg4win`

- **Linux (Debian/Ubuntu)**: 通常系统自带，若没有则运行：

  ```bash
  sudo apt-get install gnupg
  ```

### **第二步：启动密钥生成向导**

打开你的终端（或 Windows 上的 Git Bash），运行以下命令：

```bash
gpg --full-generate-key
```

接下来，你将进入一个交互式向导。别怕，我们一步步来：

1. **选择密钥类型**: 直接按回车，选择默认的 `(1) RSA and RSA`。
2. **选择密钥长度**: 输入 `4096`。这是当前推荐的最安全长度。
3. **选择有效期**: 输入 `0` 代表永不过期，或者输入 `1y` 代表一年。对于个人使用，`0` 是最方便的选择。
4. **确认信息**: 输入 `y` 并回车。

### **第三步：填写你的身份信息 (关键！)**

现在，你需要提供你的用户 ID。

- **Real name**: 输入你的名字或昵称 (推荐与 `git config user.name` 保持一致)。
- **Email address**: **至关重要！** 此处必须填写你已在 GitHub 上验证过的、并且和 `git config user.email` 设置完全相同的邮箱地址。这是 GitHub 匹配你身份的唯一依据。
- **Comment**: 可选，可以直接回车跳过。
- **确认并创建**: 检查信息无误后，输入 `O` (Okay) 并回车。

最后，系统会提示你为这个密钥设置一个**密码 (Passphrase)**。这个密码是用来保护你的私钥的，每次签名时都需要输入。请务必设置一个强密码并牢记它！

---

## **Part 2：关联身份 —— 连接 Git 与 GitHub**

有了密钥，现在要让全世界知道它属于你。

### **第一步：找到你的 GPG 密钥 ID**

运行以下命令，列出你刚刚创建的密钥：

```bash
gpg --list-secret-keys --keyid-format=long
```

你会看到类似这样的输出：

```plaintext
sec   rsa4096/3AA5C34371567BD2 2023-10-27 [SC]
      946A6E2B1A9E7F094593C2A33AA5C34371567BD2
uid                 [ultimate] Your Name <your_email@example.com>
```

`sec` 那一行斜杠 `/` 后面的那一长串字符 `3AA5C34371567BD2` 就是你的**GPG 密钥 ID**。复制它！

### **第二步：配置本地 Git**

告诉 Git 你的“签名笔”是哪一支：

```bash
# 将 YOUR_KEY_ID 替换成你自己的密钥 ID
git config --global user.signingkey YOUR_KEY_ID

# 推荐：让每次提交都自动签名，一劳永逸！
git config --global commit.gpgsign true
```

### **第三步：将公钥上传到 GitHub**

1. 导出你的公钥（可以被公开的部分）：

   ```bash
   # 将 YOUR_KEY_ID 替换成你的密钥 ID
   gpg --armor --export YOUR_KEY_ID
   ```

2. 复制终端输出的、从 `-----BEGIN PGP PUBLIC KEY BLOCK-----` 到 `-----END PGP PUBLIC KEY BLOCK-----` 的所有内容。
3. 登录 GitHub，进入 **Settings** > **SSH and GPG keys**。
4. 点击 **New GPG key**，将复制的公钥粘贴进去，然后点击 **Add GPG key**。

✅ **大功告成！** 现在去提交一个 commit 并 push 到 GitHub，你将看到那个令人愉悦的 "Verified" 徽章！

---

## **Part 3：身份迁移 —— 让你的密钥在新设备上安家**

这是本文的核心：当你换了新电脑，如何继续使用同一个 GPG 身份？

⚠️ **安全警告**：这个过程涉及你的**私钥**，它是你数字身份的核心。请务必通过安全的方式传输，**绝对不要**使用邮件或公开的网盘！

### **第一步：在【源设备】上导出密钥**

在你的旧电脑上，我们需要导出公钥和私钥。

1. **导出公钥** (公开部分)：

   ```bash
   gpg --armor --export YOUR_KEY_ID > public.asc
   ```

2. **导出私钥** (机密部分)：

   ```bash
   gpg --armor --export-secret-keys YOUR_KEY_ID > private.asc
   ```

   执行此命令时，你需要输入 GPG 密钥的密码。

现在，你有了 `public.asc` 和 `private.asc` 两个文件。

### **第二步：安全地传输文件**

将这两个 `.asc` 文件安全地从旧设备拷贝到新设备。推荐方式：

- **加密的 U 盘** (最简单直接)。
- **`scp` 命令** (如果你熟悉 SSH)。
- **端到端加密的同步工具** (如 Keybase)。

### **第三步：在【目标设备】上导入密钥**

在新电脑上，打开终端，进入存放这两个文件的目录。

1. **导入公钥**:

   ```bash
   gpg --import public.asc
   ```

2. **导入私钥**:

   ```bash
   gpg --import private.asc
   ```

### **第四步：信任这个密钥 (关键的收尾工作！)**

仅仅导入还不够，你必须在新设备上明确“信任”这个密钥，否则 Git 可能会拒绝使用它。

1. 进入密钥编辑模式：

   ```bash
   gpg --edit-key YOUR_KEY_ID
   ```

2. 在 `gpg>` 提示符后，输入 `trust` 并回车。
3. 选择最高信任级别，输入 `5` (I trust ultimately) 并回车。
4. 确认选择，输入 `y` 并回车。
5. 最后，输入 `save` 保存并退出。

### **第五步：完成配置并清理**

1. **在新设备上配置 Git**: 别忘了重复 Part 2 的第二步，告诉新设备的 Git 使用这个密钥。

   ```bash
   git config --global user.signingkey YOUR_KEY_ID
   git config --global commit.gpgsign true
   ```

2. **安全清理**: **立即删除**用于传输的 `public.asc` 和 `private.asc` 文件！不要让你的私钥副本散落在任何地方。

---

## **故障排除**

1. Windows 如果出现无法签名的情况，可以尝试设置 `git config --global gpg.program <gpg 路径>`
2. 出现 `gpg: signing failed: Inappropriate ioctl for device` 错误： 增加环境变量 `export GPG_TTY=$(tty)`，fish 将 `set -x GPG_TTY (tty)` 添加到 `~/.config/fish/config.fish` 中

## 附录：记住 GPG 密钥

可以通过以下命令记住你的 GPG 密钥，避免重复输入密码。

```shell
pinentry_line=""
if [[ -n "$DISPLAY" || -n "$WAYLAND_DISPLAY" ]]; then
	pinentry_line="pinentry-program /usr/sbin/pinentry-qt"
else
	pinentry_line="pinentry-program /usr/sbin/pinentry-tty"
fi

printf "$pinentry_line
default-cache-ttl 25920000
max-cache-ttl 25920000" | tee ~/.gnupg/gpg-agent.conf
gpg-connect-agent reloadagent /bye
```


---

> 作者: Nite  
> URL: https://www.nite07.com/zh-cn/posts/gpg-generate/  

