Karp

RSA密文过长加密解密 越过1024的解决代码
什么是RSA加密?RSA (详见维基百科)算法是现今使用最广泛的公钥密码算法,也是号称地球上最安全的加密算法,与 ...
扫描右侧二维码阅读全文
25
2022/06

RSA密文过长加密解密 越过1024的解决代码

什么是RSA加密?

RSA (详见维基百科)算法是现今使用最广泛的公钥密码算法,也是号称地球上最安全的加密算法,与 md5sha1 不同,到目前为止,也只有极短的RSA加密被破解。

使用场景

为移动端(IOS,安卓)编写 API 接口
进行支付、真实信息验证等安全性需求较高的通信
与其他第三方或合作伙伴进行重要的数据传输,用于外部商户系统和本系统之间报文的安全性验证。

<?php

class Rsa
{
    /**
     * 生成证书
     * @return array
     */
    public static function exportOpenSSLFile($bits = 1024)
    {
        $config = array(
            "digest_alg" => "sha512",
            "private_key_bits" => $bits,           //字节数  512 1024 2048  4096 等
            "private_key_type" => OPENSSL_KEYTYPE_RSA,   //加密类型
        );
        $res = openssl_pkey_new($config);
        if ($res == false) return [];

        openssl_pkey_export($res, $private_key);
        $public_key = openssl_pkey_get_details($res);
        $public_key = $public_key["key"];
        openssl_free_key($res);

        return [$private_key, $public_key];
    }

    /**
     * 生成签名
     * @param array $params 待签名的所有参数
     * @return string 生成的签名
     */
    public static function getSignGenerator($params, $ssl_private)
    {
        //生成待验签的字符串
        $data = self::getSignStr($params);
        $pem = "-----BEGIN RSA PRIVATE KEY-----\n" .
            wordwrap($ssl_private, 64, "\n", true) .
            "\n-----END RSA PRIVATE KEY-----";

        //openssl_private_encrypt($data, $crypted, $pem);
        openssl_sign($data, $sign, $pem, OPENSSL_ALGO_SHA256);

        return base64_encode($sign);
    }

    /**
     * 验证签名 公钥验证签名
     * @param array $params 待签名的所有参数
     * @param string $sign 生成的签名
     * @return boolean 校验的结果
     */
    public static function signCheck($data, $sign, $ssl_public)
    {
        //对方的公钥内容 一行的形式

        $pem = "-----BEGIN PUBLIC KEY-----\n" .
            wordwrap($ssl_public, 64, "\n", true) .
            "\n-----END PUBLIC KEY-----";

        return (bool)openssl_verify($data, base64_decode($sign), $pem, OPENSSL_ALGO_SHA256);
    }

    /**
     * 我们自己的加密
     * @param $string
     * @param $pubKey
     * @return string
     */
    function encrypt($string, $ssl_public)
    {
        $res = "-----BEGIN PUBLIC KEY-----\n" .
            wordwrap($ssl_public, 64, "\n", true) .
            "\n-----END PUBLIC KEY-----";

        openssl_public_encrypt($string, $encrypt, $res);

        return base64_encode($encrypt);
    }


    /**
     * 私钥加密 (使用公钥解密)
     * @param string $data
     * @param $privateKey
     * @param int $padding
     * @return null|string
     */
    public static function privateEncrypt(string $data, $privateKey, $padding = OPENSSL_PKCS1_PADDING)
    {
        $encrypted = '';
        $chunks = str_split($data, 117);
        foreach ($chunks as $chunk) {
            $partialEncrypted = '';
            $encryptionOk = openssl_private_encrypt($chunk, $partialEncrypted, $privateKey, $padding);
            if ($encryptionOk === false) {
                return null;
            }
            $encrypted .= $partialEncrypted;
        }

        return base64_encode($encrypted);
    }

    /**
     * 公钥加密(使用私钥解密)
     * @param string $data 加密字符串
     * @param int $padding
     * @return null|string
     */
    public static function publicEncrypt(string $data, $publicKey, $padding = OPENSSL_PKCS1_PADDING)
    {
        $encrypted = '';
        $chunks = str_split($data, 117);
        foreach ($chunks as $chunk) {
            $partialEncrypted = '';
            $encryptionOk = openssl_public_encrypt($chunk, $partialEncrypted, $publicKey, $padding);
            if ($encryptionOk === false) {
                return null;
            }
            $encrypted .= $partialEncrypted;
        }

        return base64_encode($encrypted);
    }

    /**
     * @param string $encrypted
     * @param $privateKey
     * @return null
     * @uses 私钥解密 (使用公钥加密)
     */
    public static function privateDecrypt(string $encrypted, $privateKey)
    {
        $decrypted = '';
        $chunks = str_split(base64_decode($encrypted), 128);
        foreach ($chunks as $chunk) {
            $partial = '';
            $decryptIsTrue = openssl_private_decrypt($chunk, $partial, $privateKey);
            if ($decryptIsTrue === false) {
                return null;
            }
            $decrypted .= $partial;
        }

        return $decrypted;
    }

    /**
     * 公钥解密 (使用私钥解密)
     * @param string $encrypted 被解密字符串
     * @return null
     */
    public static function publicDecrypt(string $encrypted, $publicKey)
    {
        $decrypted = '';
        $chunks = str_split(base64_decode($encrypted), 128);
        foreach ($chunks as $chunk) {
            $partial = '';
            $decryptIsTrue = openssl_public_decrypt($chunk, $partial, $publicKey);
            if ($decryptIsTrue === false) {
                return null;
            }
            $decrypted .= $partial;
        }
        return $decrypted;
    }

    /**
     * 私钥签名
     * @param $data string 验签内容
     * @param $signature string 签名字符串
     * @param int $signature_alg
     * @return string
     */
    public static function privateSign($data, $privateKey, $signature_alg = OPENSSL_ALGO_SHA1)
    {
        $signature = '';
        openssl_sign($data, $signature, $privateKey, $signature_alg);
        openssl_free_key($privateKey);

        return base64_encode($signature);
    }

    /**
     * 公钥验签
     * @param $data string 验签内容
     * @param $signature string 签名字符串
     * @param int $signature_alg
     * @return bool
     */
    public static function publicSign($data, $signature, $publicKey, $signature_alg = OPENSSL_ALGO_SHA1)
    {
        $result = openssl_verify($data, base64_decode($signature), $publicKey, $signature_alg);
        openssl_free_key($publicKey);

        return $result === 1;
    }

    /**
     * 生成待签名的字符串
     * @param array $data 参与签名的参数数组
     * @return string 待签名的字符串
     */
    public static function getSignStr(array $data)
    {
        //排序
        ksort($data);
        //剔除sign 如果对方的签名叫sign 或者可以在调用方法的时候剔除
        //unset($data['sign']);

        $stringToBeSigned = '';

        $i = 0;

        foreach ($data as $k => $v) {
            if ($i == 0) {
                $stringToBeSigned .= "$k" . "=" . "$v";
            } else {
                $stringToBeSigned .= "&" . "$k" . "=" . "$v";
            }

            $i++;
        }

        return $stringToBeSigned;
    }

}

使用Demo

<?php

$public_key = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbtLA7lMfUvpBgfgzouiPgcnbL
DnEcuCK0gMub/EAEqmr82sl+9tH1iQb1w/hgQLptVRxAuUOa03XqlnG3wkAegtQt
4Q5ZtHSSomE8/5FXJvQfGTCz5RARyM0MiLTMZJGhLdVT6O8uCYIrPRQq7u6NVLs9
6YDmtzX2do/sTsWCAwIDAQAB
-----END PUBLIC KEY-----';

$private_key = '-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCbtLA7lMfUvpBgfgzouiPgcnbLDnEcuCK0gMub/EAEqmr82sl+
9tH1iQb1w/hgQLptVRxAuUOa03XqlnG3wkAegtQt4Q5ZtHSSomE8/5FXJvQfGTCz
5RARyM0MiLTMZJGhLdVT6O8uCYIrPRQq7u6NVLs96YDmtzX2do/sTsWCAwIDAQAB
AoGAfnO3zCuAPp6k0jiMc1T4XgeXwkDwS8qfJMiUkxHBTAi66q8khSAeU7H9HQsS
Y9ktji1YzJeo98xULzgPEpWHS/uhA8VZa16TLy9Yfadn2t+wpWpEJ9ZA4jjEqfQj
DDxcUc/pEv5siaE/bU8uls4o2nAiuWnI2n5FGrQa2OziGUECQQDPOh3KD2AOZtEF
p7i0yxYXe4dCKwenfw5q7l933RgqMXsVR1EAGzAUdIs71hTye6ibhva+eJRfndoV
Jq2IHjOdAkEAwFpOZR8j3Cl4zEk/9D9WEnSa8VWLe76vb7DfgfwkSAhs/f2MNF1I
zy9W5tPHRiMzaHNgPBFX9tw2u5QzsgOqHwJAPl3zUTjHZA41okoUIPVuNKsMzjE9
IH/wyuXq/ZwhBbHWpVTNYAbOtZlNvjh0HXZyDDzWTgTkQtKzK+J0H59XUQJARukD
vYOdVKx1O9pFGWW/9U3HUPCYWyYQxrwNqX2qYmO4ymmOJj+9d6OcBbxM2i5f5UGj
WIGMTBUimEQqSpXPQQJAIkHC2GknUv8HaBRLXxYTIAjj78a0pQT2bYlI6R04AwUZ
ljBaUGvvdYJ3CGZ32Xk12Te2fMJj5h/yLyEr8uzpzw==
-----END RSA PRIVATE KEY-----',

# 公钥加密、私钥解密
// 加密明文
$crypt_text = '公钥加密、私钥解密';
echo '加密明文:' . $crypt_text.PHP_EOL;

$public_encrypt_data = Rsa::publicEncrypt($crypt_text, $publicKey);
echo '公钥加密后数据:' . $public_encrypt_data.PHP_EOL; // 一直在变化

$private_decrypt_data = Rsa::privateDecrypt($public_encrypt_data, $privateKey);
echo '私钥解密数据: ' . $private_decrypt_data.PHP_EOL;

加密明文:公钥加密、私钥解密
公钥加密后数据:QHdj15P6l1gJbjNlD7spKT7KjCJJ0Qg5c8JjLBAS9hvhkq8eRuaNY/dDrboD3t40NvyPI8SBFBkDTjJ5IDyqTTSfthUROvasMD7wCPRYGaOt5to+ygfvV5t4CyYQEvSSflqimWvffRs0L8fs3pqE2kLD/AHOC94+ZBNFfzTTtVA=
私钥解密数据: 公钥加密、私钥解密

# 私钥加密、公钥解密
// 加密明文
$crypt_text = '私钥加密、公钥解密';
echo '加密明文:' . $crypt_text.PHP_EOL;

$private_encrypt_data = Rsa::privateEncrypt($crypt_text, $privateKey);
echo '私钥加密后数据:' . $private_encrypt_data..PHP_EOL; // 不变

$public_decrypt_data = Rsa::publicDecrypt($private_encrypt_data, $publicKey);
echo '公钥解密数据: ' . $public_decrypt_data..PHP_EOL;

加密明文:私钥加密、公钥解密
私钥加密后数据:dDzAs7kj9z7kS7Zbcz6sNLP+sIOnXp2qFGr4RepZcZp9XzCt8Tt+Kd/NIo4S20hjAvBiurvSHaR6LLL5ur5dc4vkFGkV+bGaT2SlhC4JkvYt4N2T9EiQupwcCtlk+dcENLexWiCvZtuzk3peK+H7AUWqFeOlmGRZb3De7bP+heY=
公钥解密数据: 私钥加密、公钥解密

最后修改:2022 年 06 月 25 日 07 : 46 PM

发表评论