PHP中使用RSA加密总结

数据加密方式有多种,常用的是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;
    }


    /**
     * 公匙解密
     * @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加密方面的问题就是上面这些,以后遇见其他问题再来补充完善!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值