<?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 PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKp8Y3v5b1cAuAW/
PUEOrUQvNQXSqK/Thcd9a200EQe+TTB5IJQmx4zQXth0pvNnQc8VWdTas+JO0MeN
+jyXuok/HHug8AAA4J6CR3QUazH3A3yf94AaOMAF3iQwww0yiVBBJ1/8dH4X3tTf
QpBHrDcvM0fqZRdEqrJzVbbSaQqFAgMBAAECgYBcZo6E4uw1e25BryTD3fCKxAs4
3LQQl9QqCw/uYAna6IltfDjsExiUeVrudksGITDJzAikFOTqA02k2o6FyLaQSUnS
uRuDGLEGEx6SQVFMH9uZL8E7zjCPmTzvceE0RVyQG5nHkSrmL60enT2+4LnyEhUq
pvUb+Fm+WExyFDXpAQJBAOFM0GE2KLRfdgS/+CmdHfzxj19ytRnNc3/qHez2Ay24
El9gJA7B9y27c2gxYs0RXo7BwIUsaJ2FsgQeI74y5PMCQQDBt3tBsvMPPg21E+Y9
HVFue5sQ0YJ48ygDU3FmvJ66btadq8Qm/cZgiw+/R912C0IrOx+juVpgLzds1UBH
H5CnAkAs8DVgLn1P/Pp9WA0Xv88LdOM0Fp0o2GIBUaFGcouPwvdnLrYCe43iAVGz
pqYeYSiLMPpFleYIBXLMf3aBqYUhAkEAutUj47GcC09mGQcgQEFOkKhWXloy5ERg
ixSngtbYoCbWhytq+9A2zFZS0cGWLoudPeTAF0Blke74HddvLymacQJBALrbUyct
DOPupkDtGl3vN1fAefazMgcn5IfQfVvX6yCu4A7n+qr6G5cHAMlMeEAqdFCLmF+f
NM+VtU//T1kQpvE=
-----END PRIVATE KEY-----';
    const MERCHANT_C_PUBLIC_KEY_STR = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDatQ6W6EjzO2HsfSmNeFQt7iAT
FHYZ0W5URuWPyPAvKnsMJz/vPpYVi1C1cvE/Sguz24qA6819Jr+HyhMADiyCohia
l/zmTGPztP0rXGEHbU5MuQAHrFcDcOwgWcjtHggOV/XxNbmAJf/AwToSfQKkmsJ2
PE1lYJXINxgETj88uwIDAQAB
-----END PUBLIC KEY-----';
    /**
     * 商户系统B端 SERVER端私钥与客户端公钥
     */
    const MERCHANT_B_PRIVATE_KEY_STR = '-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKtuzhX9pEdN2Dth
XMJCEvSsn7sohoPgtzD9jB9pdkhyoQDqUL8NkPPn6qeFQUr/SzxloqXcxpsP3iWJ
yJNCdRIpDh9YUQWEG8qn9pncVEtzZgGt1wwOXrkxwgzS2tNmtgvOO/nqbZouAWoE
pEkZDZmexAH2qqKb+swz3KSH41UBAgMBAAECgYAqFfzAB1HCM4knIsLb6c6vhIV+
M/e5/nvaqhQxTfm81W9TQzLphFIWntPLpnoeCEiXHjhs0aNsQ9v8iTPVexY0JSpn
5unyhJKo5mENNFjplWBhQKRbTH3YZlODeSCPm+D0+PdWmOXOP6Ytz0UBhdPRN/yH
eab3IGxlHpUYWTO1pQJBANtLNIYgAQhW1OWVPnw+K8K4HBqBefcgvE2gXW410l2e
b+LPKHNJdSD2jfQ3vL1S30dNF4Le6xHZ9gO/RZbMiLcCQQDIIL8LIAyK1bD9PNjA
ZZY9+VK6XxId+Gyuu+cKlb/GhoO4L2QR9B8b1VN5B3MwYY8lI/Y9Zz1JDtD0E8b/
iSgHAkAmgBOeoKvNvQDvtb4crgWc0BoPBUBWhObKcic1HDnsuc5G8bvWUcVAnkjZ
4Zc/XfdZW02Pane20J+ClOgwy4QNAkBc29zpQ5iuPtMd3cLRGxHodaxuL7jPUTrU
pPliTvOqITYzG0I6lmRs3MIbkVpgY5Qw7ovOF/42zPollpuqbDC3AkEAqY4lGPbT
g1uiYbiGVbBNMdWIMDU1igfgA5kcSpV/H32HBbDBFRMeQRj8sA1Odr2x1NoQ4kmr
v7eca+YO5jyZoQ==
-----END PRIVATE KEY-----';
    const MERCHANT_B_PUBLIC_KEY_STR = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD2RdTxS2mxmFQUDSeBvUr4wTTX
ugBJw71/jXXo1l5mB4SOhP0fW7UwZSb3myfCMFJZQnCFdxY8LCFvEZYz4f/o8wVA
mDIZoqwIClqMBt2uJvAa4eVwn1Zr1GOnaYs+X8wakZUyIYvQgn98tr2EwN11u4ek
GeBFb3ObYV22i+jziwIDAQAB
-----END PUBLIC KEY-----';
    /**
     * TEST SERVER端私钥与客户端公钥
     */
    const TEST_PRIVATE_KEY_STR = '-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAPUJqTt1IsuidXzF
qgImn0bYxuNgC4LGku6NMS8VkYeypnGbRqwyQVMcJKYqMqoacgtW3ImiahAfadUT
suxA6YaWRploRCshZlpqncCjS5TxC/95vwsz7Wm16vMft+gYrw2pqwMjLcP2y5bG
ppXUMtKs1d26VSisiBcPLNdOzEZVAgMBAAECgYAqqjL4Mk4LrM7OGdCfLUBgYpBG
uMtoStD8jkL5EsVTHk0SzNmCVAHByc2rzP8jVRV0WfxuToQvKHkR66skray7NijW
2hxkte/mBvGKGbLRvGo08EGFDTP+REdR9s322k6BCg7KH7aXJUlcpWmEbBGuWlXt
L/0pMQJBYH+kcIEJIQJBAPvgA6nZAPyMCMeIEUYQmiRy66VWN8LxYsk3kP1MqyCY
uKE8YDhAwV256r7362VXiouZ2kYG57ZnTqOjYX+vS8kCQQD5DPs3VcQgfKIc9Waa
kW62hhFIxFRPsNDrLzdfGxZgLN7+Ej9AnAwXKXQ9kPdZBoanhWKOWCSwrutPrEHq
LlQtAkAD9l84YdCRKIbO1MYoywQRxLkOTc/swi1iqvwd8AHVLnHhH3kICYTBO7aE
sJPEcV8dmRsE9QDaLr/e9SgIgTJ5AkEAsIo7KaZqOH0gjVaHPNoKmOfAKMzC1xqH
fa8imRAidFpaV8+ndq0nBOQlud6g90JhAS7UBgMFPxk/RGLe9pmQoQJARGiilRNq
wQKlGXa9UTZANZkSVdPOSLfFsfqdvEkKCNHA4S3yIM1lDFB0MiooT8RsFJ2vsShr
6QnQQiRBFV4M0Q==
-----END PRIVATE KEY-----';
    const TEST_PUBLIC_KEY_STR = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC203n7eo7f4eIs9P6RUIxuKQZP
WfnAeW2OpRs5AnxtUBBLKLdKtuEuZclb7Nqt/tncSuAb63p4Zt/a7JQ7nPE24dMk
mnRjVUtXBgEF0A9xt2QVNMQovtjJ2rkg43gVByDKbOsUqbJYjA12IpALMdECHCMl
817QbgfnBbuIvzbImQIDAQAB
-----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);
    }
}
