<?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-----';

    /**
     * 商户系统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-----';
    /**
     * 商户系统C端-测试 SERVER端私钥与客户端公钥
     */
    const TEST_MERCHANT_C_PRIVATE_KEY_STR = '-----BEGIN PRIVATE KEY-----
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMX9eY3yNnhcRt0I
f//WJvVztaqT7GTkwDDxSeUgtbyXGjOKz9Mgahkk5lWyAlLqKXUpd+5Fksue5YWU
LL6OogoiTBNNNsPWoc9l0Wj0KKVdK3ZjnICZEz1LmjiLa++rAB/7fMYUbs6cRtK8
Nl8n9a6cjReYaW9r7tb/pSdC+T0HAgMBAAECgYEAmxEwn/UhplkXg0yB+909fCaZ
FTVwA4GJ6YtBxfw9eqyZ7957cS9FCdZ1tI6L9WbC+6lz7iF9nI8h0uI/vSu3Snm/
MFYGkcsolDBFYsTPru5GouHh4bW6X5Ge6fmz7JgGaqzOtsbD5oh7zN9SsUUb0jqM
9zR5qbw5i8Krut66zGECQQDo8CmWy5jtSJ7wUGBVECHX4dPO2lwyAC13u4Pat8dg
8YA6VzdzzHdhlWLaGuPICKPjBwxVxP6qKT8bPiAYeIgXAkEA2ZeNYQ8lN5v+hosR
dU3FVwva3d7OmIT7unEMk2Nav1YqUHLektsAYZQW1kOtfUvmtWXlba34a7E8FRow
Wt4YkQJBAJYF/7MoQ8EnUX5TNgfzEOj6gDEsf86QQLhpo91dGeM9ByoL/CHvoT/P
N9BjGys9LVhNtMsUyjQLxqIkHAXGs1cCQQDF4+olkpOjfpC+Ji5Lg95sqxBzZlZ4
KcGSr4vjY6G9kAzNu5qm7tvq4rbeSRC4elYpNbGxzV23+6mL+5Rsn76xAkBmABwk
XXLMgdt6NG4x3cM4WeMPbJPWHOXRLRRMukDGW+HklFkpHFbuGSXv+FkjCWhnE9QX
98wubX4hRtsNX8UH
-----END PRIVATE KEY-----';
    const TEST_MERCHANT_C_PUBLIC_KEY_STR = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKTlW0/1dpGK2FeUHvOf1Vus7g
yy4Yx6r0JTtZUfC0u7/Tr/2DaD4xt+OLOW/mY158azfHJO1yBIhSyxi9sKILmiV5
fpbAOKUeRJelNa6tXC+1E8dooh+s1NmZaGXn2F6HK0OtU5Qc/Ebqunm+re8Ek2lN
2ezqViipdMY2tosl2QIDAQAB
-----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-----';
    /**
     * 商户系统B端-测试 SERVER端私钥与客户端公钥
     */
    const TEST_MERCHANT_B_PRIVATE_KEY_STR = '-----BEGIN PRIVATE KEY-----
MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAKQGB1lqs3dCTGGj
qONSu5gMBucejojaF23073kIBdwfzZYSxZWw0P+YaXU6JkE8JCaaakNhTNuJmntG
3RBBJe1xaeWZo4Jca2SGy0cR0uMM5mAMtBL2AZ/1RU+D2CKbBl9H0uxB4FF+td2g
Q/C/spKDX4CDQGe1wZxr3Cyh11/JAgMBAAECgYEAoO7BWzxT5dmI8+wOEyzjnuV+
CFp041WI03wVUp1KkpYpsuusLZkVFxNFtZ1eV3dYyP+M75uSO30hs37t+7rQKDyD
9H+WzJCqe5KR5J7xvs5DWuXLCzgNYq8KdXYk+Zy8RuwB9eaWcy1F/i2dYxoz3JUw
Xsmu36Mp994bJJsLKAECQQDRA8quM9YzMXoBd/QTTw5pzKFlrNl+7eF2SMNOdCZB
IVjfOh3/d39A1I46HsvMfd1L9DMvcgz8J3/RK0/iNVWBAkEAyOUeJXH/NhbfXHr4
633DpS+jBKywCYkdhqJEh0Q3dRg/qk6q+9I2f2wS1JPmGq4FMeOxrXjpjAK97Djb
k8z+SQJBAM10obXNZJ/b4acx521Xh75+FKSiXQVFBhxEeB9VUwkwo3CCa1xkdWUf
y1LcVM6FZpOzzuCzhooStbTBk3uzm4ECQQCJWMuhgiyfyEdxLMneBp+p4cWsPnwk
KNA86de8OxFHRwrP3vTbMb78ouDE4VDiULNQhoFFPnM9u+opBD5q8C2xAkEAv2W3
fw+LtVaDnpfWWCN5y6W4gzRtfdSdSvsZpS+EY/RG0cpmN+WR+86ft3WdIIr2Bnm4
RcPnfPSsz3dgAaCR2A==
-----END PRIVATE KEY-----';
    const TEST_MERCHANT_B_PUBLIC_KEY_STR = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+2roRCWyvIl04NtZnNxyYPLAP
nM+7fL+6wGhhc3ilqk4zgr+hxdftUJ30NDkTqjbWe4wvd4ax1xVAS4la5PAK6g5W
BEFar4gu3JgkmyfT3NtwXCd7kZuH98k/7oSVQbxYc9ydwoqwDdXoIVOKtK5YWkoL
+WjPxg37zWCi3Wq5dQIDAQAB
-----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,
        ],
        'merchant-c' => [
            'pub_key' => self::MERCHANT_C_PUBLIC_KEY_STR,
            'pri_key' => self::MERCHANT_C_PRIVATE_KEY_STR,
        ],
        'test-merchant-c' => [
            'pub_key' => self::TEST_MERCHANT_C_PUBLIC_KEY_STR,
            'pri_key' => self::TEST_MERCHANT_C_PRIVATE_KEY_STR,
        ],
        'merchant-b' => [
            'pub_key' => self::MERCHANT_B_PUBLIC_KEY_STR,
            'pri_key' => self::MERCHANT_B_PRIVATE_KEY_STR,
        ],
        'test-merchant-b' => [
            'pub_key' => self::TEST_MERCHANT_B_PUBLIC_KEY_STR,
            'pri_key' => self::TEST_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);
    }
}
