php RSA 加密解密

代码:

function generate(int $private_key_bits = 1024)
{
    $rsa = [
        "private_key" => "",
        "public_key" => ""
    ];
    $config = [
        "digest_alg" => "sha512",
        "private_key_bits" => $private_key_bits,
        "private_key_type" => OPENSSL_KEYTYPE_RSA,
    ];
    $res = openssl_pkey_new($config);
    openssl_pkey_export($res, $rsa['private_key']);
    $rsa['public_key'] = openssl_pkey_get_details($res)["key"];
    return $rsa;
}




function sign($data, $priKey, $code = 'base64')
{
    $ret = false;
    if (openssl_sign($data, $ret, openssl_get_privatekey($priKey))) {
        $ret = encode($ret, $code);
    }
    return $ret;
}
function encode($data, $code)
{
    switch (strtolower($code)) {
        case 'base64':
            $data = base64_encode('' . $data);
            break;
        case 'hex':
            $data = bin2hex($data);
            break;
        case 'bin':
        default:
    }
    return $data;
}

function verify($data, $sign, $pubKey,$code = 'base64')
{
    $ret = false;
    $sign = decode($sign, $code);
    if ($sign !== false) {
        switch (openssl_verify($data, $sign, openssl_get_publickey($pubKey))) {
            case 1:
                $ret = true;
                break;
            case 0:
            case -1:
            default:
                $ret = false;
        }
    }
    return $ret;
}

function decode($data, $code){
    switch (strtolower($code)) {
        case 'base64':
            $data = base64_decode($data);
            break;
        case 'hex':
            $data = ($data !== false && preg_match('/^[0-9a-fA-F]+$/i', $data) ? pack("H*", $data) : false);
            break;
        case 'bin':
        default:
    }
    return $data;
}




function checkPadding($padding, $type)
{
    if ($type == 'en') {//加密
        switch ($padding) {
            case OPENSSL_PKCS1_PADDING:
                $ret = true;
                break;
            default:
                $ret = false;
        }
    } else {//解密
        switch ($padding) {
            case OPENSSL_PKCS1_PADDING:
            case OPENSSL_NO_PADDING:
                $ret = true;
                break;
            default:
                $ret = false;
        }
    }
    return $ret;


}

function _encrypt($data,$publicKey, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING)
{
    $ret = false;
    if (!checkPadding($padding, 'en')) return false;
    if (openssl_public_encrypt($data, $result, $publicKey, $padding)) {
        $ret = encode($result, $code);
    }
    return $ret;
}

//$rev是否翻转明文
function _decrypt($data, $priKey, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING,$rev = false)
{
    $ret = false;
    $data = decode($data, $code);
    if (!checkPadding($padding, 'de')) return false;
    if ($data !== false) {
        if (openssl_private_decrypt($data, $result, $priKey, $padding)) {
            $ret = $rev ? rtrim(strrev($result), "\0") : '' . $result;
        }
    }
    return $ret;
}
$rsa=generate();

$private_key=$rsa['private_key'];
$public_key=$rsa['public_key'];

echo "private_key:\n" . $private_key . "\n\r";
echo "public_key:\n" . $public_key . "\n\r";


$data=json_encode(['code'=>0]);
echo '要加密的数据:' . $data, "\n-------------------------------\n";

//加密
$encrypt = _encrypt($data,$public_key);
echo "公钥加密后的数据: " . $encrypt . "\n";
//解密
$decrypt = _decrypt($encrypt,$private_key);
echo "私钥解密后的数据: " . $decrypt, "\n-------------------------------\n";


$sign=sign($data,$private_key);
echo "签名: " . $sign . "\n";
$verify=verify($data,$sign,$public_key);
echo "验证的结果: \n";
var_export($verify);
echo "\n";

输出:

private_key:
-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMGkPuYP1iqjPz11
l10Z6C7C6XbXLWIoEdpgtpihTUi4wkI72LN6Lb0H8YsFUoB4M34DE68g1WuDjHAe
IYX0Izk1HxdnT8OoKxVj/A+ByLZDT5sHnsNw+bPWFF29Eg+6FkiXMFjtIfDTw1Mc
xxt4C4a3lE/5FRhAr0LuWeCeQuYhAgMBAAECgYAChHQc4Y/TNhQYZHL3TuLp2LbY
SKvaXtL8l81H5rDuhRhhbA3BJ5F4p6XIPOV5rhZdSQT0feTIZQlqW7nr1+StT+MO
wBrVDCRm2CATK/Q8kggR2468RCkRDWtrCyTCI2d0goBN/zoEEkuTTfzytg50PWUO
buEVj6rg+h9GWtbgAQJBAPqqlL2L2xdJbuzrUH0UMRURWOYDJpl/lQbZy3L6rmzJ
Bt+p+VoY2+gLYP124YxkB8pdY3umKpV1i4/GG1NPEUECQQDFwwq6HbP90SDl9oQe
H1RsjGnnvVF0hcZTS0IyHQEaWBl3lKVskk6EdpBM6KeXLDbb/7BqWSmJcM8bMkZ1
2bzhAkAhNPvjaGWr3hSN2ladW1FtQxEN15kDeL1bXPrwznjQ/IimlLPt1aE8SlWc
/mS+3nmRu3F0bfzyM9I7R7lS/gSBAkB/g1haUyaoZPyyanYbuhXEe/EZdE+eM1eC
g4cmKt94LhAVs6nKTLgF3zEB9g2BgwfIaKBGokEPFsbjgVI/UOrhAkBhe146FLSw
kGsEBtpQISw1ibRJlR/M0w4HaBaD8GI/FvqjtLgrunYRuIPnkT5rOKcHEqnKAFbo
W1tMJUCiWs4p
-----END PRIVATE KEY-----


public_key:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBpD7mD9Yqoz89dZddGeguwul2
1y1iKBHaYLaYoU1IuMJCO9izei29B/GLBVKAeDN+AxOvINVrg4xwHiGF9CM5NR8X
Z0/DqCsVY/wPgci2Q0+bB57DcPmz1hRdvRIPuhZIlzBY7SHw08NTHMcbeAuGt5RP
+RUYQK9C7lngnkLmIQIDAQAB
-----END PUBLIC KEY-----


要加密的数据:{"code":0}
-------------------------------
公钥加密后的数据: Xu+/cKeZLnBc+7NTb20wAnJclAtcrY3xw9yhSXamSDLxiNViAiccIUy7TZS6pq4xYhGh10KYCaAXdCVvvHXxC+aJbi3eoksRc8GuUwlHm+ElyLJYz7bqpYj0rBI192bF6+S+RKIHJhWRM/uThU40HylnS3GO4h4xHWicbtOBRWU=
私钥解密后的数据: {"code":0}
-------------------------------
签名: vWOvBF9CQwXypaDTZ9ZvrjhyIH1my40xg3WzApwIb8fA7T483ZQ6T02V+2uiDJndBlWx95HSg1Nu3KyTMGUh8yx0qeRv3rP6rL3OdyknuS+MsqQz77pNj0QZElgOI6CiiEuZvcRZEyhDEAHg/pVuQWHgE38jMB8/q4Qms6nXvcA=
验证的结果: 
true