OpensslService.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. <?php
  2. namespace app\common\service;
  3. class OpensslService
  4. {
  5. /**
  6. * openssl加密
  7. * @param type $companyCode
  8. * @param type $data
  9. * @return type
  10. */
  11. public static function encryptByPrivateKey($companyCode,$data) {
  12. //这个函数可用来判断私钥是否是可用的,可用返回资源id Resource id
  13. $priKey = file_get_contents("COMPANY_LIST/$companyCode/jd/my_rsa_private_pkcs8_key.pem");
  14. $privateKey = wordwrap($priKey, 64, "\n", true);
  15. $privateKeyStr = "-----BEGIN RSA PRIVATE KEY-----\n"
  16. . "$privateKey"
  17. . "\n-----END RSA PRIVATE KEY-----";
  18. $opensslPriKey = openssl_pkey_get_private($privateKeyStr);
  19. $encrypted="";
  20. openssl_private_encrypt($data,$encrypted,$opensslPriKey,OPENSSL_PKCS1_PADDING);//私钥加密
  21. $encrypted = base64_encode($encrypted);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的
  22. return $encrypted;
  23. }
  24. /**
  25. * openssl解密
  26. * @param type $companyCode
  27. * @param type $data
  28. * @return string
  29. */
  30. public static function decryptByPublicKey($companyCode,$data) {
  31. //这个函数可用来判断公钥是否是可用的,可用返回资源id Resource id
  32. $pubKey = file_get_contents("COMPANY_LIST/$companyCode/jd/wy_rsa_public_key.pem");
  33. $publicKey = wordwrap($pubKey, 64, "\n", true);
  34. $publicKeyStr = "-----BEGIN PUBLIC KEY-----\n"
  35. . "$publicKey"
  36. . "\n-----END PUBLIC KEY-----";
  37. $decrypted = "";
  38. $data = base64_decode($data);
  39. $opensslPubKey = openssl_pkey_get_public($publicKeyStr);
  40. openssl_public_decrypt($data,$decrypted,$opensslPubKey,OPENSSL_PKCS1_PADDING);//公钥解密
  41. return $decrypted;
  42. }
  43. /**
  44. * 转换一个String字符串为byte数组
  45. * @param $str 需要转换的字符串
  46. * @param $bytes 目标byte数组
  47. */
  48. private static function getBytes($string) {
  49. $bytes = array ();
  50. for($i = 0; $i < strlen ( $string); $i ++) {
  51. $bytes [] = ord($string[$i]);
  52. }
  53. return $bytes;
  54. }
  55. /**
  56. * 转换一个int为byte数组
  57. * @param $byt 目标byte数组
  58. * @param $val 需要转换的字符串
  59. */
  60. private static function integerToBytes($val) {
  61. $byt = array ();
  62. $byt [0] = ($val >> 24 & 0xff);
  63. $byt [1] = ($val >> 16 & 0xff);
  64. $byt [2] = ($val >> 8 & 0xff);
  65. $byt [3] = ($val & 0xff);
  66. return $byt;
  67. }
  68. /**
  69. * 将元数据进行补位后进行3DES加密
  70. * <p/>
  71. * 补位后 byte[] = 描述有效数据长度(int)的byte[]+原始数据byte[]+补位byte[]
  72. *
  73. * @param
  74. * sourceData 元数据字符串
  75. * @return 返回3DES加密后的16进制表示的字符串
  76. */
  77. public static function encrypt2HexStr($keys, $sourceData) {
  78. $source = [];
  79. // 元数据
  80. $source = self::getBytes($sourceData);
  81. // 1.原数据byte长度
  82. $merchantData = count($source);
  83. // 2.计算补位
  84. $x = ($merchantData + 4) % 8;
  85. $y = ($x == 0) ? 0 : (8 - $x);
  86. // echo ("需要补位 :" . $y . "<br/>");
  87. // 3.将有效数据长度byte[]添加到原始byte数组的头部
  88. $sizeByte = self::integerToBytes($merchantData);
  89. $resultByte = array ();
  90. for($i = 0; $i < 4; $i ++) {
  91. $resultByte [$i] = $sizeByte [$i];
  92. }
  93. //var_dump($sizeByte);
  94. // 4.填充补位数据
  95. for($j = 0; $j < $merchantData; $j ++) {
  96. $resultByte [4 + $j] = $source [$j];
  97. }
  98. //var_dump($resultByte);
  99. for($k = 0; $k < $y; $k ++) {
  100. $resultByte [$merchantData + 4 + $k] = 0x00;
  101. }
  102. $desdata = self::encrypt (self::toStr($resultByte), $keys);
  103. return self::strToHex($desdata);
  104. }
  105. /**
  106. * 转换一个16进制hexString字符串为十进制byte数组
  107. *
  108. * @param $hexString 需要转换的十六进制字符串
  109. * @return 一个byte数组
  110. *
  111. */
  112. private static function hexStrToBytes($hexString) {
  113. $bytes = array ();
  114. for($i = 0; $i < strlen ( $hexString ) - 1; $i += 2) {
  115. $bytes [$i / 2] = hexdec ( $hexString [$i] . $hexString [$i + 1] ) & 0xff;
  116. }
  117. return $bytes;
  118. }
  119. public static function decrypt4HexStr($keys, $data) {
  120. $hexSourceData = [];
  121. $hexSourceData = self::hexStrToBytes($data);
  122. // 解密
  123. $unDesResult = self::decrypt(self::toStr($hexSourceData),$keys);
  124. //echo $unDesResult;
  125. $unDesResultByte = self::getBytes($unDesResult);
  126. //var_dump($unDesResultByte);
  127. $dataSizeByte = array ();
  128. for($i = 0; $i < 4; $i ++) {
  129. $dataSizeByte [$i] = $unDesResultByte [$i];
  130. }
  131. // 有效数据长度
  132. $dsb = self::byteArrayToInt($dataSizeByte, 0);
  133. $tempData = array ();
  134. for($j = 0; $j < $dsb; $j++) {
  135. $tempData [$j] = $unDesResultByte [4 + $j];
  136. }
  137. return self::hexTobin(self::bytesToHex($tempData));
  138. }
  139. // 字符串转16进制
  140. private static function bytesToHex($bytes) {
  141. $str = self::toStr( $bytes );
  142. return self::strToHex ( $str );
  143. }
  144. /**
  145. * @param unknown $hexstr
  146. * @return Ambigous <string, unknown>
  147. */
  148. private static function hexTobin($hexstr)
  149. {
  150. $n = strlen($hexstr);
  151. $sbin="";
  152. $i=0;
  153. while($i<$n)
  154. {
  155. $a =substr($hexstr,$i,2);
  156. $c = pack("H*",$a);
  157. if ($i==0){$sbin=$c;}
  158. else {$sbin.=$c;}
  159. $i+=2;
  160. }
  161. return $sbin;
  162. }
  163. /**
  164. * 将byte数组 转换为int
  165. * @param b
  166. * @param offset 位游方式
  167. * @return
  168. */
  169. private static function byteArrayToInt($b, $offset) {
  170. $value = 0;
  171. for($i = 0; $i < 4; $i ++) {
  172. $shift = (4 - 1 - $i) * 8;
  173. $value = $value + ($b [$i + $offset] & 0x000000FF) << $shift; // 往高位游
  174. }
  175. return $value;
  176. }
  177. /**
  178. * 将十进制字符串转换为十六进制字符串
  179. *
  180. * @param $string 需要转换字符串
  181. * @return 一个十六进制字符串
  182. */
  183. private static function strToHex($string) {
  184. $hex = "";
  185. for($i = 0; $i < strlen ( $string ); $i ++) {
  186. $tmp = dechex ( ord ( $string [$i] ) );
  187. if (strlen ( $tmp ) == 1) {
  188. $hex .= "0";
  189. }
  190. $hex .= $tmp;
  191. }
  192. $hex = strtolower ( $hex );
  193. return $hex;
  194. }
  195. /**
  196. * 将字节数组转化为String类型的数据
  197. * @param $bytes 字节数组
  198. * @param $str 目标字符串
  199. *
  200. * @return 一个String类型的数据
  201. */
  202. private static function toStr($bytes) {
  203. $str = '';
  204. foreach ( $bytes as $ch ) {
  205. $str .= chr ( $ch );
  206. }
  207. return $str;
  208. }
  209. // 加密算法
  210. private static function encrypt($input, $key) {
  211. $size = mcrypt_get_block_size ('des', 'ecb');
  212. $td = mcrypt_module_open ( MCRYPT_3DES, '', 'ecb', '');
  213. $iv = @mcrypt_create_iv ( mcrypt_enc_get_iv_size ( $td ), MCRYPT_RAND );
  214. // 使用MCRYPT_3DES算法,cbc模式
  215. @mcrypt_generic_init ( $td, $key, $iv );
  216. // 初始处理
  217. $data = mcrypt_generic ( $td, $input );
  218. // 加密
  219. mcrypt_generic_deinit ( $td );
  220. // 结束
  221. mcrypt_module_close ( $td );
  222. return $data;
  223. }
  224. private static function decrypt($encrypted, $key) {
  225. //$encrypted = base64_decode($encrypted);
  226. $td = mcrypt_module_open ( MCRYPT_3DES, '', 'ecb', '' ); // 使用MCRYPT_DES算法,cbc模式
  227. $iv = @mcrypt_create_iv ( mcrypt_enc_get_iv_size ( $td ), MCRYPT_RAND );
  228. $ks = mcrypt_enc_get_key_size ( $td );
  229. @mcrypt_generic_init ( $td, $key, $iv ); // 初始处理
  230. $decrypted = mdecrypt_generic ( $td, $encrypted ); // 解密
  231. mcrypt_generic_deinit ( $td ); // 结束
  232. mcrypt_module_close ( $td );
  233. return $decrypted;
  234. }
  235. /**
  236. * 京东的证书请求
  237. * @param type $cacert 证书目录
  238. * @param type $url 请求地址
  239. * @param type $dataString
  240. * @return type
  241. */
  242. public static function httpPostData($cacert,$url,$dataString) {
  243. //$cacert = ''; //CA根证书 (目前暂不提供)
  244. $CA = false ; //HTTPS时是否进行严格认证
  245. $TIMEOUT = 30; //超时时间(秒)
  246. $SSL = substr($url, 0, 8) == "https://" ? true : false;
  247. $ch = curl_init ();
  248. if ($SSL && $CA) {
  249. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);//只信任CA颁布的证书
  250. curl_setopt($ch, CURLOPT_CAINFO, $cacert); //CA根证书(用来验证的网站证书是否是CA颁布)
  251. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); //检查证书中是否设置域名,并且是否与提供的主机名匹配
  252. } else if ($SSL && !$CA) {
  253. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //信任任何证书
  254. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); //检查证书中是否设置域名
  255. }
  256. curl_setopt ( $ch, CURLOPT_TIMEOUT, $TIMEOUT);
  257. curl_setopt ( $ch, CURLOPT_CONNECTTIMEOUT, $TIMEOUT-2);
  258. curl_setopt ( $ch, CURLOPT_POST, 1 );
  259. curl_setopt ( $ch, CURLOPT_URL, $url );
  260. curl_setopt ( $ch, CURLOPT_POSTFIELDS, $dataString);
  261. curl_setopt ( $ch, CURLOPT_HTTPHEADER, [
  262. 'Content-Type:application/xml;charset=utf-8',
  263. 'Content-Length:' . strlen($dataString)
  264. ]);
  265. ob_start();
  266. curl_exec($ch);
  267. $return_content = ob_get_contents();
  268. ob_end_clean();
  269. $return_code = curl_getinfo ($ch, CURLINFO_HTTP_CODE);
  270. return array (
  271. $return_code,
  272. $return_content
  273. );
  274. }
  275. }