背景 服务器上用 GPG 加密了一个备份包,密码存在 /root/.backup_pass。想在 Windows 上验证能不能解密,结果:
bash
gpg --passphrase-file backup_pass.txt --decrypt secrets.tar.gz.gpg
# gpg: decryption failed: Bad session key
密码是从服务器抄过来的,一个字符没差。
原因 用显微镜看两个文件的字节:
服务器端(Linux):
bash
xxd /root/.backup_pass | tail -2
# ... 3D 0A ← 结尾是 "=" + 换行(LF)
Windows 端:
shell
Format-Hex backup_pass.txt
# ... 3D 0D 0A ← 结尾是 "=" + 回车 + 换行(CRLF)
多了一个 0D(回车)。
Windows 的 Set-Content 默认在每行末尾加 \r\n,GPG 把那个 \r 也当成密码的一部分了。
解决 用不自动加 CRLF 的写入方式:
bash
# ❌ 会加 CRLF
"PASSWORD" | Set-Content backup_pass.txt
# ✅ 一字不差
[System.IO.File]::WriteAllText("$HOME\backup_pass.txt", "PASSWORD")
Linux 端写密码文件时,也养成习惯:
bash
# ❌ echo 会自动加 \n
echo "PASSWORD" > /root/.backup_pass
# ✅ -n 不加换行
echo -n "PASSWORD" > /root/.backup_pass
验证效果
bash
Format-Hex backup_pass.txt
# 结尾应该只有 3D,没有 0D 0A
再解密:
bash
gpg --passphrase-file backup_pass.txt --decrypt secrets.tar.gz.gpg
# gpg: AES256.CFB encrypted data
# gpg: encrypted with 1 passphrase
# → 成功
三个坑 坑 1:肉眼看不出的差异 记事本里两个文件长得一模一样,只有看字节才知道差一个 \r。跨平台处理密钥文件,永远用 Format-Hex / xxd 确认。
坑 2:Linux 的 echo 也会加换行 不只是 Windows 有坑。Linux 写密码文件记得用 echo -n。
坑 3:密码管理器里存的值可能带换行 从密码管理器复制时,有的会带上末尾换行。写入文件后记得清一下。