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 相关文章推荐
BBS(php &amp; mysql)完整版(五)
Oct 09 PHP
PHP数据缓存技术
Feb 14 PHP
php 获取本机外网/公网IP的代码
May 09 PHP
php遍历CSV类实例
Apr 14 PHP
php实现格式化多行文本为Js可用格式
Apr 15 PHP
twig模板获取全局变量的方法
Feb 05 PHP
Yii针对添加行的增删改查操作示例
Oct 18 PHP
php封装的表单验证类完整实例
Oct 19 PHP
thinkPHP模板中for循环与switch语句用法示例
Nov 30 PHP
PHP实现中国公民身份证号码有效性验证示例代码
May 03 PHP
php+js实现裁剪任意形状图片
Oct 31 PHP
Laravel框架路由管理简单示例
May 07 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过滤黑名单关键字的方法
2014/12/01 PHP
php无法连接mysql数据库的正确解决方法
2016/07/01 PHP
thinkphp3.2.3 分页代码分享
2016/07/28 PHP
PHP中检查isset()和!empty()函数的必要性
2019/02/13 PHP
JavaScript 保存数组到Cookie的代码
2010/04/14 Javascript
Js切换功能的简单方法
2010/11/23 Javascript
jQuery实现鼠标悬停显示提示信息窗口的方法
2015/04/30 Javascript
jQuery实现文本框输入同步的方法
2015/06/20 Javascript
全面解析JavaScript中的valueOf与toString方法(推荐)
2016/06/14 Javascript
jQuery实现产品对比功能附源码下载
2016/08/09 Javascript
详解Angular的双向数据绑定(MV-VM)
2016/12/26 Javascript
jQuery实现鼠标响应式透明度渐变动画效果示例
2018/02/13 jQuery
Vue实现PopupWindow组件详解
2018/04/28 Javascript
JS监听滚动和id自动定位滚动
2018/12/18 Javascript
浅谈Vue.js组件(二)
2019/04/09 Javascript
js回文数的4种判断方法示例
2019/06/04 Javascript
使用localStorage替代cookie做本地存储
2019/09/25 Javascript
vue实现权限控制路由(vue-router 动态添加路由)
2019/11/04 Javascript
Vue中函数防抖节流的理解及应用实现
2020/04/24 Javascript
Python中使用pprint函数进行格式化输出的教程
2015/04/07 Python
使用Python生成随机密码的示例分享
2016/02/18 Python
对numpy中的transpose和swapaxes函数详解
2018/08/02 Python
解决python测试opencv时imread导致的错误问题
2019/01/26 Python
selenium+python实现自动登陆QQ邮箱并发送邮件功能
2019/12/13 Python
韩国三大免税店之一:THE GRAND 中文免税店
2016/07/21 全球购物
瑞典最好的运动鞋专卖店:Sneakersnstuff
2016/08/29 全球购物
Bealls Florida百货商店:生活服饰、家居装饰和鞋子
2018/02/23 全球购物
美国球鞋寄卖网站:Stadium Goods
2018/05/09 全球购物
Yummie官方网站:塑身衣和衣柜必需品
2019/10/29 全球购物
土木工程专业个人求职信
2013/12/30 职场文书
演讲稿格式
2014/04/30 职场文书
汽车销售经理岗位职责
2014/06/09 职场文书
村级个人对照检查材料
2014/08/22 职场文书
风雨哈佛路观后感
2015/06/03 职场文书
《1942》观后感
2015/06/08 职场文书
二婚主持词
2015/06/30 职场文书