当前位置:Gxlcms > PHP教程 > phpRAS加密类代码

phpRAS加密类代码

时间:2021-07-01 10:21:17 帮助过:18人阅读

通过openssl实现的签名、验签、非对称加解密,需要配合x.509证书(如crt和pem)文件使用。
  1. /**
  2. * RSA算法类
  3. * 签名及密文编码:base64字符串/十六进制字符串/二进制字符串流
  4. * 填充方式: PKCS1Padding(加解密)/NOPadding(解密)
  5. *
  6. * Notice:Only accepts a single block. Block size is equal to the RSA key size!
  7. * 如密钥长度为1024 bit,则加密时数据需小于128字节,加上PKCS1Padding本身的11字节信息,所以明文需小于117字节
  8. *
  9. * @author: linvo
  10. * @version: 1.0.0
  11. * @date: 2013/1/23
  12. */
  13. class RSA{
  14. private $pubKey = null;
  15. private $priKey = null;
  16. /**
  17. * 自定义错误处理
  18. */
  19. private function _error($msg){
  20. die('RSA Error:' . $msg); //TODO
  21. }
  22. /**
  23. * 构造函数
  24. *
  25. * @param string 公钥文件(验签和加密时传入)
  26. * @param string 私钥文件(签名和解密时传入)
  27. */
  28. public function __construct($public_key_file = '', $private_key_file = ''){
  29. if ($public_key_file){
  30. $this->_getPublicKey($public_key_file);
  31. }
  32. if ($private_key_file){
  33. $this->_getPrivateKey($private_key_file);
  34. }
  35. }
  36. /**
  37. * 生成签名
  38. *
  39. * @param string 签名材料
  40. * @param string 签名编码(base64/hex/bin)
  41. * @return 签名值
  42. */
  43. public function sign($data, $code = 'base64'){
  44. $ret = false;
  45. if (openssl_sign($data, $ret, $this->priKey)){
  46. $ret = $this->_encode($ret, $code);
  47. }
  48. return $ret;
  49. }
  50. /**
  51. * 验证签名
  52. *
  53. * @param string 签名材料
  54. * @param string 签名值
  55. * @param string 签名编码(base64/hex/bin)
  56. * @return bool
  57. */
  58. public function verify($data, $sign, $code = 'base64'){
  59. $ret = false;
  60. $sign = $this->_decode($sign, $code);
  61. if ($sign !== false) {
  62. switch (openssl_verify($data, $sign, $this->pubKey)){
  63. case 1: $ret = true; break;
  64. case 0:
  65. case -1:
  66. default: $ret = false;
  67. }
  68. }
  69. return $ret;
  70. }
  71. /**
  72. * 加密
  73. *
  74. * @param string 明文
  75. * @param string 密文编码(base64/hex/bin)
  76. * @param int 填充方式(貌似php有bug,所以目前仅支持OPENSSL_PKCS1_PADDING)
  77. * @return string 密文
  78. */
  79. public function encrypt($data, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING){
  80. $ret = false;
  81. if (!$this->_checkPadding($padding, 'en')) $this->_error('padding error');
  82. if (openssl_public_encrypt($data, $result, $this->pubKey, $padding)){
  83. $ret = $this->_encode($result, $code);
  84. }
  85. return $ret;
  86. }
  87. /**
  88. * 解密
  89. *
  90. * @param string 密文
  91. * @param string 密文编码(base64/hex/bin)
  92. * @param int 填充方式(OPENSSL_PKCS1_PADDING / OPENSSL_NO_PADDING)
  93. * @param bool 是否翻转明文(When passing Microsoft CryptoAPI-generated RSA cyphertext, revert the bytes in the block)
  94. * @return string 明文
  95. */
  96. public function decrypt($data, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING, $rev = false){
  97. $ret = false;
  98. $data = $this->_decode($data, $code);
  99. if (!$this->_checkPadding($padding, 'de')) $this->_error('padding error');
  100. if ($data !== false){
  101. if (openssl_private_decrypt($data, $result, $this->priKey, $padding)){
  102. $ret = $rev ? rtrim(strrev($result), "\0") : ''.$result;
  103. }
  104. }
  105. return $ret;
  106. }
  107. // 私有方法
  108. /**
  109. * 检测填充类型
  110. * 加密只支持PKCS1_PADDING
  111. * 解密支持PKCS1_PADDING和NO_PADDING
  112. *
  113. * @param int 填充模式
  114. * @param string 加密en/解密de
  115. * @return bool
  116. */
  117. private function _checkPadding($padding, $type){
  118. if ($type == 'en'){
  119. switch ($padding){
  120. case OPENSSL_PKCS1_PADDING:
  121. $ret = true;
  122. break;
  123. default:
  124. $ret = false;
  125. }
  126. } else {
  127. switch ($padding){
  128. case OPENSSL_PKCS1_PADDING:
  129. case OPENSSL_NO_PADDING:
  130. $ret = true;
  131. break;
  132. default:
  133. $ret = false;
  134. }
  135. }
  136. return $ret;
  137. }
  138. private function _encode($data, $code){
  139. switch (strtolower($code)){
  140. case 'base64':
  141. $data = base64_encode(''.$data);
  142. break;
  143. case 'hex':
  144. $data = bin2hex($data);
  145. break;
  146. case 'bin':
  147. default:
  148. }
  149. return $data;
  150. }
  151. private function _decode($data, $code){
  152. switch (strtolower($code)){
  153. case 'base64':
  154. $data = base64_decode($data);
  155. break;
  156. case 'hex':
  157. $data = $this->_hex2bin($data);
  158. break;
  159. case 'bin':
  160. default:
  161. }
  162. return $data;
  163. }
  164. private function _getPublicKey($file){
  165. $key_content = $this->_readFile($file);
  166. if ($key_content){
  167. $this->pubKey = openssl_get_publickey($key_content);
  168. }
  169. }
  170. private function _getPrivateKey($file){
  171. $key_content = $this->_readFile($file);
  172. if ($key_content){
  173. $this->priKey = openssl_get_privatekey($key_content);
  174. }
  175. }
  176. private function _readFile($file){
  177. $ret = false;
  178. if (!file_exists($file)){
  179. $this->_error("The file {$file} is not exists");
  180. } else {
  181. $ret = file_get_contents($file);
  182. }
  183. return $ret;
  184. }
  185. private function _hex2bin($hex = false){
  186. $ret = $hex !== false && preg_match('/^[0-9a-fA-F]+$/i', $hex) ? pack("H*", $hex) : false;
  187. return $ret;
  188. }
  189. }

测试示例
  1. header('Content-Type:text/html;Charset=utf-8;');
  2. include "rsa.php";
  3. echo '
    '; 
  4. $a = isset($_GET['a']) ? $_GET['a'] : '测试123';
  5. //////////////////////////////////////
  6. $pubfile = 'E:\ssl\cert\pwd.crt';
  7. $prifile = 'E:\ssl\cert\pwd.pem';
  8. $m = new RSA($pubfile, $prifile);
  9. $x = $m->sign($a);
  10. $y = $m->verify($a, $x);
  11. var_dump($x, $y);
  12. $x = $m->encrypt($a);
  13. $y = $m->decrypt($x);
  14. var_dump($x, $y);

php, RAS

人气教程排行