php 生成RSA非对称加密用的证书-cer-pfx文件

首先,关于RSA的加密介绍文章,就不多说了。直接看这个网页吧(作者写的计算机科普文章是极好的)

http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html

我要实现的功能就是通过这对公钥和密钥,实现客户端软件对密码进行加密(采用公钥),然后网站端(php)采用密钥进行解密验证。

开始吧。


php服务端利用内置函数生成公钥和密钥。记得这需要php服务器安装了openssl扩展。先生成cer文件和pfx文件。cer文件相当于公钥(可以发给客户端),pfx是密钥(必须严格保存于服务器端不能泄露)。

 $dn = array(
 "countryName" => 'zh', //所在国家名称
 "stateOrProvinceName" => 'GuangDong', //所在省份名称
 "localityName" => 'ShenZhen', //所在城市名称
 "organizationName" => 'baibai', //注册人姓名
 "organizationalUnitName" => 'company', //组织名称
 "commonName" => 'bbb', //公共名称
 "emailAddress" => '123@.qq.com' //邮箱
 );
 $privkeypass = 'cf'; //私钥密码
 $numberofdays = 3650; //有效时长
 $cerpath = "./test.cer"; //生成证书路径
 $pfxpath = "./test.pfx"; //密钥文件路径//生成证书
 $privkey = openssl_pkey_new();
 $csr = openssl_csr_new($dn, $privkey);
 $sscert = openssl_csr_sign($csr, null, $privkey, $numberofdays);
 openssl_x509_export_to_file($sscert, $cerpath); //导出证书到文件
 //openssl_pkcs12_export_to_file($sscert, $pfxpath, $privkey, $privkeypass); //生成密钥文件
 openssl_pkey_export_to_file($privkey, $pfxpath); //生成密钥文件

以下是是php端进行简单测试的代码:

/*
 //私钥加密
 $cer_key = file_get_contents($pfxpath); //获取密钥内容
 openssl_pkcs12_read($cer_key, $certs, $privkeypass);
 openssl_sign($data, $signMsg, $certs['pkey'],OPENSSL_ALGO_SHA1); //注册生成加密信息
 $signMsg = base64_encode($signMsg); //base64转码加密信息
 //echo $signMsg;
 
 
 //公钥解密
 $cer_key = file_get_contents($cerpath); //获取证书内容
 $unsignMsg=base64_decode($signMsg);//base64解码加密信息
 $cer = openssl_x509_read($cer_key); //读取公钥
 $res = openssl_verify($data, $unsignMsg, $cer); //验证
 echo $res; //输出验证结果,1:验证成功,0:验证失败
 */
 
 
 
 $data = "123456";
 $crypted = "";
 $key = file_get_contents($cerpath);
 //公钥加密
 openssl_public_encrypt($data, $crypted, $key);
 echo base64_encode($crypted)."<br>";
 //echo $crypted."<br>";
 
 //私钥解密
 $decrypted = "";
 $s = file_get_contents($pfxpath);
 //echo "<br>$s<br>";
 $key2 = openssl_pkey_get_private(file_get_contents($pfxpath));

 if(openssl_private_decrypt($crypted, $decrypted, $key2)){
 echo $decrypted;
 }
 else{
 echo "failed";
 }

 


客户端通过加载cer文件,将要加密的文本用公钥加密。以下是一个函数

//通过读取本地的cer文件,得到公钥,然后对文本内容加密,返回加密后的文本,最后传到服务器端,与密钥进行比对
public static String getRSAText(Context context,String strText){

    try {
        //读取证书文件

        InputStream inStream = context.getResources().getAssets().open("test.cer");
        //创建X509工厂类
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        //创建证书对象
        X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);
        inStream.close();

        Cipher c1 = Cipher.getInstance("RSA/None/PKCS1Padding");

        c1.init(Cipher.PUBLIC_KEY, cert);
        byte[] cipherText = c1.doFinal(strText.getBytes());


        //base64转换一下,方便传输
        String res = Base64.encodeToString(cipherText,Base64.DEFAULT);
        return res;


    }
    catch (InvalidKeyException e){

    }
    catch (IOException e){

    }
    catch (CertificateException e){

    }
    catch (NoSuchPaddingException e){

    }
    catch (IllegalBlockSizeException e){

    }
    catch (BadPaddingException e){

    }
    catch (NoSuchAlgorithmException e){

    }
    return "";
}

下边是php端用pfx文件(里边放有密钥)进行解密的代码。我改写成了一个函数。参数是pfx文件路径,pfx文件名,要解密的字符串

function getPassword( $path,$pfx_file_name,$str ){ 
 $pfxpath = $path . "/public/$pfx_file_name"; //密钥文件路径
 //$cerpath = "./test.cer"; //生成证书路径
 //私钥解密
 $decrypted = "";
 
 $key2 = openssl_pkey_get_private(file_get_contents($pfxpath)); 

 $res = openssl_private_decrypt(base64_decode($str), $decrypted, $key2);
 
 if($res){
 
 return $decrypted;
 }
 else{
 return "";
 }

}

Leave a Reply