通过PHP简单了解RSA的使用

这两天,在给用户写支付的demo,用的PHP。PHP语言本身没什么值得吐槽的地方,真的很棒,很好用。可能就是构建大型系统的时候,能力弱一点吧。总之,语言还是很好用的。

以下是我写的RSA加签、验签的工具类:

<?php
/**
 * RSA工具类
 * Created by PhpStorm.
 * User: carlos
 * Date: 18-7-14
 * Time: 下午6:12
 */

class RSAUtil
{
    public $private_key;
    public $public_key;

    /**
     * 利用构造函数,初始化值
     * @param $private_str 私钥串
     * @param $public_str 公钥串
     */
    function __construct($private_str, $public_str)
    {
        /**
         * TODO:以下两行代码,是因为从常量中读取密钥,其为一行数据,且其并无前后标识
         */
        $private_str = "-----BEGIN RSA PRIVATE KEY-----\n" .
            $private_str.
            "\n-----END RSA PRIVATE KEY-----";

        $public_str = "-----BEGIN PUBLIC KEY-----\n" .
            $public_str.
            "\n-----END PUBLIC KEY-----";

        $this->private_key = openssl_get_privatekey($private_str);
        $this->public_key = openssl_get_publickey($public_str);
    }

    /**
     * 创建RSA签名
     * @param $original_str 原数据
     * @return string 签名
     */
    public function createRSASign($original_str)
    {
        openssl_sign($original_str, $sign, $this->private_key);
        openssl_free_key($this->private_key);
        return base64_encode($sign);
    }

    /**
     * RSA验签
     * @param $original_str 原数据
     * @param $sign 签名
     * @return bool 验签结果
     */
    public function verifyRSASign($original_str, $sign)
    {
        return (bool)openssl_verify($original_str, base64_decode($sign), $this->public_key);
    }

    /**
     * 创建RSA2的签名
     * @param $original_str 原数据
     * @return string 签名
     */
    public function createRSA2Sign($original_str)
    {
        openssl_sign($original_str, $sign, $this->private_key, OPENSSL_ALGO_SHA256);
        openssl_free_key($this->private_key);
        return base64_encode($sign);
    }

    /**
     * RSA2验签
     * @param $original_str 原数据
     * @param $sign 签名
     * @return bool 验签结果
     */
    public function verifyRSA2Sign($original_str, $sign)
    {
        return (bool)openssl_verify($original_str, base64_decode($sign), $this->public_key, OPENSSL_ALGO_SHA256);
    }

}

可能语法写的不标准,还请见谅,自从毕业就很少写PHP了。关于PHP使用RSA来说,他和Java相比,让我感觉最有意思的地方,就是初始化密钥的时候,需要带上前后标识(以下是PKCS#1标准的前后标识):

-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----

-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----

如果,不带有这标志,就会报错。看资料发现,PHP主要是用 PKCS#1的加密标准,Java主要是用PKCS#8的加密标准。但是,我在此方法中用了两种标准的同一个密钥来测试,都是可以使用的,产生的签名都是相同的。

这边描述一下这些标准的区别:

标准 版本 名称 简介
PKCS #1 2.1 RSA密码编译标准(RSA Cryptography Standard) 定义了RSA的数理基础、公/私钥格式,以及加/解密、签/验章的流程。1.5版本曾经遭到攻击。
PKCS #2 撤销 原本是用以规范RSA加密摘要的转换方式,现已被纳入PKCS#1之中。
PKCS #3 1.4 DH密钥协议标准(Diffie-Hellman key agreement Standard) 规范以DH密钥协议为基础的密钥协议标准。其功能,可以让两方通过金议协议,拟定一把会议密钥(Session key)。
PKCS #4 撤销 原本用以规范转换RSA密钥的流程。已被纳入PKCS#1之中。
PKCS #5 2.0 密码基植加密标准(Password-based Encryption Standard) 参见RFC 2898与PBKDF2。
PKCS #6 1.5 证书扩展语法标准(Extended-Certificate Syntax Standard) 将原本X.509的证书格式标准加以扩充。
PKCS #7 1.5 密码消息语法标准(Cryptographic Message Syntax Standard) 参见RFC 2315。规范了以公开密钥基础设施(PKI)所产生之签名/密文之格式。其目的一样是为了拓展数字证书的应用。其中,包含了S/MIME与CMS。
PKCS #8 1.2 私钥消息表示标准(Private-Key Information Syntax Standard). Apache读取证书私钥的标准。
PKCS #9 2.0 选择属性格式(Selected Attribute Types) 定义PKCS#6、7、8、10的选择属性格式。
PKCS #10 1.7 证书申请标准(Certification Request Standard) 参见RFC 2986。规范了向证书中心申请证书之CSR(certificate signing request)的格式。
PKCS #11 2.20 密码设备标准接口(Cryptographic Token Interface (Cryptoki)) 定义了密码设备的应用程序接口(API)之规格。
PKCS #12 1.0 个人消息交换标准(Personal Information Exchange Syntax Standard) 定义了包含私钥与公钥证书(public key certificate)的文件格式。私钥采密码(password)保护。常见的PFX就履行了PKCS#12。
PKCS #13 椭圆曲线密码学标准(Elliptic curve cryptography Standard) 制定中。规范以椭圆曲线密码学为基础所发展之密码技术应用。椭圆曲线密码学是新的密码学技术,其强度与效率皆比现行以指数运算为基础之密码学算法来的优秀。然而,该算法的应用尚不普及。
PKCS #14 拟随机数产生器标准(Pseudo-random Number Generation) 制定中。规范拟随机数产生器的使用与设计。
PKCS #15 1.1 密码设备消息格式标准(Cryptographic Token Information Format Standard) 定义了密码设备内部数据的组织结构。

注意:
代码中使用的密钥主体是一行,使用的时候,需要去掉换行符。
PKCS#1与PKCS#8转换的时候,请使用原始格式(带有换行符 + 前后标识)

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据