您的位置:首页 > 编程语言 > PHP开发

PHP中使用RSA加密总结

2015-12-22 14:39 531 查看
数据加密方式有多种,常用的是MD5(),RSA等,对于PHP中的RSA加密算法和使用,主要有下面这些:

<?php

/**
* rsa
* 需要 openssl 支持
*
*
*/
class Rsa
{

private static $_instance;

//类初始化操作
function __construct ()
{
}

//类销毁操作
function __destruct ()
{
}
//公用的静态方法,定义静态变量为当前类的实例
public static function instance()
{
if (self::$_instance == null) {
self::$_instance = new self;
}
return self::$_instance;
}

/**
* 生成一对RSA的公匙和私匙
* @param unknown_type $bits  钥匙对的字节数
* 返回一对RSA钥匙
*/
public function create($bits = 1024)
{
$rsa = openssl_pkey_new(array('private_key_bits' => $bits,'private_key_type' => OPENSSL_KEYTYPE_RSA));
//得到私匙
openssl_pkey_export($rsa, $privatekey);
$publickey = openssl_pkey_get_details($rsa);
//得到公匙
$publickey = $publickey['key'];
return array(
'privatekey' => $privatekey,
'publickey' => $publickey
);
}

/**
* 公匙加密  使用公匙对信息进行加密处理
* @param unknown_type $sourcestr  待加密数据
* @param unknown_type $publickey  RSA公匙(pem格式)
* 加密成功返回加密字符串,失败返回FALSE
*/
function publickey_encodeing($sourcestr, $publickey)
{
//先将rsa公匙转化为openssl公匙
$pubkeyid = openssl_get_publickey($publickey);
//使用openssl加密方法加密
/**
* openssl公匙加密
* $sourcestr  待加密数据
* $crypttext  加密后数据
* $pubkeyid  openssl公匙
* 成功返回加密后的数据,失败返回false
*/
if (openssl_public_encrypt($sourcestr, $crypttext, $pubkeyid, OPENSSL_PKCS1_PADDING))
{
return $crypttext;
}
return FALSE;
}
c7a2

/**
* 公匙解密
* @param unknown_type $crypttext  待解密数据
* @param unknown_type $publickey  rsa公匙(pem格式或资源)
*
*/
function publickey_decodeing($crypttext, $publickey)
{
$pubkeyid = openssl_get_publickey($publickey);
if (openssl_public_decrypt($crypttext, $sourcestr, $pubkeyid, OPENSSL_PKCS1_PADDING))
{
return $sourcestr;
}
return FALSE;
}

/**
* 私匙解密  同公匙解密
* @param unknown_type $crypttext
* @param unknown_type $privatekey
*
*/
function privatekey_decodeing($crypttext, $privatekey)
{

$prikeyid = openssl_get_privatekey($privatekey);
if (openssl_private_decrypt($crypttext, $sourcestr, $prikeyid, OPENSSL_PKCS1_PADDING))
{
return $sourcestr;
}
return FALSE;
}

/**
* 私匙加密  同公匙加密
* @param unknown_type $sourcestr
* @param unknown_type $privatekey
*
*/
function privatekey_encodeing($sourcestr, $privatekey)
{

$prikeyid = openssl_get_privatekey($privatekey);
if (openssl_private_encrypt($sourcestr, $crypttext, $prikeyid, OPENSSL_PKCS1_PADDING))
{
return $crypttext;
}
return FALSE;
}

/**
* RSA私匙签名
* @param unknown_type $sourcestr  待签名数据
* @param unknown_type $privatekey rsa私匙(pem格式或资源)
* 返回签名后的字符串
*/
function sign($sourcestr, $privatekey)
{
//先将RSA私匙转化为openssl私匙
$pkeyid = openssl_get_privatekey($privatekey);
//签名,$signature为签名后的字符串
openssl_sign($sourcestr, $signature, $pkeyid);
//释放资源
openssl_free_key($pkeyid);
return $signature;

}

/**
* RSA公匙验签
* @param unknown_type $sourcestr  待签名数据
* $signature  私匙签名后的字符串(未经过base64编码的)
* @param unknown_type $publickey rsa公匙(pem格式或资源)
* 返回验证签名结果
*
*/
function verify($sourcestr, $signature, $publickey)
{
//先将rsa公匙转化为openssl公匙
$pkeyid = openssl_get_publickey($publickey);
//验证签名,返回1验签正确,返回0验签错误,-1是函数执行错误
$verify = openssl_verify($sourcestr, $signature, $pkeyid);
openssl_free_key($pkeyid);
return $verify;

}

}
?>


以上是RSA加密算法的常用方法,我们使用的私匙和公匙,格式都是为pem格式的字符串或者是文件资源,而如果是PKCS格式的字符串,需要先进行格式化处理,处理方法如下:

/**格式化私钥  将私匙每64个长度取做一串,放在pem格式密匙的每一行中
* $priKey PKCS#1格式的私钥串
* return pem格式私钥, 可以保存为.pem文件
*/
function formatPriKey($priKey) {
$fKey = "-----BEGIN RSA PRIVATE KEY-----\n";
$len = strlen($priKey);
for($i = 0; $i < $len; ) {
$fKey = $fKey . substr($priKey, $i, 64) . "\n";
$i += 64;
}
$fKey .= "-----END RSA PRIVATE KEY-----";
return $fKey;
}

/**格式化公钥  将公匙每64个长度取做一串,放在pem格式密匙的每一行中
* $pubKey PKCS#1格式的私钥串
* return pem格式公钥, 可以保存为.pem文件
*/
function formatPubKey($pubKey) {
$fKey = "-----BEGIN PUBLIC KEY-----\n";
$len = strlen($pubKey);
for($i = 0; $i < $len; ) {
$fKey = $fKey . substr($pubKey, $i, 64) . "\n";
$i += 64;
}
$fKey .= "-----END PUBLIC KEY-----";
return $fKey;
}


另外在解密过程中,需要注意的是数据过长时,一定要进行分段解密,以128个字符长度为例,最长字节数是1024,超过需要分段解密,才能得到正常的解密数据,过程如下:

class MyRsa extends Rsa{
/**
* 分段解密
* $data  待解密数据
* $key rsa公匙(pem格式或资源)
* $rsa_bit 限定解密最长字节数
* 返回验证签名结果
*/
function rsa_decrypt($data, $key, $rsa_bit = 1024) {
$inputLen = strlen($data);
$offSet = 0;
$i = 0;
$maxDecryptBlock = $rsa_bit / 8;  //128
$de = '';
$cache = '';

// 对数据分段解密
while ($inputLen - $offSet > 0) {

if ($inputLen - $offSet > $maxDecryptBlock) {
$cache = parent::publickey_decodeing(substr($data, $offSet, $maxDecryptBlock), $key);
} else {
$cache = parent::publickey_decodeing(substr($data, $offSet, $inputLen - $offSet), $key);
}

$de = $de . $cache;

$i = $i + 1;
$offSet = $i * $maxDecryptBlock;
}
return $de;
}
}


最近做支付接口时,主要用到的RSA加密方面的问题就是上面这些,以后遇见其他问题再来补充完善!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: