php报文加签验签与读取证书

写在前面

在一些比较注重安全的项目中,需要对报文进行加解密,签名等操作,下面说一些这方面的概念:

  • 算法:算法用来加密报文,常见的sha1,sha256等这里就不多讲了。但普通的算法加密解密是不安全的,因为报文如果被抓取,知道了算法,很轻易就可以篡改报文信息。所以就有签名,具体看以下的签名说明。
  • 签名:
  1. 在说到签名前,得谈谈SHA1withRSA,SHA256withRSA这些算法,其实这些也是sha1、sha256加密,那为什么会有个withRSA后缀?这牵涉到RSA非对称性加密(复杂的概念不多讲,有兴趣可以自己查),简单来讲,就是双方拥有不同的钥匙,这对钥匙同时生成,分为自留的私钥和分发的公钥,都可以用来加密和解对方加密的报文。因此,他们是在sha1、sha256基础上用钥匙来加签名。
  2. 那为什么说签名会比较安全?因为签名的过程是这样的,本地用私钥(或公钥)对报文进行加密生成一串签名,并将签名附加到原有报文发送出去。对方接受到后,用他们本地的公钥(或者私钥)解密签名,看解密出的内容是否与报文一致,如果一致说明没问题,不一致的话emmm,说明安全堪忧啊😆。而钥匙是生成后直接派发到对应的人员和计算机上的,所以无法获取钥匙就无法解密,安全性也就提高了
  • 证书和公私钥:常见的证书文件后缀有pfx(等同于.p12,是pcks#12的)、cer。cer里面一般都是存放的公钥,pfx则是同时存放私钥和公钥

php生成签名和验证签名

    //读取pfx文件的方法
    $cerContent=file_get_contents(__DIR__."/cert/abcdefg.pfx");
    //读取pkcs文件内容到数组,其中pfx属于pcks#12
    openssl_pkcs12_read($cerContent,$readCerContent,"123123");
    print_r($readCerContent);

    //结果如下:
    //Array
    //(
    //    [cert] => -----BEGIN CERTIFICATE-----
    //        钥匙内容base64格式 * n行
    //-----END CERTIFICATE-----

    //    [pkey] => -----BEGIN PRIVATE KEY-----
    //    钥匙内容base64格式 * n行
    //-----END PRIVATE KEY-----

    //已知cer公钥内容则用这段读取公钥
    $pubKeyCotent = "-----BEGIN PUBLIC KEY-----\n" .
                wordwrap("你的公钥内容", 64, "\n", true) .
                "\n-----END PUBLIC KEY-----";
	$pukey=openssl_pkey_get_public($pubKeyCotent);



/**
* @desc 私钥生成签名方法
* @param string pfxFile (包含begin和end标准格式)pfx文件绝对路径
* @param string privateKey 读取pfx文件的密码,例如123123
*/
function genPriSign($toSign, $pfxFile,$pass){
    //读取x.509证书文件
    $cerContent=file_get_contents($pfxFile);
    //用pfx打开的密码,将pfx文件读取到数组
    openssl_pkcs12_read($cerContent,$readCerContent,$pass);
    //得到私钥
    $pkey=openssl_pkey_get_private($readCerContent['pkey']);
    //生成签名$sign,默认是sha1加密, 这里用sha256
    openssl_sign($toSign,$sign,$pkey,"SHA256");
    openssl_free_key($pkey);
    $sign = base64_encode($sign);
    return $sign;
}

//使用例子
$sign=genPriSign("test",DIR."/cer/server.pfx","123123");
echo $sign.PHP_EOL;

```php
/**
* @desc 公钥验证签名方法
* @param string sign 需要验证的签名
* @param string data 需要验证的数据
* @param string pfxFile (包含begin和end标准格式)pfx文件绝对路径
* @param string privateKey 读取pfx文件的密码,例如123123
*/
function verPubSign($sign,$data, $pfxFile,$pass){
    $sign = base64_decode($sign);

    $cerContent=file_get_contents($pfxFile);

    openssl_pkcs12_read($cerContent,$readCerContent,$pass);
    //得到公钥
    $pukey=openssl_pkey_get_public($readCerContent['cert']);          
    $result = openssl_verify($data, $sign, $pukey, "SHA256") === 1;
    return $result;
}

//使用例子
//这里的sign为上一步生成的结果
$sign="MWhI7xujNa7PshsrYCnsJH7nC+ZB60rkISqqNeNA+Me7R8qOsGqvKq25uO9uSN00OpniV0k8uIGnJ4OSchj99v9f7cfpg1gt9aqgJ64oohx0As1+S+UtO/UDK5Y2YqvOy22H386khlLVqQ1s4XtCa7x7a/xWMtpRTkbsIvu/l3xbZPG69/E8tTTMuCkXYOW89DrSk0OiHlL60hQjL69Pl1dvP5RMwWs5Bcw6XAtTLlqe3mYXYSS1ojQqzCJR4ha0yj+UudwIilN7/vow6Tmy7nKIgl7DM0WSZ2ZQqXe/xCunkRBGt5skcM2w55N+foiXLSIFuuYjbnnXJRTp8CnLgQ==";
var_dump(verPubSign($sign,"test",DIR."/cer/server.pfx","123123"));


posted @ 2021-01-05 14:49  小七闲  阅读(385)  评论(0)    收藏  举报