php实现RSA加密类实例


Posted in PHP onMarch 26, 2015

本文实例讲述了php实现RSA加密类。分享给大家供大家参考。具体分析如下:

通过openssl实现的签名、验签、非对称加解密,需要配合x.509证书(如crt和pem)文件使用。
由于各种原因,该类并不十分完善,欢迎各种测试!

<?php 
/**
 * RSA算法类
 * 签名及密文编码:base64字符串/十六进制字符串/二进制字符串流
 * 填充方式: PKCS1Padding(加解密)/NOPadding(解密)
 *
 * Notice:Only accepts a single block. Block size is equal to the RSA key size! 
 * 如密钥长度为1024 bit,则加密时数据需小于128字节,加上PKCS1Padding本身的11字节信息,所以明文需小于117字节
 *
 * @author: linvo
 * @version: 1.0.0
 * @date: 2013/1/23
 */ 
class RSA{ 
 private $pubKey = null; 
 private $priKey = null; 
 /**
  * 自定义错误处理
  */ 
 private function _error($msg){ 
  die('RSA Error:' . $msg); //TODO 
 } 
 /**
  * 构造函数
  *
  * @param string 公钥文件(验签和加密时传入)
  * @param string 私钥文件(签名和解密时传入)
  */ 
 public function __construct($public_key_file = '', $private_key_file = ''){
  if ($public_key_file){ 
   $this->_getPublicKey($public_key_file); 
  } 
  if ($private_key_file){ 
   $this->_getPrivateKey($private_key_file); 
  } 
 } 
 /**
  * 生成签名
  *
  * @param string 签名材料
  * @param string 签名编码(base64/hex/bin)
  * @return 签名值
  */ 
 public function sign($data, $code = 'base64'){ 
  $ret = false;
  if (openssl_sign($data, $ret, $this->priKey)){ 
   $ret = $this->_encode($ret, $code);
  }
  return $ret; 
 }
 /**
  * 验证签名
  *
  * @param string 签名材料
  * @param string 签名值
  * @param string 签名编码(base64/hex/bin)
  * @return bool 
  */ 
 public function verify($data, $sign, $code = 'base64'){ 
  $ret = false;
  $sign = $this->_decode($sign, $code);
  if ($sign !== false) {
   switch (openssl_verify($data, $sign, $this->pubKey)){ 
    case 1: $ret = true; break;
    case 0:  
    case -1:  
    default: $ret = false;  
   } 
  } 
  return $ret; 
 } 
 /**
  * 加密
  *
  * @param string 明文
  * @param string 密文编码(base64/hex/bin)
  * @param int 填充方式(貌似php有bug,所以目前仅支持OPENSSL_PKCS1_PADDING)
  * @return string 密文
  */ 
 public function encrypt($data, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING){
  $ret = false;  
  if (!$this->_checkPadding($padding, 'en')) $this->_error('padding error');
  if (openssl_public_encrypt($data, $result, $this->pubKey, $padding)){
   $ret = $this->_encode($result, $code);
  } 
  return $ret; 
 } 
 /**
  * 解密
  *
  * @param string 密文
  * @param string 密文编码(base64/hex/bin)
  * @param int 填充方式(OPENSSL_PKCS1_PADDING / OPENSSL_NO_PADDING)
  * @param bool 是否翻转明文(When passing Microsoft CryptoAPI-generated RSA cyphertext, revert the bytes in the block)
  * @return string 明文
  */ 
 public function decrypt($data, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING, $rev = false){
  $ret = false;
  $data = $this->_decode($data, $code);
  if (!$this->_checkPadding($padding, 'de')) $this->_error('padding error');
  if ($data !== false){ 
   if (openssl_private_decrypt($data, $result, $this->priKey, $padding)){
    $ret = $rev ? rtrim(strrev($result), "\0") : ''.$result;
   } 
  } 
  return $ret; 
 } 
 // 私有方法 
 /**
  * 检测填充类型
  * 加密只支持PKCS1_PADDING
  * 解密支持PKCS1_PADDING和NO_PADDING
  * 
  * @param int 填充模式
  * @param string 加密en/解密de
  * @return bool
  */ 
 private function _checkPadding($padding, $type){
  if ($type == 'en'){ 
   switch ($padding){ 
    case OPENSSL_PKCS1_PADDING: 
     $ret = true; 
     break; 
    default: 
     $ret = false; 
   } 
  } else { 
   switch ($padding){ 
    case OPENSSL_PKCS1_PADDING: 
    case OPENSSL_NO_PADDING: 
     $ret = true; 
     break; 
    default: 
     $ret = false; 
   } 
  } 
  return $ret; 
 } 
 private function _encode($data, $code){ 
  switch (strtolower($code)){ 
   case 'base64': 
    $data = base64_encode(''.$data);
    break; 
   case 'hex': 
    $data = bin2hex($data); 
    break; 
   case 'bin': 
   default: 
  } 
  return $data; 
 } 
 private function _decode($data, $code){ 
  switch (strtolower($code)){ 
   case 'base64': 
    $data = base64_decode($data); 
    break; 
   case 'hex': 
    $data = $this->_hex2bin($data); 
    break; 
   case 'bin': 
   default: 
  } 
  return $data; 
 } 
 private function _getPublicKey($file){ 
  $key_content = $this->_readFile($file);
  if ($key_content){ 
   $this->pubKey = openssl_get_publickey($key_content);
  } 
 } 
 private function _getPrivateKey($file){ 
  $key_content = $this->_readFile($file); 
  if ($key_content){ 
   $this->priKey = openssl_get_privatekey($key_content);
  }
 }
 private function _readFile($file){
  $ret = false;
  if (!file_exists($file)){
   $this->_error("The file {$file} is not exists");
  } else {
   $ret = file_get_contents($file);
  }
  return $ret;
 } 
 private function _hex2bin($hex = false){ 
  $ret = $hex !== false && preg_match('/^[0-9a-fA-F]+$/i', $hex) ? pack("H*", $hex) : false;
  return $ret; 
 } 
}

测试demo:

<?php 
header('Content-Type:text/html;Charset=utf-8;'); 
include "rsa.php"; 
echo '<pre>'; 
$a = isset($_GET['a']) ? $_GET['a'] : '测试123'; 
////////////////////////////////////// 
$pubfile = 'E:\ssl\cert\pwd.crt'; 
$prifile = 'E:\ssl\cert\pwd.pem'; 
$m = new RSA($pubfile, $prifile); 
$x = $m->sign($a); 
$y = $m->verify($a, $x); 
var_dump($x, $y); 
$x = $m->encrypt($a); 
$y = $m->decrypt($x); 
var_dump($x, $y);

希望本文所述对大家的php程序设计有所帮助。

PHP 相关文章推荐
如何去掉文章里的 html 语法
Oct 09 PHP
mysql5的sql文件导入到mysql4的方法
Oct 19 PHP
php去掉URL网址中带有PHPSESSID的配置方法
Jul 08 PHP
php实现对两个数组进行减法操作的方法
Apr 17 PHP
PHP单例模式是什么 php实现单例模式的方法
May 14 PHP
php获取POST数据的三种方法实例详解
Dec 20 PHP
PHP实现将标点符号正则替换为空格的方法
Aug 09 PHP
PHP微信发送推送消息乱码的解决方法
Feb 28 PHP
PHP实现提高SESSION响应速度的几种方法详解
Aug 09 PHP
PHP7.0连接DB操作实例分析【基于mysqli】
Sep 26 PHP
php设计模式之观察者模式实例详解【星际争霸游戏案例】
Mar 30 PHP
PHP 实现缩略图
Mar 09 PHP
PHP中实现crontab代码分享
Mar 26 #PHP
PHP利用hash冲突漏洞进行DDoS攻击的方法分析
Mar 26 #PHP
ThinkPHP、ZF2、Yaf、Laravel框架路由大比拼
Mar 25 #PHP
CentOS 安装 PHP5.5+Redis+XDebug+Nginx+MySQL全纪录
Mar 25 #PHP
MacOS 安装 PHP的图片裁剪扩展Tclip
Mar 25 #PHP
php编写的一个E-mail验证类
Mar 25 #PHP
php取得字符串首字母的方法
Mar 25 #PHP
You might like
php 常用类汇总 推荐收藏
2010/05/13 PHP
APACHE的AcceptPathInfo指令使用介绍
2013/01/18 PHP
解析:php调用MsSQL存储过程使用内置RETVAL获取过程中的return值
2013/07/03 PHP
PHP基于GD2函数库实现验证码功能示例
2019/01/27 PHP
Jquery之美中不足小结
2011/02/16 Javascript
jQuery版仿Path菜单效果
2011/12/15 Javascript
js限制textarea每行输入字符串长度的代码
2012/10/31 Javascript
js限制文本框只能输入整数或者带小数点的数字
2015/04/27 Javascript
js基于面向对象实现网页TAB选项卡菜单效果代码
2015/09/09 Javascript
js实现StringBuffer的简单实例
2016/09/02 Javascript
jquery封装插件时匿名函数形参和实参的写法解释
2017/02/14 Javascript
JS实现标签页切换效果
2017/05/04 Javascript
js图片上传的封装代码
2017/08/01 Javascript
Vue.js搭建移动端购物车界面
2020/06/28 Javascript
vue-cli常用设置总结
2018/02/24 Javascript
Javascript中弹窗confirm与prompt的区别
2018/10/26 Javascript
详解ES7 Decorator 入门解析
2019/02/18 Javascript
Layui 带多选框表格监听事件以及按钮自动点击写法实例
2019/09/02 Javascript
layui table数据修改的回显方法
2019/09/04 Javascript
easyUI使用分页过滤器对数据进行分页操作实例分析
2020/06/01 Javascript
一行JavaScript代码如何实现瀑布流布局
2020/12/11 Javascript
使用python实现递归版汉诺塔示例(汉诺塔递归算法)
2014/04/08 Python
使用python 爬虫抓站的一些技巧总结
2018/01/10 Python
python事件驱动event实现详解
2018/11/21 Python
python多进程 主进程和子进程间共享和不共享全局变量实例
2020/04/25 Python
使用sklearn对多分类的每个类别进行指标评价操作
2020/06/11 Python
如何使用canvas绘制可移动网格的示例代码
2020/12/14 HTML / CSS
美国值得信赖的婚恋交友网站:eHarmony
2018/10/04 全球购物
PHP开发工程师面试问题集锦
2012/11/01 面试题
日语系毕业生推荐信
2013/11/11 职场文书
财务与信息服务专业推荐信
2013/11/28 职场文书
自荐信需注意事项
2014/01/25 职场文书
工程类专业自荐信范文
2014/03/09 职场文书
合伙经营协议书
2014/04/18 职场文书
协议书模板
2014/04/23 职场文书
匿名检举信范文
2015/03/02 职场文书