
本文详解如何在 PHP 中借助 GnuPG 扩展正确实现基于 RSA 的 PGP 加密与解密,重点纠正常见误区(如解密时未设置私钥密码和未调用 adddecryptkey),并提供可直接运行的健壮示例代码。
本文详解如何在 php 中借助 gnupg 扩展正确实现基于 rsa 的 pgp 加密与解密,重点纠正常见误区(如解密时未设置私钥密码和未调用 `adddecryptkey`),并提供可直接运行的健壮示例代码。
在 PHP 中实现符合 OpenPGP 标准的加密/解密,推荐使用官方 gnupg 扩展(底层调用 GnuPG 命令行工具),而非手动实现 RSA 运算——这不仅确保协议兼容性(支持签名、压缩、对称加密层等 PGP 特性),也规避了密钥管理、填充模式、会话密钥派生等高危细节。但实践中,开发者常因忽略关键配置导致解密失败,例如:仅导入私钥却未通过 adddecryptkey() 显式声明解密凭据,或遗漏私钥密码(passphrase)参数。
以下是一个经过验证、生产就绪的完整实现:
<?php
// 1. 配置 GnuPG 环境(务必指定独立、可写的 GNUPGHOME)
putenv('GNUPGHOME=/tmp/gnupg-'.uniqid()); // 避免多请求冲突
mkdir(getenv('GNUPGHOME'), 0700, true);
// 2. 初始化 GnuPG 实例并启用异常模式(便于调试)
$gpg = new gnupg();
$gpg->seterrormode(gnupg::ERROR_EXCEPTION);
// 3. 加载密钥文件(确保权限安全:.asc 文件应仅 PHP 可读)
$publicKeyData = file_get_contents('/path/to/public.asc');
$privateKeyData = file_get_contents('/path/to/private.asc');
// 4. 导入密钥并获取指纹(关键:必须检查导入结果)
$publicImport = $gpg->import($publicKeyData);
$privateImport = $gpg->import($privateKeyData);
if (empty($publicImport['fingerprint']) || empty($privateImport['fingerprint'])) {
throw new RuntimeException('密钥导入失败:请检查 ASC 文件格式及完整性');
}
$fingerprint = $publicImport['fingerprint'];
$secretFingerprint = $privateImport['fingerprint'];
// 5. 设置加密与解密密钥(⚠️ 核心修正点!)
$gpg->addencryptkey($fingerprint); // 指定公钥用于加密
$gpg->adddecryptkey($secretFingerprint, 'your_passphrase_here'); // 必须提供私钥密码!
// 6. 执行加密与解密
$plaintext = 'Hello, this is a PGP-encrypted message.';
$encrypted = $gpg->encrypt($plaintext);
echo "Encrypted:\n" . wordwrap($encrypted, 64, "\n", true) . "\n\n";
$decrypted = $gpg->decrypt($encrypted);
echo "Decrypted: " . $decrypted . "\n";
echo "Integrity check: " . ($plaintext === $decrypted ? '✅ PASS' : '❌ FAIL') . "\n";关键注意事项:
- ✅ 私钥密码不可省略:adddecryptkey($fingerprint, $passphrase) 是解密成功的前提。若私钥无密码,传空字符串 '';但强烈建议始终使用强密码保护私钥。
- ✅ 环境隔离:每次运行应使用唯一 GNUPGHOME 目录(如上例中 uniqid()),避免并发请求间密钥环污染或权限冲突。
- ✅ 密钥格式要求:必须使用 ASCII-armored(即 .asc)格式的公钥/私钥,且私钥需包含完整的 -----BEGIN PGP PRIVATE KEY BLOCK----- 头尾。可通过 gpg --export -a KEYID > public.asc 和 gpg --export-secret-keys -a KEYID > private.asc 生成。
- ⚠️ 扩展依赖:确保已安装 gnupg PHP 扩展(pecl install gnupg)及系统级 gnupg 工具(apt install gnupg / brew install gnupg)。
- ⚠️ 安全性提示:切勿将私钥硬编码或存于 Web 可访问目录;生产环境应通过安全密钥管理服务(如 HashiCorp Vault)动态注入密码,并限制 GNUPGHOME 目录权限为 0700。
通过以上结构化实现,即可稳定完成端到端 PGP 加解密流程——它严格遵循 RFC 4880 规范,天然支持 RSA、ECC 等多种算法,并自动处理会话密钥生成、对称加密(CAST5/AES)、数据压缩与 Base64 编码等全部 PGP 栈逻辑。
立即学习“PHP免费学习笔记(深入)”;



















