php电子签名
原理
使用一对公钥和私钥,用私钥对数据进行签名,用公钥对签名数据进行加密,形成电子签名。
电子签名认证,用私钥解密数据,用公钥验证签名。
若加密容过长,则将加密内容按照固定长度分块,对每块进行加密再拼接;解密时也是分块进行,
分割大小固定。
生成证书
# 生成私钥openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048# 生成公钥openssl rsa -pubout -in private_key.pem -out public_key.pem
代码
目录结构
- public_private_key 证书
---- private_key.pem 私钥
---- public_key.pem 公钥- src
-- esign.php 电子签名类- vendor 扩展包-index.php 调用文件
电子签名类
namespace Wj/Esign;class esign {const RSA_ENCRYPT_BLOCK_SIZE = 117; //加密切割长度const RSA_DECRYPT_BLOCK_SIZE = 256; //解密切割长度private $privateKey; //私钥证书private $publicKey; //公钥证书private $signstr; //加密数据 字符串public function __construct($signdata) {$path = ROOT_PATH . "public_private_key" . DS . DS;$this->privateKey = openssl_get_privatekey(file_get_contents($path . "private_key.pem"));$this->publicKey = openssl_get_publickey(file_get_contents($path . "public_key.pem"));$this->setsigndata($signdata);}private function setsigndata($signdata) {$signstr = $signdata;if (is_array($signdata)) {$signstr = implode("", $signdata);}if (!is_string($signstr)) {if (empty($signstr)) {throw new \Exception("加密数据错误");}}$this->signstr = $signstr;}/*** 获取签名*/public function getsignstr() {openssl_sign($this->signstr, $signature, $this->privateKey);$signature = base64_encode($signature);$data = $this->encryptsign($signature);return $data;}/*** 加密签名*/private function encryptsign($signature) {if (!is_string($signature)) {return null;}$signature_arr = str_split($signature, self::RSA_ENCRYPT_BLOCK_SIZE);$useencrypted = "";foreach ($signature_arr as $key => $block) {openssl_public_encrypt($block, $encrypted, $this->publicKey, OPENSSL_PKCS1_OAEP_PADDING);$useencrypted .= $encrypted;}$useencrypted = base64_encode($useencrypted);return $useencrypted ? $useencrypted : null;}/*** 解密签名*/private function decryptsign($encrypted) {if (!is_string($encrypted)) {return null;}$result = '';$encrypted_arr = str_split(base64_decode($encrypted), self::RSA_DECRYPT_BLOCK_SIZE);foreach ($encrypted_arr as $block) {openssl_private_decrypt($block, $dataDecrypt, $this->privateKey, OPENSSL_PKCS1_OAEP_PADDING);$result .= $dataDecrypt;}return $result ? $result : null;}/*** 签名验证*/public function verifysign($encrypted) {$encodestr = $this->decryptsign($encrypted);$result = base64_decode((string) $encodestr);$result = openssl_verify($this->signstr, $result, $this->publicKey);return $result == 1 ? true : false;}
}
调用
define('DS', DIRECTORY_SEPARATOR);
defined('ROOT_PATH') or define('ROOT_PATH', __DIR__ . DS);require "./vendor/autoload.php";
use Wj\Esign\esign;$data = ['name' => 'test','time' => time(),
];
$es = new esign($data);
$encrypted = $es->getsignstr();
$result = $es->verifysign($encrypted);
var_dump($encrypted, $result);
输出结果
string(1024) "g5j76cEr/odqfH6H4kUYM6GwCoJYKNLyh61O10XDIbCwqo0p+kmPhyMGL4sFam8L/vpCxwabV7FHjhq5JYbgYCq19T4PqsJ2yO8xs/Lf3x3DWvImIAkBghYRLYtyri6JoK2CATQ7cGWKYl9s16LLvpxmmLlcWztnvRc47NkjEVinTNKGghNLcSU1pmphCyvI0nzYMCdrsTKGWVPt5qDXUtJsukLS8rMfxQNQQppRUeETUr+1+r8PAEqrJVRSeJIQ+Eng/JpolWB4cYnLjOPqknU8ft4zuHGwcGbtcvk/DGI2B+4uwC+Y71evWim+Jct6hFE7IOQNIuUyg/gpAcQH7z3Ab6gfdup0pM4gfM/rCsfvMhC07AngeraiE+5Yzl2mugzzYe5hHZ5epUPpur3K/v1ZP3Hf6thzmImvcj1b661FB3ElVSLbqHl9SvrYgd5LQOfl0ThsJe51dJqp+40hmeH7jyYrJAtykmDIu992lsfkc+eJQ1NcyNnseztQ7f0F0vj2sLNnpR26PvXznik2auQPMLdsr3ksPbJM9gcaCPLE0apfbU0dUvGwpVGgbPYpRgSpGQXtc5uAeJtk/Ia24KMj7kOVlXG//3T7UhkrxF8WSmlfFoRpJq5jnc+ANNfZzRcINs3VdsTHHtWsbLjgCNsiPHAz9bezqs2y2JsFQMgJ6U+2QMQRwnSlEEQMtC9NCQJeTe3YivEhhEsgfNKLdS0+O8Ml3qRnYYLC0zI63EL6PsN7S69WQwS839TdtdUiwvUy8SC2rfYrXwNQpttCxJ/LQJTznOZbnYdMqTp2C0XRCMn8Jz5GQY4c3ZpP48MZ3+kAjKgNF1U9cWw0zDwEYIkFBI0EHAAYTgrRXNlUfSCgkDnKlb813WKrz/+f2oUQKYzl+wI25T4EREuASv3xi5Q/INlasL3Nj0jzLxwsHkm4hvon4aG2uc1oeNviPOmCgArKCNwQ+R4R8mvS1wTNnckgEdkFV9G0V6SxJUixIiKZAxSeaAL7Ijng6PGhJsFp"
D:\workspace\php\test\esign\index2.php:15:
bool(true)