JimChenWYU /
TimSDK
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * Created by PhpStorm. |
||
| 4 | * User: lenovo |
||
| 5 | * Date: 6/12/2018 |
||
| 6 | * Time: 10:31 AM |
||
| 7 | */ |
||
| 8 | |||
| 9 | namespace TimSDK\Core; |
||
| 10 | |||
| 11 | use TimSDK\Core\Exceptions\UserSigException; |
||
| 12 | use TimSDK\Core\Exceptions\OpensslException; |
||
| 13 | |||
| 14 | /** |
||
| 15 | * Class TLSSigApi |
||
| 16 | * @package TimSDK\Service |
||
| 17 | */ |
||
| 18 | class TLSSig |
||
| 19 | { |
||
| 20 | private $private_key = false; |
||
| 21 | private $public_key = false; |
||
| 22 | private $appid; |
||
| 23 | |||
| 24 | /** |
||
| 25 | * 设置Appid |
||
| 26 | * @param type $appid |
||
| 27 | */ |
||
| 28 | public function setAppid($appid) |
||
| 29 | { |
||
| 30 | $this->appid = $appid; |
||
| 31 | } |
||
| 32 | |||
| 33 | /** |
||
| 34 | * 设置私钥 如果要生成usersig则需要私钥 |
||
| 35 | * @param string $private_key 私钥文件内容 |
||
| 36 | * @return bool 是否成功 |
||
| 37 | */ |
||
| 38 | public function setPrivateKey($private_key) |
||
| 39 | { |
||
| 40 | $this->private_key = openssl_pkey_get_private($private_key); |
||
|
0 ignored issues
–
show
|
|||
| 41 | if ($this->private_key === false) { |
||
| 42 | throw new OpensslException(openssl_error_string()); |
||
| 43 | } |
||
| 44 | return true; |
||
| 45 | } |
||
| 46 | |||
| 47 | /** |
||
| 48 | * 设置公钥 如果要验证usersig则需要公钥 |
||
| 49 | * @param string $public_key 公钥文件内容 |
||
| 50 | * @return bool 是否成功 |
||
| 51 | */ |
||
| 52 | public function setPublicKey($public_key) |
||
| 53 | { |
||
| 54 | $this->public_key = openssl_pkey_get_public($public_key); |
||
|
0 ignored issues
–
show
It seems like
openssl_pkey_get_public($public_key) of type resource is incompatible with the declared type boolean of property $public_key.
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. Loading history...
|
|||
| 55 | if ($this->public_key === false) { |
||
| 56 | throw new OpensslException(openssl_error_string()); |
||
| 57 | } |
||
| 58 | return true; |
||
| 59 | } |
||
| 60 | |||
| 61 | /** |
||
| 62 | * 用于url的base64encode |
||
| 63 | * '+' => '*', '/' => '-', '=' => '_' |
||
| 64 | * @param string $string 需要编码的数据 |
||
| 65 | * @return string 编码后的base64串,失败返回false |
||
| 66 | */ |
||
| 67 | View Code Duplication | private function base64Encode($string) |
|
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 68 | { |
||
| 69 | static $replace = array('+' => '*', '/' => '-', '=' => '_'); |
||
| 70 | $base64 = base64_encode($string); |
||
| 71 | if ($base64 === false) { |
||
| 72 | throw new OpensslException('base64_encode error'); |
||
| 73 | } |
||
| 74 | return str_replace(array_keys($replace), array_values($replace), $base64); |
||
| 75 | } |
||
| 76 | |||
| 77 | /** |
||
| 78 | * 用于url的base64decode |
||
| 79 | * '+' => '*', '/' => '-', '=' => '_' |
||
| 80 | * @param string $base64 需要解码的base64串 |
||
| 81 | * @return string 解码后的数据,失败返回false |
||
| 82 | */ |
||
| 83 | View Code Duplication | private function base64Decode($base64) |
|
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 84 | { |
||
| 85 | static $replace = array('+' => '*', '/' => '-', '=' => '_'); |
||
| 86 | $string = str_replace(array_values($replace), array_keys($replace), $base64); |
||
| 87 | $result = base64_decode($string); |
||
| 88 | if ($result == false) { |
||
|
0 ignored issues
–
show
|
|||
| 89 | throw new OpensslException('base64_decode error'); |
||
| 90 | } |
||
| 91 | return $result; |
||
| 92 | } |
||
| 93 | |||
| 94 | /** |
||
| 95 | * 根据json内容生成需要签名的buf串 |
||
| 96 | * @param array $json 票据json对象 |
||
| 97 | * @return string 按标准格式生成的用于签名的字符串 |
||
| 98 | * 失败时返回false |
||
| 99 | */ |
||
| 100 | private function genSignContent(array $json) |
||
| 101 | { |
||
| 102 | static $members = array( |
||
| 103 | 'TLS.appid_at_3rd', |
||
| 104 | 'TLS.account_type', |
||
| 105 | 'TLS.identifier', |
||
| 106 | 'TLS.sdk_appid', |
||
| 107 | 'TLS.time', |
||
| 108 | 'TLS.expire_after' |
||
| 109 | ); |
||
| 110 | $content = ''; |
||
| 111 | foreach ($members as $member) { |
||
| 112 | if (!isset($json[$member])) { |
||
| 113 | throw new OpensslException('json need ' . $member); |
||
| 114 | } |
||
| 115 | $content .= "{$member}:{$json[$member]}\n"; |
||
| 116 | } |
||
| 117 | return $content; |
||
| 118 | } |
||
| 119 | |||
| 120 | /** |
||
| 121 | * ECDSA-SHA256签名 |
||
| 122 | * @param string $data 需要签名的数据 |
||
| 123 | * @return string 返回签名 失败时返回false |
||
| 124 | */ |
||
| 125 | private function sign($data) |
||
| 126 | { |
||
| 127 | $signature = ''; |
||
| 128 | if (!openssl_sign($data, $signature, $this->private_key, 'sha256')) { |
||
| 129 | throw new OpensslException(openssl_error_string()); |
||
| 130 | } |
||
| 131 | return $signature; |
||
| 132 | } |
||
| 133 | |||
| 134 | /** |
||
| 135 | * 验证ECDSA-SHA256签名 |
||
| 136 | * @param string $data 需要验证的数据原文 |
||
| 137 | * @param string $sig 需要验证的签名 |
||
| 138 | * @return int 1验证成功 0验证失败 |
||
| 139 | */ |
||
| 140 | private function verify($data, $sig) |
||
| 141 | { |
||
| 142 | $ret = openssl_verify($data, $sig, $this->public_key, 'sha256'); |
||
| 143 | if ($ret == -1) { |
||
| 144 | throw new OpensslException(openssl_error_string()); |
||
| 145 | } |
||
| 146 | return $ret; |
||
| 147 | } |
||
| 148 | |||
| 149 | /** |
||
| 150 | * 生成usersig |
||
| 151 | * @param string $identifier 用户名 |
||
| 152 | * @param uint $expire usersig有效期 默认为180天, 180 * 24 * 3600, 单位秒 |
||
| 153 | * @return string 生成的UserSig 失败时为false |
||
| 154 | */ |
||
| 155 | public function genSig($identifier, $expire = 15552000) |
||
| 156 | { |
||
| 157 | $json = array( |
||
| 158 | 'TLS.account_type' => '0', |
||
| 159 | 'TLS.identifier' => (string) $identifier, |
||
| 160 | 'TLS.appid_at_3rd' => '0', |
||
| 161 | 'TLS.sdk_appid' => (string) $this->appid, |
||
| 162 | 'TLS.expire_after' => (string) $expire, |
||
| 163 | 'TLS.version' => '201512300000', |
||
| 164 | 'TLS.time' => (string) time() |
||
| 165 | ); |
||
| 166 | $err = ''; |
||
| 167 | $content = $this->genSignContent($json, $err); |
||
|
0 ignored issues
–
show
The call to
TLSSig::genSignContent() has too many arguments starting with $err.
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. In this case you can add the Loading history...
|
|||
| 168 | $signature = $this->sign($content, $err); |
||
|
0 ignored issues
–
show
The call to
TLSSig::sign() has too many arguments starting with $err.
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. In this case you can add the Loading history...
|
|||
| 169 | $json['TLS.sig'] = base64_encode($signature); |
||
| 170 | if ($json['TLS.sig'] === false) { |
||
| 171 | throw new UserSigException('base64_encode error'); |
||
| 172 | } |
||
| 173 | $json_text = json_encode($json); |
||
| 174 | if ($json_text === false) { |
||
| 175 | throw new UserSigException('json_encode error'); |
||
| 176 | } |
||
| 177 | $compressed = gzcompress($json_text); |
||
| 178 | if ($compressed === false) { |
||
| 179 | throw new UserSigException('gzcompress error'); |
||
| 180 | } |
||
| 181 | return $this->base64Encode($compressed); |
||
| 182 | } |
||
| 183 | |||
| 184 | /** |
||
| 185 | * 验证usersig |
||
| 186 | * @param type $sig usersig |
||
| 187 | * @param type $identifier 需要验证用户名 |
||
| 188 | * @param type $init_time usersig中的生成时间 |
||
| 189 | * @param type $expire_time usersig中的有效期 如:3600秒 |
||
| 190 | * @param type $error_msg 失败时的错误信息 |
||
| 191 | * @return boolean 验证是否成功 |
||
| 192 | */ |
||
| 193 | public function verifySig($sig, $identifier, &$init_time, &$expire_time, &$error_msg) |
||
| 194 | { |
||
| 195 | try { |
||
| 196 | $error_msg = ''; |
||
| 197 | $decoded_sig = $this->base64Decode($sig); |
||
| 198 | $uncompressed_sig = gzuncompress($decoded_sig); |
||
| 199 | if ($uncompressed_sig === false) { |
||
| 200 | throw new UserSigException('gzuncompress error'); |
||
| 201 | } |
||
| 202 | $json = json_decode($uncompressed_sig); |
||
| 203 | if ($json == false) { |
||
| 204 | throw new UserSigException('json_decode error'); |
||
| 205 | } |
||
| 206 | $json = (array) $json; |
||
| 207 | if ($json['TLS.identifier'] !== $identifier) { |
||
| 208 | throw new UserSigException("identifier error sigid:{$json['TLS.identifier']} id:{$identifier}"); |
||
| 209 | } |
||
| 210 | if ($json['TLS.sdk_appid'] != $this->appid) { |
||
| 211 | throw new UserSigException("appid error sigappid:{$json['TLS.appid']} thisappid:{$this->appid}"); |
||
| 212 | } |
||
| 213 | $content = $this->genSignContent($json); |
||
| 214 | $signature = base64_decode($json['TLS.sig']); |
||
| 215 | if ($signature == false) { |
||
|
0 ignored issues
–
show
|
|||
| 216 | throw new UserSigException('sig json_decode error'); |
||
| 217 | } |
||
| 218 | $succ = $this->verify($content, $signature); |
||
| 219 | if (!$succ) { |
||
| 220 | throw new UserSigException('verify failed'); |
||
| 221 | } |
||
| 222 | $init_time = $json['TLS.time']; |
||
| 223 | $expire_time = $json['TLS.expire_after']; |
||
| 224 | return true; |
||
| 225 | } catch (UserSigException $ex) { |
||
| 226 | $error_msg = $ex->getMessage(); |
||
| 227 | return false; |
||
| 228 | } |
||
| 229 | } |
||
| 230 | } |
||
| 231 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..