<?php

namespace Api\PhpUtils\Common;

class Rsa
{

    const  RSA_ENCRYPT_BLOCK_SIZE = 117;//加密切割长度
    const  RSA_DECRYPT_BLOCK_SIZE = 128;//解密切割长度

    const PRIVATE_KEY_STR = '-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDP2SYzFccMwZxC05Uxwei6ijFcOoJOHPHBK2oRX6ZVDSZMxb7g
hH1HU63abxzcW/+OC845OlxC5XZA9AZtfgEHdYNpEGyaCHE1zu4LsWiovTLpYhV1
Ya9Ks/6ynUecn1P8D3OAKaCuD3DLlawLCRmWlc2EpnwYuJIrEf/OnB7A2QIDAQAB
AoGAEsWa9Jwv6RAHa+WuINtRiJ94i8rg/+sPTpH8N2t7G01fuylU7vQoWGvPVN4a
LjDE6PBaBMMnmAcfYghoGDV8JCWlgxza69JLG6BC/ug4AxKbPVN20okQSkXIRzKQ
2y+nyLk/ud2UJ5revYKv9Off/Byh6cFQJJMXTMB/SQNzJ4ECQQDqwP9T1i2EVMxo
GkYJWyYeKFcUFoHyjH+7cNitlMgd4f4+t7CpkiaXDNRu9nYuUC+T3KNJb/r1kuiQ
HUcZNVeRAkEA4qjGn3p/fmer0YruTX1X8xBIk0bgaKfnTAD8Mo/DvtzCu9L85m4P
y4DMDh9u40/TXeP5kvEh/XovRQedwO0AyQJBAL5WR28hO/yMiMNrchfJ6KkRCjGG
YkxXsIU45OYwuOTJxMvzQfDrSBC23VMuz/mTGFBp15cGjVMpjxiyNGBzCJECQBgA
f2gL9MxR9iPubmXOTC31H3pZGxJ6FUg7InnIN5ZSklyJbzaHmSyXqwQj1/5CScO7
jIY++rZ45eCNeesgLeECQFyzTM+ZcpJmD0gHrR9HOZVRGxuY4VEnlmXskmDofozU
62iHAnRxrSv8I1Fiafok33wS7QkLu3Zq4WqifNsmRwQ=
-----END RSA PRIVATE KEY-----';
    const PUBLIC_KEY_STR = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDP2SYzFccMwZxC05Uxwei6ijFc
OoJOHPHBK2oRX6ZVDSZMxb7ghH1HU63abxzcW/+OC845OlxC5XZA9AZtfgEHdYNp
EGyaCHE1zu4LsWiovTLpYhV1Ya9Ks/6ynUecn1P8D3OAKaCuD3DLlawLCRmWlc2E
pnwYuJIrEf/OnB7A2QIDAQAB
-----END PUBLIC KEY-----';

    /**
     * VPN项目 SERVER端私钥与客户端公钥
     */
    const HUBBLE_PRIVATE_KEY_STR = '-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAL38wjPQ0SqaBWWH
1r6Ot+Cb5wqcHcZDtZ6P3W3BjZM49WOm2RgT71FAZSqpAEFF2ZHFb6/E6Q4GzVYY
sCc36I3HACIBC7HutettRylzYeD6sIc6Cc0Qep1e0qmDIQ7CpqUZafvgVl0DMAzg
HH+6J70H83abZtNahcrFQNkFoEkTAgMBAAECgYAzY64oE+CwFE9HYlHs42/LWoBJ
N2c6XNBAnot3h7ZCz1JY7SWlxKakJLX4rxP5k+pA6tXGBo4/lAlws2bahN3rHDrs
n9Yp/LNHo/w91ewF+lofeDnqE5EELllaEB/q7pHb2QI/OS7NmaR3Ya4oaIMQ6HmS
/fpPhzRO85KhVu+BKQJBAORMBTkTcfMSEc026oi5NHCKUX4pdxxocR+CiMK3LpM4
m33QsuqSx3wHr1cwmextweKxk/DV9QOmHKLSBdT97jcCQQDVCqkyY+0qFEjkJ9hp
CUmRf5bgCBpCwo/X5Ds+kpW0aGnygTyqEAZWKFYNWrfxZ2oTTMgk6GO9ey5q9oBy
qW4FAkEA2hnOO5LaH8+5dgXq1iepc4KRDChtBJS6zdGU+gCq3DcORYpmAzeqoFFv
L6rcwkSxH/NqVIDzDENbxClFLRBSzQJBAIdTtFKcAyT9qae0X9Wo3qCb6Zz5yKSr
rm+3PKLsvkfRI6u1yHFGqJ/GE5N8Eug3hrwnw+Md822Dd+LeHo23bnkCQFUZLyaO
AJs9kaIOS8OCId89fQNTHOXaITxPAF29WZtMZ0UoN9kr4TnqzljHyi4k6RUk+n5N
aavtRtfecEWBSKM=
-----END PRIVATE KEY-----';
    const HUBBLE_PUBLIC_KEY_STR = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzGJjG6q4T6ddlsL9mflAkJTsZ
KkXgfdyBSiLFLxU+vncB5qEm8LkHi7M8NRcJ7MEaxWO5OyZ1K8YUIS/LI5/PHBP8
e9l6pxBysN4O29xK8YgMr++okxbzEj2BTJqP8RZMAllOS/FtoObcSvIVgJW+zvxG
HrOB+O1JK1HozVV7UwIDAQAB
-----END PUBLIC KEY-----';

    /**
     * 地铁项目 SERVER端私钥与客户端公钥
     */
    const METRO_PRIVATE_KEY_STR = '-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAL8A0U/w8iLhDb/h
thD1PXHPKvovy5p8eym+jMMcE3GSml2MKNYWYfQlAmH7UQCigtpT8lqH47u3/co3
c1PDgXgtOO2FHoKT2T6eoxVbigSupbdvgh/aQUrMULVdkjvWjBnVRSl9+uP4oYhY
wJyFI2+xWtWrG4TEt/zBIl9uMdIjAgMBAAECgYEAoP8Gb3SwFLhQh6GwfoDIpwqx
tirdWr18b0ZfjgI3XW7uUNXYggRh0pHzfTWCJJ/W3kMOMEMEsXE4KeAthLhxgq7g
bJaWYW8n2N8uT/7jmmb1ETOXcExIyKOBSkrH4Tc5sotTR/b0fNt1/wDGaMC6Akwa
rASUqP++tVi1HxOsqdECQQDj60eT1cTvE9YILJ2y254OtSHZ8IcBFULAJGJbGzB+
E5x/z/evwWj6tNhIZQ+5uB0UGEr1BJYitglFpNid52aJAkEA1okvz6KUfmX4jN1J
VYkcyOsOD+jg+0ZlXtpZouIO5RoH7N5TV6tZZNZ5Q9xS4nBH/ym6xGWfnNBiAv5K
Of6ISwJBAKva1HXcUkoTIue2/JHIlz1vxr6WZrWiWlqXFLKtpbrq/q5BGfokVAv2
IL81tM3MzeBBEQP/GVXC/OrOiadGvEECQBf3IUEnn0DzcS2DNsL4Wx/SqjJ6yE8p
kP9kkujQKevL2aDLQTIk8QqDru42uYeUFWbaqYNw+sCQwrIk5/PMjDsCQDhIYzQJ
3yJRBu1qR0MtYe31nGNheNgxFdWPBHb2esVBRjpJHCBgq3yD7F8/fqS2VS4kuZVg
vijw5aJoY41NBh0=
-----END PRIVATE KEY-----';
    const METRO_PUBLIC_KEY_STR = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA9oxWHFsNGFhCrlnNDZkrkhXg
hjo2KfqV5PTG1ytUdqI4UL+gvt0cV0rc3PC1iMk0PBWIM7w0SqqmLp95JH0g6TnU
AIgT6PrMFgXpFVW0MVgn6vtsfi0AAcArkKimbl9o5pQEz36m4OjqTlyhMQKUDVmu
iRaFoFfqBezeUC0gywIDAQAB
-----END PUBLIC KEY-----';
    /**
     * 商户系统C端 SERVER端私钥与客户端公钥
     */
    const MERCHANT_C_PRIVATE_KEY_STR = '-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCPSD9uvMpO9ZplXip0w/xnwCKjn++MKcaUsMevBE1aZ+qF6HVv
KHn1oxFz7Wo+uSnO5CKLiithYYkI5qyT+1O3KSRNrdxwEx0nMuoK61Sy0BhmbxT8
RmEAj8P90ydGeaXUfeUkc8GIux85sEbhn+7GIeH5pkrJDoBxn6EBhnetCQIDAQAB
AoGAAe6zBAFJSa4t7Cs4r5iyxYFx/Yl9tRanTaKdf3Fa6UIxTJPjS7phrXljboZA
OxQZ/9NKPCMDCGHE4CzRf5NvNnjj2j/GVOIq9mBiBMxC2lmta8ELcebkG7YZw4aV
GCF1xykot6Fi/6H/jxg0aRqy5UfQaBKMsMBpDv2W1SjWWikCQQDLy24r1lalV/YA
H17c6Z2eBmbfP1qwoJxDCZlcCV34vTzoYzxxQv0ybnr8PTzHbPUEJ/bu35aJvrtv
cTCP2Uq1AkEAs/x/DrdiqTNIlKwvrd8283cISHMjivzZsg+64vgu8i45czXce8db
9RzW4L1TbYh+2Eibya2uOnzuSgmRldWJhQJAKdCg11/QQXbN4/KL3VoV3CHGI9J1
Aj7CMUMb83V8kZgKkkgiU78CAsIGfBD4kpa5o1Or6BF6auL2xIP+CdX07QJAXT5S
FK2szztiPqN1j/4z2a2w/NepcjfMEBNWHn+00oJgAO/Gadm+Kh3mtEdhET3FeQck
rjbsLCDM0k5ivd0CgQJBAIcuJFMh0NgvUWV7OMokkgk1ypAwueftB00QpCSKafG3
aCpXDOvobQrT5+xYwfnJI0EdhrwKmXpleXtFiJGnrG8=
-----END RSA PRIVATE KEY-----';
    const MERCHANT_C_PUBLIC_KEY_STR = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiLyLlYmMKf80XMuq6PADgGDgM
AQsEhDSblQUlqXZh/tgZvN4U9QTjLVj5/52wAEXQBu90jvfAiRvqrcc131gAW/JZ
96FUBp8li3a05EwJdyGAaczMNufjHJ05VbNFFvFcnINzbTmsgW+ZGOjw0r6JwOq8
R/DAwvX/MRzDjmYD4wIDAQAB
-----END PUBLIC KEY-----';
    /**
     * 商户系统B端 SERVER端私钥与客户端公钥
     */
    const MERCHANT_B_PRIVATE_KEY_STR = '-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCOa5R/Rkv8xLXl3nlH/03D0xaKlYJcEjAivmrkmtG2KFNDMKCa
zlucu8iW8YDyWCxe7Pfdw/vYeVEpkbhsZdppRCHNgyOhj2UrlESvB34743ieRpHl
OU71S+6q8jzkyddk954z+jbmOi3BkTEdqrTHCbxVkBBA+Hjlxqhy04QHbQIDAQAB
AoGAAZhwSfhKmP0icKuw0qFDqLiM58YuNyPnvDbDYbjfkTK7hXu1FON0tTTADMSN
etvSXpJLhrMmiaY/s9ZDZNIM2qHsO2SF2MtZOBHzkvmuXFdkYipeq+P/Ja+01Nrm
XLt4L6zJINjOJRYzJ8y0Ef6gO7oz1yWjjSIth+syFYV9jDkCQQCjxhfcu6VxOJox
InkUIVS98SsWqiYBSAsbqjUKSJHJz0OQ2M6tTqqiYxF2iQINvXxFkhnj+GmmvuVx
2KxuM63lAkEA3p8e5xEWiaPvYvvUpvHyel5yShOQ6LykehVqewZ/RIC5/NNljDjU
f1YgWBJAgXogYrUp1YSZbyiKFYYJ6nOa6QJACWGNeF1fSq79VhctbFPEcOThnPi+
GJCx4jHLu/0QLMksi51/qTm6WHboRyvt7C+QcMO/q+lM0/pXVkAdEGrxaQJAVHCS
bh6DJ+3wbOEMRc5bpKKSQxqsyjpTQKNC4isSts8EvKsKR2d+4lWuqvkxUmsaQZZp
qb1D3W/JAGT4+d6jkQJAXPHh+4CZoymqsR5hVCbkF/x5S0/n2DhC9+jQc1PpeVBG
EulU0oYPCy55Yku1nD07OkfroyWV6Fe6WzVhCrELUA==
-----END RSA PRIVATE KEY-----';
    const MERCHANT_B_PUBLIC_KEY_STR = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQComhuwIPTxCTFDRVt8A+n2ZF+d
zIMW+szaNtSgd+vQkY+QXWUvs/uI6JPvwvCDVTjao+5W6nN8R26Ttf3ct1GV2Fft
J8K0aV88NMmbP/IQ2o+pcp5kNGW33A6dC4stliSM2BukaYFh4K5xNpzKas6mkuCJ
hXPUTnLhGi/f1hc14QIDAQAB
-----END PUBLIC KEY-----';
    /**
     * TEST SERVER端私钥与客户端公钥
     */
    const TEST_PRIVATE_KEY_STR = '-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANTSopSxl7oFCFDo
D1CFta5K2JmLfYC3N+NLAFyCKRcMFfvX//cXynkQcwciL9KRcE924p5Cgu40i1CA
e6DedjqPu2jgTKJgnkr+j4D2IviMA1SxVg9gWowb9Vda1wrpjUP0EGDODbCWkZ/j
c2wv/eJw5i6dWEff9olJCjW70gbFAgMBAAECgYA4QDwspQv/ZNkf2VZC6DRvDuVV
ICNZ5BNnhilgSh7mMpGU8TB8dNNVUF224vhU5ZAT0M5xGg9VOpof+vWyPVpuAC/0
l0yyjMp7pNRos6JWW8885E+JiFs1WxZUtW3aYvd6cexkCT3WK7W4Jp6yN3GHyjRF
fPcvZ+W5IB+OLxK5+QJBAP9jBP1auCCy0SRNcR+XcnxUneb/IeNN3gUhw7Vf7Xor
0cqJyxzrnUNxn33/7GNXLxLAHCVpIxdW8cmqunlZeF8CQQDVVXPUQ+kawBu4ntnG
t1ukxyXgDuXOFgZJBS1/iMsTMSCuI6A4TYErC9heuqHoM+jXe4c7p+dn3TRkfrCh
uONbAkEA3+h98G9AbhK5QP3Qx6TtkEpT4rofiP21QYSX5QaE3A9dMRlchi+hQwd0
kXD3XSWMNQFP7BDg3k6xUGGqekhSOwJAEfcbRQHfDIinDPobntdsGUlIEEFQ6vUB
3H5aIYZUi640cVXAtV0ZhpV9yCRxZAuTDSpy7fwqyZ1gPyJIH6ZhRwJBANRPBk/J
jvtD5O59rKXYjixl40tGfwJ4oOyrH80mqeOjIUHNqvBYEJ2GUEBQeo+T/nkmaGZ7
2ejuCtERq8JqP+c=
-----END PRIVATE KEY-----';
    const TEST_PUBLIC_KEY_STR = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUe+X6+/HHzJSm2HZJQ/XURaXm
9xlM8udSY6tePCome/JzGCJjRcHkbkGlqXAyT7Ia7Eo4EN4/kGfeJsCD14YIEJLe
X3yl3sCpioETqnNWQnaJtKWADcEaD+uEtw7VOPHMzRl25//RhW91eSgTYW3xgfaS
olw776GB+LcQzmLLFwIDAQAB
-----END PUBLIC KEY-----';

    private static $switchApp = [
        'yidian' => [
            'pub_key' => self::PUBLIC_KEY_STR,
            'pri_key' => self::PRIVATE_KEY_STR,
        ],
        'hubble' => [
            'pub_key' => self::HUBBLE_PUBLIC_KEY_STR,
            'pri_key' => self::HUBBLE_PRIVATE_KEY_STR,
        ],
        'metro' => [
            'pub_key' => self::METRO_PUBLIC_KEY_STR,
            'pri_key' => self::METRO_PRIVATE_KEY_STR,
        ],
        'merchant-c' => [
            'pub_key' => self::MERCHANT_C_PUBLIC_KEY_STR,
            'pri_key' => self::MERCHANT_C_PRIVATE_KEY_STR,
        ],
        'merchant-b' => [
            'pub_key' => self::MERCHANT_B_PUBLIC_KEY_STR,
            'pri_key' => self::MERCHANT_B_PRIVATE_KEY_STR,
        ],
        'test' => [
            'pub_key' => self::TEST_PUBLIC_KEY_STR,
            'pri_key' => self::TEST_PRIVATE_KEY_STR,
        ],
    ];

    /**
     * RSA 签名
     * 
     * @param string $data
     */
    public static function sign_with_private($data, $app = 'yidian')
    {
        $encrypted = '';
        if(isset(self::$switchApp[$app]['pri_key'])) {
            $pri_key = openssl_pkey_get_private(self::$switchApp[$app]['pri_key']);
            openssl_sign($data, $encrypted, $pri_key, OPENSSL_ALGO_SHA256);
            $encrypted = base64_encode($encrypted);
        }
        return $encrypted;
    }

    /**
     * rsa 验证签名
     * 
     * @param string $signed_string
     * @param string $sign_string
     * @param bool 
     */
    public static function verify_with_public($signed_string, $sign_string, $app = 'yidian')
    {
        $ok = false;
        if(isset(self::$switchApp[$app]['pub_key'])) {
            $pub_key = openssl_pkey_get_public(self::$switchApp[$app]['pub_key']);
            $signed_string = base64_decode($signed_string);
            $ok = (bool)openssl_verify($sign_string, $signed_string, $pub_key, OPENSSL_ALGO_SHA256);
        }
        return $ok;
    }

     /**
     * 私钥加密
     * 
     * @param string $data 加密字符串
     * @return string
     */
    public static function encode_with_private($data, $app = 'yidian')
    {
        $encrypted = '';
        if(isset(self::$switchApp[$app]['pri_key'])) {
            $pri_key = openssl_pkey_get_private(self::$switchApp[$app]['pri_key']);
            $data = str_split($data, self::RSA_ENCRYPT_BLOCK_SIZE);
            foreach ($data as $block) {
                openssl_private_encrypt($block, $dataEncrypt, $pri_key);
                $encrypted .= $dataEncrypt;
            }
        }
        return self::urlsafe_b64encode($encrypted);
    }

    /**
     * 公钥加密
     * 
     * @param string $data 加密字符串
     * @return string
     */
    public static function encode_with_public($data, $app = 'yidian')
    {
        $encrypted = '';
        if(isset(self::$switchApp[$app]['pub_key'])) {
            $pub_key = openssl_pkey_get_public(self::$switchApp[$app]['pub_key']);
            $data = str_split($data, self::RSA_ENCRYPT_BLOCK_SIZE);
            foreach ($data as $block) {
                openssl_public_encrypt($block, $dataEncrypt, $pub_key);
                $encrypted .= $dataEncrypt;
            }
        }
        return self::urlsafe_b64encode($encrypted);
    }

    /**
     * 私钥解密
     * 
     * @param $private_key私钥
     * @param string $encrypted解密字符串
     * @return string
     */
    public static function decode_with_private($encrypted, $app = 'yidian')
    {
        $decrypted = '';
        if(isset(self::$switchApp[$app]['pri_key'])) {
            $pri_key = openssl_pkey_get_private(self::$switchApp[$app]['pri_key']);
            $data = str_split(self::urlsafe_b64decode($encrypted), self::RSA_DECRYPT_BLOCK_SIZE);
            foreach ($data as $block) {
                openssl_private_decrypt($block, $dataDecrypt, $pri_key);
                $decrypted .= $dataDecrypt;
            }
        }
        return $decrypted;
    }

    /**
     * 公钥解密
     * 
     * @param string $encrypted解密字符串
     * @return string
     */
    public static function decode_with_public($encrypted, $app = 'yidian')
    {
        $decrypted = '';
        if(isset(self::$switchApp[$app]['pub_key'])) {
            $pub_key = openssl_pkey_get_public(self::$switchApp[$app]['pub_key']);
            $data = str_split(self::urlsafe_b64decode($encrypted), self::RSA_DECRYPT_BLOCK_SIZE);
            foreach ($data as $block) {
                openssl_public_decrypt($block, $dataDecrypt, $pub_key);
                $decrypted .= $dataDecrypt;
            }
        }
        return $decrypted;
    }

    public static function urlsafe_b64encode($string)
    {
        $data = base64_encode($string);
        $data = str_replace(array('+','/','='),array('-','_',''),$data);
        return $data;
    }

    public static function urlsafe_b64decode($string)
    {
        $data = str_replace(array('-','_'),array('+','/'),$string);
        $mod4 = strlen($data) % 4;
        if ($mod4) {
            $data .= substr('====', $mod4);
        }
        return base64_decode($data);
    }
}
