php RSA 加密 解密 验签

2018-09-16  本文已影响87人  sowork

注:加密的内容长度是有限制的,具体可参考

密钥生成

https://www.jianshu.com/p/9dc5c8a93308

https://blog.csdn.net/li396864285/article/details/79865806

A为客户端 B为服务端

A手里有一套密钥(私钥A/公钥A)

B手里有一套密钥(私钥B/公钥B)

A将公钥A发给B

B将公钥B发给A

注:两套公钥目的是为了保证确实是AB双方在通信,双方的私钥加签是为了标明自己的身份,如果只是对数据进行保护,防止被窃取,服务器只颁发一套密钥也可以

A向B发送请求流程:

2. A用 私钥A + msg获取签名SignA

3. A用 公钥B 将SignA + msg 加密 得到 要发送的密文 secret

4. B 收到 A 发送过来的密文 secret 使用 私钥B 进行解密 得到 SignA + msg (第一次解密)

5. B 使用 公钥B + msg +signA进行验签操作(第二次验签)

引用别处的图片

image

/**

* Created by PhpStorm.

* User: 80752

* Date: 2018/9/12

* Time: 21:30

*/

if (! function_exists('url_safe_base64_encode')) {

    function url_safe_base64_encode ($data) {

        return str_replace(array('+','/', '='),array('-','_', ''), base64_encode($data));

    }

}

if (! function_exists('url_safe_base64_decode')) {

    function url_safe_base64_decode ($data) {

        $base_64 = str_replace(array('-','_'),array('+','/'), $data);

        return base64_decode($base_64);

    }

}

class RSA

{

    /**

    * 选择在创建CSR时应该使用哪些扩展。可选值有 OPENSSL_KEYTYPE_DSA, OPENSSL_KEYTYPE_DH, OPENSSL_KEYTYPE_RSA 或 OPENSSL_KEYTYPE_EC. 默认值是 OPENSSL_KEYTYPE_RSA.

*/

    const RSA_ALGORITHM_KEY_TYPE = OPENSSL_KEYTYPE_RSA;

    /**

    * 签名算法, 默认为 OPENSSL_ALGO_SHA1

*/

    const RSA_ALGORITHM_SIGN = OPENSSL_ALGO_SHA256;

    /**

    * 公钥

    * @var string

*/

    public static $publicKey = '';

    /**

    * 私钥

    * @var string

*/

    public static $privateKey = '';

    public static function createRsaKey ($key_size = 2048) {

        $config = array(

            "private_key_bits" => $key_size,

            "private_key_type" => self::RSA_ALGORITHM_KEY_TYPE

        );

        $res = openssl_pkey_new($config);

        openssl_pkey_export($res, $private_key);

        $public_key_detail = openssl_pkey_get_details($res);

        $public_key = $public_key_detail["key"];

        self::$publicKey = $public_key;

        self::$privateKey = $private_key;

        return [

            "public_key" => $public_key,

            "private_key" => $private_key,

        ];

    }

    /**

    * 获取rsa密钥加密位数

    * @param $source

    * @return mixed

*/

    private static function getKeyBitDetail ($source) {

        return openssl_pkey_get_details($source)['bits'];

    }

    /**

    * 获取私钥

    * @return bool|resource

*/

    public static function getPrivateKey () {

        $source =  openssl_pkey_get_private('file://rsa_private_key.pem');

        if (!$source) {

            $source = openssl_pkey_get_private(self::$privateKey);

        }

        return $source;

    }

    /**

    * 获取公钥

    * @return resource

*/

    public static function getPublicKey () {

        $source = openssl_pkey_get_public('file://rsa_public_key.pem');

        if (!$source) {

            $source = openssl_pkey_get_public(self::$publicKey);

        }

        return $source;

    }

    /**

    * 私钥加密

    * @param $data

    * @return bool|null

*/

    public static function privEncrypt ($data = '') {

        $privKey = self::getPrivateKey();

        $partLen = self::getKeyBitDetail($privKey) / 8 - 11;

        $parts = str_split($data, $partLen);

        $encrypted = '';

        foreach ($parts as $part) {

            openssl_private_encrypt($part, $partEncrypt, $privKey);

            $encrypted .= $partEncrypt;

        }

        openssl_free_key($privKey);

        return $encrypted ? url_safe_base64_encode($encrypted) : null;

    }

    /**

    * 公钥解密

    * @param string $encrypted

    * @return bool|null

*/

    public static function publicDecrypt ($encrypted = '') {

        $pubKey = self::getPublicKey();

        $partLen = self::getKeyBitDetail($pubKey) / 8;

        $parts = str_split(url_safe_base64_decode($encrypted), $partLen);

        $decrypted = '';

        foreach ($parts as $part) {

            openssl_public_decrypt($part, $partDecrypt, $pubKey);

            $decrypted .= $partDecrypt;

        }

        openssl_free_key($pubKey);

        return $decrypted ?: null;

    }

    /**

    * 公钥加密

    * @param string $data

    * @return bool|null

*/

    public static function publicEncrypt ($data = '') {

        $pubKey = self::getPublicKey();

        $partLen = self::getKeyBitDetail($pubKey) / 8 - 11;

        $parts = str_split($data, $partLen);

        $encrypted = '';

        foreach ($parts as $part) {

            openssl_public_encrypt($part, $partEncrypt, $pubKey);

            $encrypted .= $partEncrypt;

        }

        openssl_free_key($pubKey);

        return $encrypted ? url_safe_base64_encode($encrypted) : null;

    }

    /**

    * 私钥解密

    * @param string $encrypted

    * @return bool|null

*/

    public static function privDecrypt ($encrypted = '') {

        $privKey = self::getPrivateKey();

        $partLen = self::getKeyBitDetail($privKey) / 8;

        $parts = str_split(url_safe_base64_decode($encrypted), $partLen);

        $decrypted = '';

        foreach ($parts as $part) {

            openssl_private_decrypt($part, $partDecrypt, $privKey);

            $decrypted .= $partDecrypt;

        }

        openssl_free_key($privKey);

        return $decrypted ?: null;

    }

    /**

    * 私钥签名

    * @param string $data

    * @return null|string

*/

    public static function privSign ($data = '') {

        $privKey = self::getPrivateKey();

        openssl_sign($data, $sign, $privKey, self::RSA_ALGORITHM_SIGN);

        openssl_free_key($privKey);

        return $sign ? url_safe_base64_encode($sign) : null;

    }

    /**

    * 公钥验签

    * @param string $data

    * @param string $sign

    * @return int

*/

    public static function publicVerifySign ($data = '', $sign = '') {

        $pubKey = self::getPublicKey();

        $res = openssl_verify($data, url_safe_base64_decode($sign), $pubKey, self::RSA_ALGORITHM_SIGN);

        openssl_free_key($pubKey);

        return $res;

    }

}

$data['name'] = 'sowork111111111111111111111111111111111111111111111111sowork1111111111111111111111111111111111112313111111111111111111111111===============================================';

$data['age'] = '24';

echo '<pre>';

print_r(RSA::createRsaKey()) . '<br/>';

echo '</pre>';

// 私钥加密 公钥解密

//$privSec = RSA::privEncrypt(json_encode($data));

//echo '私钥加密:' . $privSec . '<br/>';

//echo '公钥解密:' . RSA::publicDecrypt($privSec) . '<br/>';

// 公钥加密 私钥解密

//$pubSec = RSA::publicEncrypt(json_encode($data));

//echo '公钥加密:' . $pubSec . '<br/>';

//echo '私钥解密:' . RSA::privDecrypt($pubSec) . '<br/>';

$sign = RSA::privSign(json_encode($data));

$secret = RSA::publicEncrypt(json_encode($data));

echo '私钥签名后:' . $sign . ' <br/>';

echo '公钥验签后:' . RSA::publicVerifySign(json_encode($data), $sign) . '<br/>';

上一篇下一篇

猜你喜欢

热点阅读