PHP GnuPG实现加密解密

1,741 阅读2分钟

GnuPG简介

GnuPG 是 RFC4880 OpenPGP 标准 PGP 的完整实现,自由软件。GnuPG 可以加密和签名数据和信息传递,包含一个通用的密钥管理系统,包含的访问模块可以访问各种公钥目录。 GnuPG, 简称 GPG, 是命令行工具,很方便和其它程序进行整合,具有很多前端程序和函数库。 GnuPG V2 还支持 S/MIME 和 Secure Shell (ssh). 更多详细介绍点击这里

安装PHP GnuPG扩展

目前该扩展没有找到windows版本,是在linux系统centos7安装测试的

  • 下载扩展包
wget https://pecl.php.net/get/gnupg-1.4.0.tgz
  • 解压扩展包
tar xvf gnupg-1.4.0.tgz
  • 进入扩展目录进行安装操作
cd gnupg-1.4.0
/www/server/php/72/bin/phpize //用自己的phpize路径
./configure --with-php-config=/www/server/php/72/bin/php-config //用自己的php-config路径
make && make install
echo "extension = gnupg.so" >> /www/server/php/72/etc/php.ini //用自己的php.ini路径

如果checkconfig时报错please reinstall the gpgme distribution(请重新安装gpgme发行版),如下图

如出现这种错误我们需要安装下gpgme,直接执行命令 yum install gpgme-devel安装即可!

验证扩展是否安装成功:在页面打印出phpinfo,搜索gnupg,搜到说明安装成功!

创建GPG密钥

网上有很多教程可以参考这里,这里主要说下遇见的问题:

  • 生成密钥最后一步不要设置保护密码,因为高版本的gpg密码无法通过普通的程序传输,会导致解密失败。
  • 生成密钥过程中如果卡住了,说明机器没有生成足够的随机数,需要安装rngd服务---熵值,命令如下
yum -y install  rng-tools
rngd -r /dev/urandom

Web服务器开通访问权限

cd /root/.gnupg
chown: www pubring.gpg trustdb.gpg secring.gpg
chmod  660 pubring.gpg trustdb.gpg secring.gpg

PHP通过GPG加密解密

    /**
     * 公钥加密
     * @param $text
     * @param $publicKey
     * @return mixed
     */
    public function encrypt($text, $publicKey)
    {
        try{
            $gpg = gnupg_init();
            gnupg_seterrormode($gpg, GNUPG_ERROR_EXCEPTION);
            $keyInfo = gnupg_import($gpg, file_get_contents($publicKey));//导入公钥
            gnupg_addencryptkey($gpg, $keyInfo['fingerprint']);
            $encryptText = gnupg_encrypt($gpg, $text);
            if ($encryptText !== false) {
                $ret['code'] = 1;
                $ret['msg'] = '加密成功!';
                $ret['encryptText'] = $encryptText;
            } else {
                $ret['code'] = -10001;
                $ret['msg'] = '加密失败!';
            }
        } catch (\Exception $e) {
            $ret['code'] = -10002;
            $ret['msg'] = 'ERROR: ' . $e->getMessage();
        }

        return $ret;
    }
    /**
     * 私钥解密
     * @param $text
     * @param $privateKey
     * @return mixed
     */
    public function decrypt($text, $privateKey)
    {
        try {
            $gpg = gnupg_init();
            gnupg_seterrormode($gpg, GNUPG_ERROR_EXCEPTION);
            $keyInfo = gnupg_import($gpg, file_get_contents($privateKey));//导入私钥
            gnupg_adddecryptkey($gpg, $keyInfo['fingerprint']);
            $decryptText = gnupg_decrypt($gpg, $text);
            if ($decryptText !== false) {
                $ret['code'] = 1;
                $ret['msg'] = '解密成功!';
                $ret['decryptText'] = $decryptText;
            } else {
                $ret['code'] = -10001;
                $ret['msg'] = '解密失败!';
            }
        } catch (\Exception $e) {
            $ret['code'] = -10002;
            $ret['msg'] = 'ERROR: ' . $e->getMessage();
        }

        return $ret;
    }
    /**
     * 签名加密
     * @param $text
     * @param $signKey
     * @param $EncryptKey
     * @return mixed
     */
    public function signEncrypt($text, $signKey, $EncryptKey)
    {
        try {
            $gpg = gnupg_init();
            gnupg_seterrormode($gpg, GNUPG_ERROR_EXCEPTION);
            $signKeyInfo = gnupg_import($gpg, file_get_contents($signKey));//导入密钥
            $EncryptKeyInfo = gnupg_import($gpg, file_get_contents($EncryptKey));//导入密钥
            gnupg_addsignkey($gpg, $signKeyInfo['fingerprint']);
            gnupg_addencryptkey($gpg, $EncryptKeyInfo['fingerprint']);
            $signEncryptText = gnupg_encryptsign($gpg, $text);
            if ($signEncryptText !== false) {
                $ret['code'] = 1;
                $ret['msg'] = '签名加密成功!';
                $ret['signEncryptText'] = $signEncryptText;
            } else {
                $ret['code'] = -10001;
                $ret['msg'] = '签名加密失败!';
            }
        } catch (\Exception $e) {
            $ret['code'] = -10002;
            $ret['msg'] = 'ERROR: ' . $e->getMessage();
        }

        return $ret;
    }
    /**
     * 私钥签名
     * @param $text
     * @param $privateKey
     * @return mixed
     */
    public function sign($text, $privateKey)
    {
        try {
            $gpg = gnupg_init();
            gnupg_seterrormode($gpg, GNUPG_ERROR_EXCEPTION);
            $keyInfo = gnupg_import($gpg, file_get_contents($privateKey));//导入私钥
            gnupg_addsignkey($gpg, $keyInfo['fingerprint']);
            $signText = gnupg_sign($gpg, $text);
            if ($signText !== false) {
                $ret['code'] = 1;
                $ret['msg'] = '签名成功!';
                $ret['signText'] = $signText;
            } else {
                $ret['code'] = -10001;
                $ret['msg'] = '签名失败!';
            }
        } catch (\Exception $e) {
            $ret['code'] = -10002;
            $ret['msg'] = 'ERROR: ' . $e->getMessage();
        }

        return $ret;
    }
    /**
     * 验签
     * @param $signText
     * @return mixed
     */
    public function verify($signText)
    {
        try {
            $gpg = gnupg_init();
            gnupg_seterrormode($gpg, GNUPG_ERROR_EXCEPTION);
            $text = '';
            $verifyInfo = gnupg_verify($gpg, $signText, false, $text);
            $res = gnupg_keyinfo($gpg, $verifyInfo['fingerprint']);
            if ($res !== false) {
                $ret['code'] = 1;
                $ret['msg'] = '验签成功!';
                $ret['verifyText'] = $text;
            } else {
                $ret['code'] = -10001;
                $ret['msg'] = '验签失败!';
            }
        } catch (\Exception $e) {
            $ret['code'] = -10002;
            $ret['msg'] = 'ERROR: ' . $e->getMessage();
        }

        return $ret;
    }