PHP中使用RSA加密总结

来源:互联网 发布:人工智能产品设计 编辑:程序博客网 时间:2024/06/07 06:43

数据加密方式有多种,常用的是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加密方面的问题就是上面这些,以后遇见其他问题再来补充完善!

0 0
原创粉丝点击