OpenSSLVerify.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <?php
  2. namespace loyalsoft;
  3. /**
  4. * 使用openssl实现非对称加密,用于安全的通讯中,
  5. * 可进行签名/验签, 加密/解密
  6. * @author gwang email:wanggangzero@qq.com
  7. * @copyright © 2015-12-3, SJZ LoyalSoft Corporation & gwang. All rights reserved.
  8. */
  9. class MyRsa
  10. {
  11. /**
  12. * 测试
  13. */
  14. public static function Test()
  15. {
  16. $path = __DIR__ . DIRECTORY_SEPARATOR . "key";
  17. $msRsa = new MyRsa($path);
  18. // $msRsa->createKey();
  19. $data = "中华人民共和国";
  20. echo "data: $data";
  21. $crypted = $msRsa->privEncrypt($data);
  22. echo "encrypted: $crypted";
  23. $decrypted = $msRsa->pubDecrypt($crypted);
  24. echo "decrypted: $decrypted";
  25. unset($msRsa);
  26. }
  27. // 测试签名/验签
  28. public static function testSign()
  29. {
  30. $path = __DIR__ . DIRECTORY_SEPARATOR . "key";
  31. $msRsa = new MyRsa($path);
  32. // $msRsa->createKey();
  33. $data = "中华人民共和国";
  34. echoLine("data: $data");
  35. $sign = $msRsa->sign_str($data);
  36. echoLine("sign: $sign");
  37. $verify = $msRsa->verify($data, $sign);
  38. echoLine("verify : $verify");
  39. unset($msRsa);
  40. }
  41. private $_privKey;
  42. private $_pubKey;
  43. private $_keyPath; // 密钥保存路径
  44. /**
  45. * 构造函数
  46. * @param string $path 密钥保存路径
  47. */
  48. public function __construct($path)
  49. {
  50. if (empty($path) || !is_dir($path)) {
  51. throw new \Exception('Must set the keys save path');
  52. } $this->_keyPath = $path;
  53. }
  54. /**
  55. * 创建密钥对,保存到 $this->_keyPath
  56. * @deprecated since version now() 还是用OpenSSL工具生成秘钥吧, 这个函数生成的C#不认, 不知道为什么.-gwang 2018年1月19日14:17:48
  57. * */
  58. public function createKey()
  59. {
  60. //参数设置
  61. $config = [
  62. "digest_alg" => "sha512",
  63. //文件路径根据自己的要求进行填充
  64. // "config" => "./conf/openssl.cnf",
  65. //字节数 512 1024 2048 4096 等
  66. "private_key_bits" => 1024,
  67. //加密类型
  68. "private_key_type" => OPENSSL_KEYTYPE_RSA,
  69. ];
  70. $r = openssl_pkey_new($config);
  71. openssl_pkey_export($r, $privKey);
  72. $tsday = TimeUtil::dtToday();
  73. file_put_contents($this->_keyPath . DIRECTORY_SEPARATOR . "key.$tsday.pem", $privKey);
  74. $this->_privKey = openssl_pkey_get_public($privKey);
  75. $rp = openssl_pkey_get_details($r);
  76. $pubKey = $rp['key'];
  77. file_put_contents($this->_keyPath . DIRECTORY_SEPARATOR . "pub.$tsday.pem", $pubKey);
  78. $this->_pubKey = openssl_pkey_get_public($pubKey);
  79. }
  80. /*
  81. * setup the private key
  82. */
  83. public function setupPrivKey()
  84. {
  85. if (is_resource($this->_privKey)) {
  86. return true;
  87. }
  88. $file = $this->_keyPath . DIRECTORY_SEPARATOR . 'key.pem';
  89. $prk = file_get_contents($file);
  90. $this->_privKey = openssl_pkey_get_private($prk);
  91. return true;
  92. }
  93. /**
  94. * setup the public key
  95. */
  96. public function setupPubKey()
  97. {
  98. if (is_resource($this->_pubKey)) {
  99. return true;
  100. }
  101. $file = $this->_keyPath . DIRECTORY_SEPARATOR . 'pub.pem';
  102. $puk = file_get_contents($file);
  103. $this->_pubKey = openssl_pkey_get_public($puk);
  104. return true;
  105. }
  106. /**
  107. * 生成签名
  108. * @param array $params
  109. * @return string sign with base64 encoded
  110. */
  111. public function sign_arr($params)
  112. {
  113. $content = "";
  114. if ($params) {
  115. ksort($params);
  116. $i = 0;
  117. foreach ($params as $key => $value) {
  118. if ($key != "sign") {
  119. $content .= ($i == 0 ? '' : '&') . $key . '=' . $value;
  120. $i++;
  121. }
  122. }
  123. }
  124. return $this->sign_str($content);
  125. }
  126. /**
  127. * 签名
  128. * @param string $data
  129. * @return string with base64 encoded
  130. */
  131. public function sign_str($data)
  132. {
  133. if (!is_string($data)) {
  134. return null;
  135. }
  136. $this->setupPrivKey();
  137. $sign = null;
  138. $r = openssl_sign($data, $sign, $this->_privKey);
  139. if ($r) {
  140. return base64_encode($sign);
  141. }
  142. return null;
  143. }
  144. /**
  145. * 验签
  146. * @param type $data
  147. * @param type $sign
  148. * @return boolean true 通过, false 不通过
  149. */
  150. public function verify($data, $sign)
  151. {
  152. if (!is_string($data) || !is_string($sign)) {
  153. return false;
  154. }
  155. $this->setupPubKey();
  156. $r = openssl_verify($data, base64_decode($sign), $this->_pubKey);
  157. if ($r == 1) {
  158. return true;
  159. }
  160. return false;
  161. }
  162. /**
  163. * 验签(数组)
  164. * @param array $arr
  165. * @param string $sign
  166. * @return boolean true 通过, false 不通过
  167. */
  168. public function verify_arr($arr, $sign)
  169. {
  170. if (!is_array($arr) || !is_string($sign)) {
  171. CLog::err("验签防御代码:参数有误", 'RSA');
  172. return false;
  173. }
  174. return $sign == $this->sign_arr($arr);
  175. }
  176. /**
  177. * encrypt with the private key
  178. */
  179. public function privEncrypt($data)
  180. {
  181. if (!is_string($data)) {
  182. return null;
  183. }
  184. $this->setupPrivKey();
  185. $encrypted = null;
  186. $r = openssl_private_encrypt($data, $encrypted, $this->_privKey);
  187. if ($r) {
  188. return base64_encode($encrypted);
  189. }
  190. return null;
  191. }
  192. /**
  193. * * decrypt with the private key
  194. */
  195. public function privDecrypt($encrypted)
  196. {
  197. if (!is_string($encrypted)) {
  198. return null;
  199. }
  200. $this->setupPrivKey();
  201. $encrypted = base64_decode($encrypted);
  202. $r = openssl_private_decrypt($encrypted, $decrypted, $this->_privKey);
  203. if ($r) {
  204. return $decrypted;
  205. }
  206. return null;
  207. }
  208. /**
  209. * encrypt with public key
  210. */
  211. public function pubEncrypt($data)
  212. {
  213. if (!is_string($data)) {
  214. return null;
  215. }
  216. $this->setupPubKey();
  217. $encrypted = null;
  218. $r = openssl_public_encrypt($data, $encrypted, $this->_pubKey);
  219. if ($r) {
  220. return base64_encode($encrypted);
  221. }
  222. return null;
  223. }
  224. /**
  225. * decrypt with the public key
  226. */
  227. public function pubDecrypt($crypted)
  228. {
  229. if (!is_string($crypted)) {
  230. return null;
  231. }
  232. $this->setupPubKey();
  233. $crypted = base64_decode($crypted);
  234. $r = openssl_public_decrypt($crypted, $decrypted, $this->_pubKey);
  235. if ($r) {
  236. return $decrypted;
  237. }
  238. return null;
  239. }
  240. /**
  241. * 析构函数
  242. */
  243. public function __destruct()
  244. {
  245. if (is_resource($this->_pubKey)) {
  246. openssl_free_key($this->_pubKey);
  247. }
  248. if (is_resource($this->_privKey)) {
  249. openssl_free_key($this->_privKey);
  250. }
  251. }
  252. }