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 相关文章推荐
PHP中GET变量的使用
Oct 09 PHP
PHP Smarty生成EXCEL文档的代码
Aug 23 PHP
PHP 输出简单动态WAP页面
Jun 09 PHP
php学习笔记 [预定义数组(超全局数组)]
Jun 09 PHP
PHP实现读取一个1G的文件大小
Aug 24 PHP
PHP mkdir()无写权限的问题解决方法
Jun 19 PHP
Laravel框架路由配置总结、设置技巧大全
Sep 03 PHP
PHP实现采集中国天气网未来7天天气
Oct 15 PHP
php操作xml入门之cdata区段
Jan 23 PHP
php根据指定位置和长度获得子字符串的方法
Mar 17 PHP
php处理复杂xml数据示例
Jul 11 PHP
PHPCrawl爬虫库实现抓取酷狗歌单的方法示例
Dec 21 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
Joomla下利用configuration.php存储简单数据
2010/05/19 PHP
php过滤html中的其他网站链接的方法(域名白名单功能)
2014/04/24 PHP
从零开始学习jQuery (二) 万能的选择器
2010/10/01 Javascript
JS高级笔记
2011/07/13 Javascript
用js来刷新当前页面保留参数的具体实现
2013/12/23 Javascript
AngularJS iframe跨域打开内容时报错误的解决办法
2015/01/26 Javascript
JavaScript对象反射用法实例
2015/04/17 Javascript
nodejs实现遍历文件夹并统计文件大小
2015/05/28 NodeJs
JS实现字符串转驼峰格式的方法
2016/12/16 Javascript
JavaScript和JQuery获取DIV值的方法示例
2017/03/07 Javascript
json字符串传到前台input的方法
2018/08/06 Javascript
element ui 表格动态列显示空白bug 修复方法
2018/09/04 Javascript
微信小程序npm引入vant-weapp的踩坑记录
2019/08/01 Javascript
mpvue微信小程序的接口请求fly全局拦截代码实例
2019/11/13 Javascript
举例讲解如何在Python编程中进行迭代和遍历
2016/01/19 Python
Python+django实现简单的文件上传
2016/08/17 Python
python爬虫 正则表达式使用技巧及爬取个人博客的实例讲解
2017/10/20 Python
python3利用smtplib通过qq邮箱发送邮件方法示例
2017/12/03 Python
用TensorFlow实现多类支持向量机的示例代码
2018/04/28 Python
python matplotlib 在指定的两个点之间连线方法
2018/05/25 Python
详解PyCharm配置Anaconda的艰难心路历程
2018/08/13 Python
python与mysql数据库交互的实现
2020/01/06 Python
详解HTML5将footer置于页面最底部的方法(CSS+JS)
2018/10/11 HTML / CSS
师范教师大学生职业生涯规划范文
2014/01/05 职场文书
党校培训自我鉴定范文
2014/04/10 职场文书
残疾人小组计划书
2014/04/27 职场文书
责任胜于能力演讲稿
2014/05/20 职场文书
2014企业领导班子四风对照检查材料思想汇报
2014/09/17 职场文书
2014年防汛工作总结
2014/12/08 职场文书
自主招生自荐信范文
2015/03/04 职场文书
千与千寻观后感
2015/06/04 职场文书
自荐信范文
2019/05/20 职场文书
goland 恢复已更改文件的操作
2021/04/28 Golang
MongoDB安装使用并实现Python操作数据库
2021/06/28 MongoDB
《地。-关于地球的运动-》单行本第七集上市,小说家朝井辽献上期待又害怕的推荐文
2022/03/31 日漫
Java实现简单小画板
2022/06/10 Java/Android