$config = array( "digest_alg" => "sha512", "private_key_bits" => 4096, "private_key_type" => OPENSSL_KEYTYPE_RSA, ); $private_key_passwd = '123456'; //私鑰密碼 $expire = 365; //有效時長 $cer_path = "./test.cer"; //生成證書路徑 $pfx_path = "./test.pfx"; //密鑰文件路徑 $dn = array( "countryName" => "CN", //所在國家 "stateOrProvinceName" => "ANHUI", //所在省份 "localityName" => "HEFEI", //所在城市 "organizationName" => "Mr.sui", //註冊人姓名 "organizationalUnitName" => "sui Team", //組織名稱 "commonName" => "lucky", //公共名稱 "emailAddress" => "sui@qq.com" //郵箱 ); // 生成公鑰私鑰資源 $res = openssl_pkey_new($config); // 導出私鑰 $private_key openssl_pkey_export($res, $private_key,null,$config); // 導出公鑰 $pubKey $public_key = openssl_pkey_get_details($res); $public_key = $public_key["key"]; //print_r($private_key); 私鑰 //print_r($public_key); 公鑰 //直接測試私鑰 公鑰 echo '-------------------公私鑰加解密T---------------------'.PHP_EOL; $data = '我是 data,哈哈哈'; // 公鑰加密 openssl_public_encrypt($data, $encrypted, $public_key); // 私鑰解密 openssl_private_decrypt($encrypted, $decrypted, $private_key); echo '公鑰加密:',base64_encode($encrypted).PHP_EOL; echo '私鑰解密後的數據:'. $decrypted.PHP_EOL; echo '-------------------公私鑰加解密-END---------------------'.PHP_EOL; echo '-------------------生產證書---------------------'.PHP_EOL; //生成文件 $csr = openssl_csr_new($dn, $private_key,$config); //基於$dn生成新的 CSR (證書籤名請求) $sscert = openssl_csr_sign($csr, null, $private_key, 365,$config);//根據配置本身對證書進行簽名 openssl_x509_export($sscert, $csrkey); //將公鑰證書存儲到一個變量 $csrkey,由 PEM 編碼格式命名。 openssl_pkcs12_export($sscert, $new_private_key, $private_key, $private_key_passwd); //將私鑰存儲到名爲的出 PKCS12 文件格式的字符串。 導出密鑰$new_private_key //生成證書文件 $fp = fopen($cer_path, "w"); fwrite($fp, $csrkey); fclose($fp); //生成密鑰文件 $fp = fopen($pfx_path, "w"); fwrite($fp, $new_private_key); fclose($fp); echo '-------------------生產證書END---------------------'.PHP_EOL; echo '----------------------自簽名驗證-START----------------------'.PHP_EOL; // 測試私鑰 祕鑰 $private_key_passwd = '123456'; //私鑰密碼 $pfx_path = "./test.pfx"; //密鑰文件路徑 $priv_key = file_get_contents($pfx_path); //獲取密鑰文件內容 $data = "測試數據!"; //加密數據測試test //私鑰加密 openssl_pkcs12_read($priv_key, $certs, $private_key_passwd); //讀取公鑰、私鑰 $prikeyid = $certs['pkey']; //私鑰 openssl_sign($data, $signMsg, $prikeyid,OPENSSL_ALGO_SHA1); //註冊生成加密信息 $signMsg = base64_encode($signMsg); //base64轉碼加密信息 //公鑰解密 $unsignMsg = base64_decode($signMsg);//base64解碼加密信息 openssl_pkcs12_read($priv_key, $certs, $private_key_passwd); //讀取公鑰、私鑰 $pubkeyid = $certs['cert']; //公鑰 $res = openssl_verify($data, $unsignMsg, $pubkeyid); //驗證 echo $res?'證書測試成功!':'證書測試失敗!'; //輸出驗證結果,1:驗證成功,0:驗證失敗 var_dump($res); echo '-----------------------簽名驗證-END------------------------',PHP_EOL;
註釋:安全
x509,公鑰證書,只有公鑰。
p7,簽名或加密。能夠往裏面塞x509,同時沒有簽名或加密內容。
p12,含有私鑰,同時能夠有公鑰,有口令保護。
p7的做用就是電子信封。
X509是基本規範
P7和P12是兩個實現規範,P7是數字信封,P12是帶有私鑰的證書規範。
x509是數字證書的規範,P7和P12是兩種封裝形式。好比說一樣的電影,有的是avi格式,有的是mpg,大概就這個意思。
P7通常是把證書分紅兩個文件,一個公鑰一個私鑰,有PEM和DER兩種編碼方式。PEM比較多見,就是純文本的,P7通常是分發公鑰用,看到的就是一串可見字符串,擴展名常常是.crt,.cer,.key等。DER是二進制編碼。
P12是把證書壓成一個文件,.pfx 。主要是考慮分發證書,私鑰是要絕對保密的,不能隨便以文本方式散播。因此P7格式不適合分發。.pfx中能夠加密碼保護,因此相對安全些。
在實踐中要中,用戶證書都是放在USB Key中分發,服務器證書常常仍是以文件方式分發。服務器證書和用戶證書,都是X509證書,就是裏面的屬性有區別。
X509 是證書規範
PKCS#7 是消息語法 (經常使用於數字簽名與加密)
PKCS#12 我的消息交換與打包語法 (如.PFX .P12)打包成帶公鑰與私鑰服務器