SSH 密钥
1. SSH 密钥概述
1.1 什么是 SSH 密钥
SSH(Secure Shell)密钥是一对加密密钥,用于在不安全的网络中安全地进行身份验证:
- 公钥(Public Key):可以公开分享,存储在服务器上
- 私钥(Private Key):必须严格保密,存储在本地计算机上
1.2 为什么使用 SSH 密钥
| 特性 | 密码认证 | SSH 密钥认证 |
|---|---|---|
| 安全性 | 较低(可能被暴力破解) | 高(基于加密算法) |
| 便利性 | 每次需要输入密码 | 一次配置,免密登录 |
| 自动化 | 不支持脚本自动化 | 支持自动化脚本 |
| 管理复杂度 | 简单 | 需要密钥管理 |
1.3 工作原理
┌─────────────────┐ ┌─────────────────┐
│ 客户端 │ │ 服务器 │
│ (持有私钥) │◄──── SSH 连接 ────►│ (持有公钥) │
└─────────────────┘ └─────────────────┘
│ │
│ 1. 客户端发送连接请求 │
│─────────────────────────────────────>│
│ │
│ 2. 服务器发送随机挑战(Challenge) │
│<─────────────────────────────────────│
│ │
│ 3. 客户端用私钥签名挑战 │
│─────────────────────────────────────>│
│ │
│ 4. 服务器用公钥验证签名 │
│ [验证成功 → 允许登录] │2. 密钥类型详解
2.1 RSA(Rivest-Shamir-Adleman)
| 属性 | 说明 |
|---|---|
| 算法类型 | 非对称加密 |
| 安全性基础 | 大整数分解的数学难题 |
| 推荐密钥长度 | 4096 位(最低 2048 位) |
| 兼容性 | 最广泛支持 |
| 性能 | 生成和验证较慢 |
| 适用场景 | 通用场景,兼容性要求高的环境 |
bash
# RSA 密钥生成命令
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"2.2 Ed25519
| 属性 | 说明 |
|---|---|
| 算法类型 | 基于椭圆曲线的 EdDSA |
| 安全性基础 | 椭圆曲线离散对数问题 |
| 推荐密钥长度 | 固定 256 位 |
| 兼容性 | OpenSSH 6.5+,较新系统 |
| 性能 | 生成和验证速度快 |
| 适用场景 | 现代系统的首选,性能敏感场景 |
bash
# Ed25519 密钥生成命令
ssh-keygen -t ed25519 -C "your_email@example.com"2.3 ECDSA(Elliptic Curve Digital Signature Algorithm)
| 属性 | 说明 |
|---|---|
| 算法类型 | 基于椭圆曲线的 DSA |
| 安全性基础 | 椭圆曲线离散对数问题 |
| 推荐密钥长度 | 256、384 或 521 位 |
| 兼容性 | OpenSSH 5.7+ |
| 性能 | 较快 |
| 适用场景 | 需要比 RSA 更快但 Ed25519 不支持的环境 |
bash
# ECDSA 密钥生成命令
ssh-keygen -t ecdsa -b 521 -C "your_email@example.com"2.4 DSA(Digital Signature Algorithm)
| 属性 | 说明 |
|---|---|
| 状态 | ⚠️ 已弃用,不推荐使用 |
| 原因 | 密钥长度固定为 1024 位,安全性不足 |
| 兼容性 | 旧系统可能仍支持 |
2.5 密钥类型对比总结
| 密钥类型 | 密钥长度 | 安全性 | 性能 | 兼容性 | 推荐度 |
|---|---|---|---|---|---|
| Ed25519 | 256 位 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| RSA | 2048-4096 位 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| ECDSA | 256-521 位 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| DSA | 1024 位 | ⭐⭐ | ⭐⭐ | ⭐⭐ | ❌ 不推荐 |
💡 推荐选择:
- 新项目/现代系统:优先使用 Ed25519
- 兼容性要求高的旧系统:使用 RSA 4096
3. 生成 SSH 密钥
3.1 检查现有密钥
在生成新密钥之前,先检查是否已有 SSH 密钥:
bash
# 列出 ~/.ssh 目录下的密钥文件
ls -la ~/.ssh/常见的密钥文件:
id_rsa/id_rsa.pub— RSA 密钥对id_ed25519/id_ed25519.pub— Ed25519 密钥对id_ecdsa/id_ecdsa.pub— ECDSA 密钥对known_hosts— 已知主机列表config— SSH 配置文件
3.2 生成 Ed25519 密钥(推荐)
bash
ssh-keygen -t ed25519 -C "your_email@example.com"交互过程示例:
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/username/.ssh/id_ed25519):
↳ 按 Enter 使用默认路径,或输入自定义路径
Enter passphrase (empty for no passphrase):
↳ 输入密码短语(推荐设置,增强安全性)
↳ 直接按 Enter 则不设置密码
Enter same passphrase again:
↳ 再次确认密码短语
Your identification has been saved in /home/username/.ssh/id_ed25519
Your public key has been saved in /home/username/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:AbCdEfGhIjKlMnOpQrStUvWxYz1234567890abcdef your_email@example.com
The key's randomart image is:
+--[ED25519 256]--+
| .o. |
| . +.. |
| o +. |
| . + .. |
| . = + S |
| o * = . |
| . O + |
| + X . |
| =oE. |
+----[SHA256]-----+3.3 生成 RSA 密钥(兼容性场景)
bash
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"参数说明:
-t rsa:指定密钥类型为 RSA-b 4096:指定密钥位数为 4096(安全性更高)-C "your_email@example.com":添加注释(通常用邮箱)
3.4 生成带自定义文件名的密钥
bash
# 为不同服务生成不同的密钥
ssh-keygen -t ed25519 -C "github" -f ~/.ssh/id_ed25519_github
ssh-keygen -t ed25519 -C "gitlab" -f ~/.ssh/id_ed25519_gitlab
ssh-keygen -t ed25519 -C "work-server" -f ~/.ssh/id_ed25519_work3.5 生成密钥时的最佳实践
| 建议 | 说明 |
|---|---|
| ✅ 使用强密码短语 | 即使私钥泄露,也需要密码才能使用 |
| ✅ 为不同服务使用不同密钥 | 隔离风险,便于管理 |
| ✅ 使用描述性文件名 | 如 id_ed25519_github |
| ✅ 使用有意义的注释 | 便于识别密钥用途 |
| ❌ 不要共享私钥 | 私钥永远不应该离开你的设备 |
| ❌ 不要通过邮件/聊天发送私钥 | 使用安全的密钥分发方式 |
4. 配置 SSH 密钥
4.1 启动 SSH Agent
SSH Agent 可以在内存中缓存私钥,避免每次使用都输入密码短语。
macOS
bash
# 启动 ssh-agent 并添加环境变量
eval "$(ssh-agent -s)"
# 或者使用 macOS 自带的钥匙串(推荐)
ssh-add --apple-use-keychain ~/.ssh/id_ed25519Linux
bash
# 启动 ssh-agent
eval "$(ssh-agent -s)"
# 添加私钥到 agent
ssh-add ~/.ssh/id_ed25519
# 添加时输入密码短语后,后续使用无需再次输入Windows (Git Bash / WSL)
bash
# 启动 ssh-agent
exec ssh-agent bash
# 或者
eval $(ssh-agent -s)
# 添加私钥
ssh-add ~/.ssh/id_ed255194.2 配置 SSH Config 文件
创建或编辑 ~/.ssh/config 文件,管理多个密钥和主机:
bash
nano ~/.ssh/config示例配置:
ssh-config
# 默认配置
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 60
ServerAliveCountMax 3
# GitHub 配置
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
IdentitiesOnly yes
# GitLab 配置
Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/id_ed25519_gitlab
IdentitiesOnly yes
# 公司服务器配置
Host work-server
HostName 192.168.1.100
User admin
Port 2222
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
# 跳板机配置(通过跳板机连接内网服务器)
Host jump-server
HostName jump.company.com
User admin
IdentityFile ~/.ssh/id_ed25519_work
Host internal-server
HostName 10.0.0.50
User dev
ProxyJump jump-server
IdentityFile ~/.ssh/id_ed25519_work配置项说明:
| 配置项 | 说明 |
|---|---|
Host | 别名,用于 ssh 别名 连接 |
HostName | 实际主机地址(IP 或域名) |
User | 登录用户名 |
Port | SSH 端口(默认 22) |
IdentityFile | 使用的私钥文件路径 |
IdentitiesOnly | 只使用指定的密钥,不尝试其他密钥 |
ProxyJump | 跳板机配置 |
ServerAliveInterval | 保持连接的心跳间隔(秒) |
AddKeysToAgent | 自动将密钥添加到 ssh-agent |
4.3 设置正确的文件权限
SSH 对密钥文件权限有严格要求:
bash
# 设置 .ssh 目录权限(所有者读写执行)
chmod 700 ~/.ssh
# 设置私钥权限(所有者只读)
chmod 600 ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_rsa
# 设置公钥权限(所有者读写)
chmod 644 ~/.ssh/id_ed25519.pub
chmod 644 ~/.ssh/id_rsa.pub
# 设置 config 文件权限
chmod 600 ~/.ssh/config
# 设置 known_hosts 权限
chmod 644 ~/.ssh/known_hosts权限要求总结:
| 文件/目录 | 权限 | 数字表示 |
|---|---|---|
~/.ssh | drwx------ | 700 |
| 私钥文件 | -rw------- | 600 |
| 公钥文件 | -rw-r--r-- | 644 |
config | -rw------- | 600 |
known_hosts | -rw-r--r-- | 644 |
5. 使用 SSH 密钥
5.1 将公钥添加到远程服务器
方法一:使用 ssh-copy-id(推荐)
bash
# 将公钥复制到远程服务器
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@remote_host
# 指定端口
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 2222 user@remote_host方法二:手动添加
bash
# 在本地查看公钥内容
cat ~/.ssh/id_ed25519.pub
# 输出示例:
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDIhz2GK/XCUj4i6Q5yQJNL1MXMY0RxzPV2QrBqfHrDq your_email@example.com
# 登录到远程服务器
ssh user@remote_host
# 在远程服务器上创建 .ssh 目录并设置权限
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# 将公钥内容追加到 authorized_keys
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDIhz2GK/XCUj4i6Q5yQJNL1MXMY0RxzPV2QrBqfHrDq your_email@example.com" >> ~/.ssh/authorized_keys
# 设置 authorized_keys 权限
chmod 600 ~/.ssh/authorized_keys5.2 将公钥添加到 Git 托管服务
GitHub
- 复制公钥内容:
bash
cat ~/.ssh/id_ed25519.pub | pbcopy # macOS
cat ~/.ssh/id_ed25519.pub | xclip -selection clipboard # Linux
cat ~/.ssh/id_ed25519.pub | clip # Windows Git Bash- 登录 GitHub → Settings → SSH and GPG keys → New SSH key
- 粘贴公钥内容,添加标题(如 "MacBook Pro")
- 选择密钥类型(Authentication Key 或 Signing Key)
- 点击 "Add SSH key"
GitLab
- 登录 GitLab → User Settings → SSH Keys
- 粘贴公钥内容
- 设置过期时间(可选)
- 点击 "Add key"
Gitee / 码云
- 登录 Gitee → 设置 → SSH 公钥
- 粘贴公钥内容
- 输入密码确认
- 点击 "确定"
5.3 测试 SSH 连接
bash
# 测试 GitHub 连接
ssh -T git@github.com
# 预期输出:
# Hi username! You've successfully authenticated, but GitHub does not provide shell access.
# 测试 GitLab 连接
ssh -T git@gitlab.com
# 测试自定义服务器
ssh -T user@remote_host
# 使用详细模式调试
ssh -v user@remote_host
ssh -vv user@remote_host # 更详细
ssh -vvv user@remote_host # 最详细5.4 使用 SSH 密钥进行 Git 操作
bash
# 克隆仓库(SSH 方式)
git clone git@github.com:username/repository.git
# 查看远程 URL
git remote -v
# 将 HTTPS 远程 URL 改为 SSH
git remote set-url origin git@github.com:username/repository.git
# 配置 Git 使用 SSH 签名提交(Git 2.34+)
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
git config --global gpg.format ssh6. 密钥管理与安全
6.1 查看密钥信息
bash
# 查看公钥内容
cat ~/.ssh/id_ed25519.pub
# 查看私钥指纹(不暴露私钥内容)
ssh-keygen -lf ~/.ssh/id_ed25519.pub
# 查看私钥的指纹和随机艺术图
ssh-keygen -lf ~/.ssh/id_ed25519
# 查看所有已加载的密钥
ssh-add -l
# 查看所有已加载密钥的公钥内容
ssh-add -L6.2 更改密钥密码短语
bash
# 修改私钥的密码短语
ssh-keygen -p -f ~/.ssh/id_ed25519
# 交互过程:
# Enter old passphrase: [输入旧密码]
# Enter new passphrase: [输入新密码]
# Enter same passphrase again: [确认新密码]6.3 删除/撤销密钥
bash
# 从 ssh-agent 中移除特定密钥
ssh-add -d ~/.ssh/id_ed25519
# 从 ssh-agent 中移除所有密钥
ssh-add -D
# 删除密钥文件(谨慎操作!)
rm ~/.ssh/id_ed25519
rm ~/.ssh/id_ed25519.pub6.4 密钥备份与恢复
备份密钥
bash
# 创建备份目录
mkdir -p ~/backup/ssh-keys
# 复制密钥到备份目录
cp ~/.ssh/id_ed25519 ~/backup/ssh-keys/
cp ~/.ssh/id_ed25519.pub ~/backup/ssh-keys/
# 压缩并加密备份
tar -czf - ~/backup/ssh-keys | gpg --symmetric --cipher-algo AES256 -o ssh-keys-backup.tar.gz.gpg
# 或者使用 7z 加密压缩
7z a -p ssh-keys-backup.7z ~/backup/ssh-keys/恢复密钥
bash
# 解密备份
gpg --decrypt ssh-keys-backup.tar.gz.gpg | tar -xzf -
# 恢复密钥到 .ssh 目录
cp ~/backup/ssh-keys/id_ed25519 ~/.ssh/
cp ~/backup/ssh-keys/id_ed25519.pub ~/.ssh/
# 设置正确权限
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub6.5 安全最佳实践
| 实践 | 说明 |
|---|---|
| 🔒 使用密码短语 | 为私钥设置强密码短语 |
| 🔒 定期轮换密钥 | 建议每 1-2 年更换一次密钥 |
| 🔒 分离用途 | 不同服务使用不同密钥 |
| 🔒 及时撤销 | 离职/设备丢失时立即从服务器移除公钥 |
| 🔒 安全备份 | 加密备份私钥,存储在安全位置 |
| 🔒 监控使用 | 定期检查服务器上的 authorized_keys |
| 🔒 使用硬件密钥 | 考虑使用 YubiKey 等硬件安全密钥 |
| 🚫 禁止操作 | 永远不要通过邮件/聊天工具发送私钥 |
6.6 使用硬件安全密钥(YubiKey)
bash
# 生成存储在 YubiKey 上的密钥(需要 OpenSSH 8.2+)
ssh-keygen -t ed25519-sk -C "yubikey" -f ~/.ssh/id_ed25519_sk
# 或者使用 ecdsa-sk
ssh-keygen -t ecdsa-sk -C "yubikey" -f ~/.ssh/id_ecdsa_sk
# 使用时需要触摸 YubiKey 进行确认
ssh user@remote_host
# [提示触摸 YubiKey...]7. 常见问题排查
7.1 权限问题
问题:Permissions 0644 for '/home/user/.ssh/id_ed25519' are too open.
解决:
bash
chmod 600 ~/.ssh/id_ed25519
chmod 700 ~/.ssh7.2 连接被拒绝
问题:ssh: connect to host github.com port 22: Connection refused
解决(使用 HTTPS 端口):
bash
# 在 ~/.ssh/config 中添加
Host github.com
HostName ssh.github.com
Port 4437.3 认证失败
问题:Permission denied (publickey).
排查步骤:
bash
# 1. 确认公钥已添加到服务器
cat ~/.ssh/id_ed25519.pub
# 对比服务器上的 ~/.ssh/authorized_keys
# 2. 确认使用正确的私钥
ssh -i ~/.ssh/id_ed25519 user@host
# 3. 检查详细日志
ssh -vvv user@host
# 4. 确认 ssh-agent 已加载密钥
ssh-add -l
ssh-add ~/.ssh/id_ed255197.4 主机密钥变更
问题:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
解决:
bash
# 查看 known_hosts 中的记录
ssh-keygen -l -f ~/.ssh/known_hosts
# 删除特定主机的记录
ssh-keygen -R hostname
ssh-keygen -R 192.168.1.100
# 或者手动编辑 known_hosts 文件删除对应行
nano ~/.ssh/known_hosts7.5 代理转发问题
问题:在远程服务器上无法使用本地 SSH 密钥
解决:
bash
# 在 ~/.ssh/config 中启用代理转发
Host remote-server
HostName remote-server.com
User admin
ForwardAgent yes
IdentityFile ~/.ssh/id_ed25519
# 或者命令行方式
ssh -A user@remote-server⚠️ 注意:代理转发有安全风险,只在可信服务器上使用
7.6 多个 Git 账号配置
场景:同时使用个人 GitHub 和工作 GitHub 账号
解决:
bash
# ~/.ssh/config
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_workbash
# 克隆时使用对应的主机别名
git clone git@github-personal:personal/repo.git
git clone git@github-work:company/repo.git7.7 密钥格式转换
bash
# OpenSSH 私钥转 PEM 格式
ssh-keygen -p -m PEM -f ~/.ssh/id_rsa
# 从私钥提取公钥
ssh-keygen -y -f ~/.ssh/id_ed25519 > ~/.ssh/id_ed25519.pub
# 转换密钥格式(如用于 PuTTY)
# 安装 putty-tools
sudo apt install putty-tools
# OpenSSH 转 PuTTY
puttygen ~/.ssh/id_ed25519 -o ~/.ssh/id_ed25519.ppk
# PuTTY 转 OpenSSH
puttygen ~/.ssh/id_ed25519.ppk -O private-openssh -o ~/.ssh/id_ed255198. 服务器端安全加固
8.1 编辑 SSH 配置文件
在服务器上,用 root 或 sudo 编辑:
bash
sudo vi /etc/ssh/sshd_config找到并修改以下参数(如果前面有 # 记得删掉):
ini
# 禁止 root 密码登录(先确认你已经能用密钥登录 root 或 sudo 用户)
PermitRootLogin prohibit-password
# 完全禁止密码认证,只允许密钥
PasswordAuthentication no
# 禁止空密码
PermitEmptyPasswords no
# 禁止挑战回应认证(通常也跟密码有关)
ChallengeResponseAuthentication no
# 可选:限制允许登录的用户(强烈推荐)
AllowUsers 你的用户名
# 可选:更改 SSH 端口(减少自动扫描)
Port 2222 # 不要和已占用端口冲突,同时记得云平台防火墙放行如果改为
Port 2222,客户端连接时需要-p 2222或更新~/.ssh/config里的 Port。
8.2 语法检查并重启服务
bash
sudo sshd -t # 检查配置语法,无输出代表正常
sudo systemctl restart sshd附录
A. 常用命令速查表
| 命令 | 说明 |
|---|---|
ssh-keygen -t ed25519 -C "comment" | 生成 Ed25519 密钥 |
ssh-keygen -t rsa -b 4096 -C "comment" | 生成 RSA 4096 密钥 |
ssh-keygen -p -f keyfile | 修改密钥密码短语 |
ssh-keygen -lf keyfile.pub | 查看公钥指纹 |
ssh-keygen -R hostname | 删除 known_hosts 记录 |
ssh-copy-id -i key.pub user@host | 复制公钥到远程服务器 |
ssh-add keyfile | 添加私钥到 ssh-agent |
ssh-add -l | 列出已加载的密钥 |
ssh-add -D | 移除所有已加载的密钥 |
ssh -T git@github.com | 测试 GitHub SSH 连接 |
ssh -vvv user@host | 详细调试模式连接 |