公鑰加密後的字元串是一直變化的,但是用私鑰解密後的内容仍然是相同的,這是為了加密資料使用的。
私鑰加密的字元串是不會變化的,即使暴露在外網上别人截取時如果沒有公鑰也是看不出來内容的,僅允許給予公鑰的第三方來解密并看到内容,實際作用相當于簽名功能,如果能拿到未加密的内容,說明一定是信任方的資料,因為有他的簽名啊。
其實這種非對稱加密技術可以用于單點登入中去,安全級别高,能解密擷取到内容應該就是信任方的資料。
<?php
namespace Common\Org;
class RsaCrypt {
const CERPATH ='../Application/Runtime/Data/server.cer'; //生成證書路徑
const PFXPATH = '../Application/Runtime/Data/server.pfx'; //秘鑰檔案路徑
const FILEDIR = '../Application/Runtime/Data/';
/**
* 生成公鑰私鑰
*/
public static function generateCertKey()
{
$dn = array('countryName'=>'CN', 'stateOrProvinceName'=>'beijing', 'localityName'=>'beijing','organizationName'=>'clcw',
'organizationalUnitName'=>'clcw', 'commonName'=>'clcw', 'emailAddress'=>'[email protected]');
$privkeypass = 'secret'; //私鑰密碼
$numberOfDays = 365; //有效時長,機關為天
//生成證書
$privkey = openssl_pkey_new();
$csr = openssl_csr_new($dn, $privkey);
$sscert = openssl_csr_sign($csr, null, $privkey, $numberOfDays);
openssl_x509_export_to_file($sscert, self::CERPATH);
openssl_pkcs12_export_to_file($sscert, self::PFXPATH, $privkey, $privkeypass);
(file_exists(self::CERPATH)) or die('公鑰的檔案路徑錯誤');
(file_exists(self::PFXPATH)) or die('密鑰的檔案路徑錯誤');
}
public static function verifyData($originData, $decryptData)
{
$cer_key = file_get_contents(self::$cerpath);
$cer = openssl_x509_read($cer_key);
$res = openssl_verify($originData, $decryptData, $cer);
var_dump($res);
}
/**
* 生成公鑰私鑰檔案
* @param $appName string 應用名稱
*/
public static function generateKey($appName='')
{
$result = ['status'=>0, 'msg'=>''];
if (!extension_loaded('openssl') ) {
$result['msg'] = 'php需要openssl支援';
}
//建立公鑰
$res = openssl_pkey_new();//array('private_key_bits'=>512) 這一串參數不加,否則隻能加密54個長度的字元串
//提取私鑰
openssl_pkey_export($res, $privatekey);
//生成公鑰
$public_key = openssl_pkey_get_details($res);
$publickey = $public_key['key'];
// $path = self::FILEDIR.$appName;
try{
// file_put_contents($path.'_public.pem', $publickey);
// file_put_contents($path.'_private.pem', $privatekey);
$result['status'] = 1;
$result['publickey'] = $publickey;
$result['privatekey'] = $privatekey;
}catch(\Exception $e) {
// throw new \Exception($e->getMessage());
$result['msg'] = $e->getMessage();
}
return $result;
}
/**
* 用私鑰加密資料
* @param $data string 需要加密的字元串(最好不要超過200個字元)
* @param $appName string 應用名稱
*/
public static function privateEncrypt($data, $appName)
{
$result = ['status'=>0, 'msg'=>''];
$privatekey = C($appName.'.PRIVATE_KEY');
$myinfo = 'In '.__METHOD__.',privatekey:'.$privatekey."\n";
file_put_contents('/tmp/shiyf.log', $myinfo, FILE_APPEND);
//生成resource類型的密鑰,如果密鑰檔案内容被破壞,openssl_pkey_get_private函數傳回false
$privatekey = openssl_pkey_get_private($privatekey);
if (empty($privatekey)) {
$result['msg'] = '密鑰不可用';
}
$encryptData = '';
//用私鑰加密
if (openssl_private_encrypt($data, $encryptData, $privatekey)) {
$result['msg'] = base64_encode($encryptData);
$result['status'] = 1;
} else {
$result['msg'] = '加密失敗!';
}
return $result;
}
/**
* 用公鑰解密資料
* @param $data string 需要解密的字元串(最好不要超過200個字元)
* @param $appName string 應用名稱
*/
public static function publicDecrypt($data, $appName)
{
$result = ['status'=>0, 'msg'=>''];
$data = base64_decode($data);
$publickey = C($appName.'.PUBLIC_KEY');
//生成resource類型的公鑰,如果公鑰檔案内容被破壞,openssl_pkey_get_public函數傳回false
$publickey = openssl_pkey_get_public($publickey);
if (empty($publickey)) {
$result['msg'] = '公鑰不可用';
}
//解密資料
$decryptData = '';
if (openssl_public_decrypt($data, $decryptData, $publickey)) {
$result['msg'] = $decryptData;
$result['status'] = 1;
} else {
$result['msg'] = '解密失敗';
}
return $result;
}
/**
* 用公鑰加密資料
* @param $data string 需要加密的字元串(最好不要超過200個字元)
* @param $appName string 應用名稱
*/
public static function publicEncrypt($data, $publickey)
{
$result = ['status'=>0, 'msg'=>''];
//生成resource類型的公鑰,如果公鑰檔案内容被破壞,openssl_pkey_get_private函數傳回false
$publickey = openssl_pkey_get_public($publickey);
if (empty($publickey)) {
$result['msg'] = '公鑰不可用';
}
$encryptData = '';
//用私鑰加密
if (openssl_public_encrypt($data, $encryptData, $publickey)) {
$result['msg'] = base64_encode($encryptData);
$result['status'] = 1;
} else {
$result['msg'] = '加密失敗!';
}
return $result;
}
/**
* 用私鑰加密資料
* @param $data string 需要解密的字元串(最好不要超過200個字元)
* @param $appName string 應用名稱
*/
public static function privateDecrypt($data, $appName)
{
$result = ['status'=>0, 'msg'=>''];
$data = base64_decode($data);
$privatekey = C($appName.'.PRIVATE_KEY');
//生成resource類型的私鑰,如果私鑰檔案内容被破壞,openssl_pkey_get_public函數傳回false
$privatekey = openssl_pkey_get_private($privatekey);
if (empty($privatekey)) {
$result['msg'] = '私鑰不可用';
}
//解密資料
$decryptData = '';
if (openssl_private_decrypt($data, $decryptData, $privatekey)) {
$result['msg'] = $decryptData;
$result['status'] = 1;
} else {
$result['msg'] = '解密失敗';
}
return $result;
}
}