2024 PHP Conference Japan

OpenSSL 函式

目錄

新增註記

使用者貢獻的註記 24 則註記

dan -AT- NOSPAM danschafer DOT netTT
17 年前
目前,PHP 中定義的所有 OpenSSL 函式僅使用 PEM 格式。使用以下程式碼在 DER 和 PEM 之間進行轉換。

<?php
$pem_data
= file_get_contents($cert_path.$pem_file);
$pem2der = pem2der($pem_data);

$der_data = file_get_contents($cert_path.$der_file);
$der2pem = der2pem($der_data);

function
pem2der($pem_data) {
$begin = "CERTIFICATE-----";
$end = "-----END";
$pem_data = substr($pem_data, strpos($pem_data, $begin)+strlen($begin));
$pem_data = substr($pem_data, 0, strpos($pem_data, $end));
$der = base64_decode($pem_data);
return
$der;
}

function
der2pem($der_data) {
$pem = chunk_split(base64_encode($der_data), 64, "\n");
$pem = "-----BEGIN CERTIFICATE-----\n".$pem."-----END CERTIFICATE-----\n";
return
$pem;
}
?>
skippy zuavra net
20 年前
如果您想知道什麼是 cainfo 可用的「正確雜湊」目錄:它只是一個包含 PEM/X.509 格式的 CA 公開憑證的目錄。您可以從憑證授權單位 (CA) 的網站(他們會在顯眼的地方公告)或從您的瀏覽器取得此類憑證。例如,在 Explorer 中,您可以點擊黃色小鎖頭,前往 CA 項目並匯出它。

關於目錄的唯一技巧是檔名必須採用「雜湊值.#」的格式。「雜湊值」部分是憑證的 8 位數十六進位雜湊值,而 # 部分是一個數字,用於區分產生相同雜湊值的憑證(是的,使用來自同一個 CA 的憑證可能會發生這種情況)。通常 # 為 0,但當您有更多具有相同雜湊值的憑證時,您也可以使用 1、2 等。

為了取得憑證的雜湊值,您可以使用 openssl 命令列工具,如下所示

openssl x509 -hash -in certfile.cer | head -1
peter dot mescalchin @ geemail dot com
18 年前
對於使用 w32 的使用者,若要啟用 OpenSSL 支援,除了將 "libeay32.dll" 複製到 Windows 的 system32 資料夾之外,還需要複製 "ssleay32.dll"。上述文件應該更新以說明這一點。

這個需求已記錄在 libcurl 的網頁上

http://curl.haxx.se/libcurl/php/install.html#windows
kraven at kraven dot org
11 年前
如果您想驗證 CSR 是否已從您的私鑰正確產生,您可以執行以下操作

<?php
$countryName
= "UK";
$stateOrProvinceName = "London";
$localityName = "Blah";
$organizationName = "Blah1";
$organizationalUnitName = "Blah2";
$commonName = "Joe Bloggs";
$emailAddress = "openssl@example.com";

$dn = array(
"countryName" => $countryName,
"stateOrProvinceName" => $stateOrProvinceName,
"localityName" => $localityName,
"organizationName" => $organizationName,
"organizationalUnitName" => $organizationalUnitName,
"commonName" => $commonName,
"emailAddress" => $emailAddress
);

$badPriv = 'foo';

// 產生一個錯誤的 CSR
$badCsr = openssl_csr_new($dn, $badPriv);

// 產生私鑰
$priv = openssl_pkey_new();

// 產生 CSR
$csr = openssl_csr_new($dn, $priv);

$badCsrDetails = openssl_pkey_get_details(openssl_csr_get_public_key($badCsr));
$privDetails = openssl_pkey_get_details($priv);
$csrDetails = openssl_pkey_get_details(openssl_csr_get_public_key($csr));

echo
md5($badCsrDetails['rsa']['n']);
echo
"\n不相符\n";
echo
md5($privDetails['rsa']['n']);
echo
"\n相符\n";
echo
md5($csrDetails['rsa']['n']);
echo
"\n";
?>

這個輸出是模數的 md5 雜湊值。可以使用 openssl 進行相同的檢查
openssl rsa -noout -modulus -in server.key | openssl md5
openssl req -noout -modulus -in server.csr | openssl md5
jts
17 年前
使用 Win32 的用戶如果在讓 php_openssl 正常運作時遇到問題,應該確保他們使用 PHP 附帶的版本替換所有版本的 libeay32.dll 和 ssleay32.dll。這在同時使用 Apache2 和 OpenSSL 時尤其如此,因為某些 OpenSSL win32 套件包含這兩個檔案的舊版本。
greensweater
19 年前
「此函式需要安裝有效的 openssl.cnf 才能正常運作」包含大多數 openssl 函式。您可以強制 php 找到您的 openssl.cnf 檔案,如下所示

$config = array('config'=>'/path/to/openssl.cnf');
$pkey = openssl_pkey_new($config);
$csr = openssl_csr_new('MyCSR',$pkey,$config);
rahuul at yours dot com
14 年前
以下是更改憑證序號的解決方案

<?php
$sscert
= openssl_csr_sign($csr, $cacert, $privkey, $days,$config,$serial);
?>
yabba dabba
18 年前
適用於 Windows/IIS 的 php4 發行版有一個 README-SSL.txt 檔案,它強烈暗示只需將路徑添加到伺服器環境變數中的 OPENSLL_CONF 變數即可。請務必同時新增檔案名稱和副檔名。

例如:c:\php-4.3.11\openssl\openssl.cnf
web at mburda dot com
16 年前
Matt Alexander 以下的程式碼有點問題。
公開金鑰和私密金鑰都在內部產生並儲存到 OpenSSL 類別物件屬性中,但之後只使用了私密金鑰。
公開金鑰取自外部檔案,如果它與內部儲存的公開金鑰不同,OpenSSL 將無法解密文字。
stephen_at_liberty-irm_dot_com
16 年前
這則注意事項主要針對將加密內容儲存在 MySQL 中的人,因為我不熟悉其他資料庫設定。例如,如果您儲存已使用 openssl_public_encrypt 加密並儲存在資料庫中的信用卡號碼,則用於儲存號碼的欄位類型必須是 blob。這是因為「結果可能包含任意位元組值」(MySQL 參考手冊)。基本上,如果您嘗試將其儲存在 VARCHAR、LONGTEXT 等中,則加密資料的某些部分可能會被刪除、截斷等。這當然會導致資料無法解密。希望這可以幫助到某些人,因為它困擾了我大約一個小時!
karel dot wintersky at gmail dot com
7 年前
可能對密碼執行速度有用。

<?php
// PHP 7.0+ required!
// see results at https://gist.github.com/KarelWintersky/fe29dcad75de515e5a468894e7c070e6

const TEST_COUNT = 100000;
const
SOURCE = 'Note that HTML tags are not allowed in the posts, but the note formatting is preserved.';
const
KEY = "password";

function
TESTER( $testing_function, $argument )
{
$t = microtime(true);

for (
$test_iterator = 0; $test_iterator < TEST_COUNT; $test_iterator++) {
$testing_function( $argument );
}
return
round(microtime(true) - $t, 4);
}

$crypt = function($cipher) {
$ivlen = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($ivlen);
openssl_encrypt(SOURCE, $cipher, KEY, $options=0, $iv);
};

$methods = openssl_get_cipher_methods(false);

array_splice( $methods, 0, count($methods) / 2);

$timings = array();

foreach (
$methods as $cypher) {
$time = TESTER( $crypt, $cypher );
$timings[ $cypher ] = $time;
echo
str_pad($cypher, 40, ' ', STR_PAD_LEFT), " have time ", str_pad($time, 8, STR_PAD_LEFT), ' seconds. ', PHP_EOL;
}

uasort($timings, function($a, $b){
return
$a <=> $b;
});

$min_time = round(reset($timings) / TEST_COUNT, 7);
$min_cypher = key($timings);

$max_time = round(end($timings) / TEST_COUNT, 7);
$max_cypher = key($timings);

echo
'-------------', PHP_EOL;
echo
"Total tests: ", count($timings), PHP_EOL;
echo
"Max timing : {$max_time} seconds for `{$max_cypher}` algorithm.", PHP_EOL;
echo
"Min timing : {$min_time} seconds for `{$min_cypher}` algorithm.", PHP_EOL;

echo
'Details: ', PHP_EOL;

foreach (
$timings as $m => $t) {
echo
'- ', str_pad($t, 8, STR_PAD_LEFT), " seconds for `{$m}`", PHP_EOL;
}

echo
PHP_EOL;
kurian at net4ideas dot com
17 年前
要在 Windows 平台的 IIS 網頁伺服器上使用 OpenSSL,我們需要在 php.ini 中啟用它,然後將 libeay32.dll 和 ssleay32.dll 複製到 PHP 資料夾(或 Windows 的 system32 資料夾),並將這兩個 DLL 的路徑添加到 Windows 的 PATH 環境變數中。在我完成這些更改後,它似乎對我來說可以正常運作。
matt at NOSPAMopenflowsPLEASE dot org
19 年前
OpenSSL 函式在 Debian 3.0 (woody) 中被停用,但從 3.1 (sarge) 版開始,它們又再次可用了。
greensweater
19 年前
抱歉,我上一則留言中的程式碼無法運作... 最後一行應該改成

$csr = openssl_csr_new(array('commonName'=>'MyCSR'),$pkey,$config);
匿名
4 年前
對第一個評論的改進,此函式在將 PEM 格式轉換為 DER 格式時,將能正確處理憑證鏈。

<?php

function pemToDer(string $pem_data): string
{
$der_data = '';

$begin = "-----BEGIN CERTIFICATE-----";
$end = "-----END CERTIFICATE-----";
while (
strpos($pem_data, $begin) !== false) {
$pem_data = substr($pem_data, strpos($pem_data, $begin) + strlen($begin));
$der_data .= substr($pem_data, 0, strpos($pem_data, $end));
$pem_data = substr($pem_data, strpos($pem_data, $end) + strlen($end));
}

return
base64_decode($der_data);
}
jaz at ensn dot net
20 年前
給新手們(例如我)
如果您想在 Win32 的家用電腦上嘗試,您可以透過以下網址學習如何在 Win32 上安裝 Apache+SSL:http://tud.at/programm/apache-ssl-win32-howto.php3

提供英文、西班牙文和法文版本。

我閱讀了說明並安裝,它完美地運作。
norman at rasmussen dot org
20 年前
Debian 維護者已停用 openssl 支援,因為它似乎會導致 Apache 在啟動時崩潰。(http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=193343http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=165699)

- Norman
daevid at daevid dot com
17 年前
這裡似乎沒有函式可以測試憑證是否有效(例如,未損毀)... 這段 bash 程式碼片段應該會有幫助。抱歉,這不是 PHP。把它放在 system(); 呼叫中,或者把它做成 bash 腳本,然後用那種方式呼叫它之類的...

if [ "`openssl x509 -in /etc/certs/my.crt -noout -modulus`" = "`openssl rsa -in /etc/keys/my.key -noout -modulus`" ]; then echo "Match"; else echo "Different"; fi
Richard Ablewhite
18 年前
Windows 使用者請注意,您需要在 system32 中放入以下檔案

msvcr71.dll

它必須放在 system32 中,php/dlls 資料夾不會被搜尋到。
ChronoFish
17 年前
下方有一則注意事項,提到在 Win32 系統上需要將 ssleay32.dll 和 libeay32.dll 複製到系統 PATH 中的資料夾。

這絕對是正確的。還需要注意的是,Windows 會先搜尋 Windows 系統目錄,然後才會搜尋 PATH。如果這些目錄中已有現有的 .dll 檔案,請重新命名它們(而不是刪除,以防您需要復原變更),並複製這些檔案的最新版本。

關鍵位置可能包含 /i386、/windows/system32 和 ~/apache/.../modules 目錄。

我也更新了我的 ~/subversion/bin 目錄。

-CF
igor dot gorshkov at gmail dot com
17 年前
我用這種方式產生憑證。

$config = array("config" => "d:/sslcert/openssl.cnf");
$dn = array(
"countryName" => "RU",
"stateOrProvinceName" => "Russia",
"localityName" => "Saint-Petersburg",
"organizationName" => "temp",
"organizationalUnitName" => "temp",
"commonName" => "temp",
"emailAddress" => "temp@temp.com"
);
$privkey_enc = openssl_pkey_new($config);
$csr = openssl_csr_new($dn, $privkey_enc, $config);
$sscert = openssl_csr_sign($csr, null, $privkey_enc, 365);
openssl_x509_export_to_file($sscert, "d:/cert_enc.crt");
openssl_pkey_export_to_file($privkey_enc, "d:/privkey_enc.pem");

結果所有收到的憑證都具有相同的序號 (00)。但這不應該發生!如何避免這種情況?
mattalexx at gmail dot com
17 年前
使用這個方法進行簡單的公鑰/私鑰加密。

<?php

/**
* Point to your config file
*
*/
define("OPEN_SSL_CONF_PATH", "/usr/share/ssl/openssl.cnf");
/**
* Length of time certificate is valid (in days)
*
*/
define("OPEN_SSL_CERT_DAYS_VALID", 365);
/**
* Passphrase required with private key
*
*/
define("OPEN_SSL_PASSPHRASE", "lkdfjbjeyrasdfvkajwdeblsolkdkdjfbvzslalsmdbfvksb");
/**
* Enter description here...
*
*/
define("OPEN_SSL_PUBKEY_PATH", "/docs/domains/mywebsite.com/docs/key.pem"); // Public key path

/**
* A wrapper class for a simple subset of the PHP OpenSSL functions. Use for public key encryption jobs.
*
* <code>
*
* // To configure
* // 1. Set OPEN_SSL_CONF_PATH to the path of your openssl.cnf file.
* // 2. Set OPEN_SSL_PASSPHRASE to any passphrase.
* // 3. Use the OpenSSL::do_csr method to generate your private and public keys (see next section).
* // 4. Save the private key somewhere offline and save your public key somewhere on this machine.
* // 5. Set OPEN_SSL_PUBKEY_PATH to the public key's path.
*
* // To generate keys
* $ossl = new OpenSSL;
* $ossl->do_csr();
* $privatekey = $ossl->privatekey;
* $publickey = $ossl->publickey;
* unset($ossl);
*
* // Encrypt
* $text = "Secret text";
* $ossl = new OpenSSL;
* $ossl->encrypt($text);
* $encrypted_text = $ossl->crypttext;
* $ekey = $ossl->ekey;
* unset($ossl);
*
* // Decrypt
* $ossl = new OpenSSL;
* $decrypted_text = $ossl->decrypt($encrypted_text, $privatekey, $ekey);
* unset($ossl);
*
* @author Matt Alexander (mattalexx@gmail.com) [based on code by Alex Poole (php@wwwcrm.com)]
* @copyright 2007
*
*/
class OpenSSL {

public
$privatekey;
public
$publickey;
public
$csr;
public
$crypttext;
public
$ekey;

public function
encrypt($plain) {

// Turn public key into resource
$publickey = openssl_get_publickey(is_file(OPEN_SSL_PUBKEY_PATH)? file_get_contents(OPEN_SSL_PUBKEY_PATH) : OPEN_SSL_PUBKEY_PATH);

// Encrypt
openssl_seal($plain, $crypttext, $ekey, array($publickey));
openssl_free_key($publickey);

// Set values
$this->crypttext = $crypttext;
$this->ekey = $ekey[0];
}

public function
decrypt($crypt, $privatekey, $ekey="") {

// Turn private key into resource
$privatekey = openssl_get_privatekey((is_file($privatekey)? file_get_contents($privatekey) : $privatekey), OPEN_SSL_PASSPHRASE);

// Decrypt
openssl_open($crypt, $plaintext, $ekey, $privatekey);
openssl_free_key($privatekey);

// Return value
return $plaintext;
}

public function
do_csr(
$countryName = "UK",
$stateOrProvinceName = "London",
$localityName = "Blah",
$organizationName = "Blah1",
$organizationalUnitName = "Blah2",
$commonName = "Joe Bloggs",
$emailAddress = "openssl@domain.com"
) {
$dn = array(
"countryName" => $countryName,
"stateOrProvinceName" => $stateOrProvinceName,
"localityName" => $localityName,
"organizationName" => $organizationName,
"organizationalUnitName" => $organizationalUnitName,
"commonName" => $commonName,
"emailAddress" => $emailAddress
);
$config = array(
"config" => OPEN_SSL_CONF_PATH
);
$privkey = openssl_pkey_new();
$csr = openssl_csr_new($dn, $privkey, $config);
$sscert = openssl_csr_sign($csr, null, $privkey, OPEN_SSL_CERT_DAYS_VALID, $config);
openssl_x509_export($sscert, $this->publickey);
openssl_pkey_export($privkey, $this->privatekey, OPEN_SSL_PASSPHRASE, $config);
openssl_csr_export($csr, $this->csr);
}

}

?>
php ~at~ wwwcrm dot komm
19 年前
如果您想使用 PHP 進行公鑰/私鑰加密工作,而不需要了解 Open SSL 擴充套件的細節,以下內容可能會讓您感興趣

http://www.karenandalex.com/php_stuff/_class_OpenSSL.phps

這個類別先前有一段時間無法使用(伺服器問題),但現在已恢復。對於點選連結卻收到 404 錯誤訊息的使用者,我們深感抱歉

希望它對您有所幫助...

Alex
beckman at purplecow dot com
19 年前
FreeBSD Ports tree php5-openssl 使用 openssl-0.9.8a。這是一個問題,因為如果您安裝這兩個 ports 並嘗試在 PHP 中開啟 HTTPS URL,它會失敗並顯示 openssl_error_string() 的錯誤訊息:error:140A90A1:SSL routines:func(169):reason(161),也就是 SSL_R_LIBRARY_HAS_NO_CIPHERS 或「程式庫沒有加密法」。

這是因為 openssl 程式庫現在需要您手動載入加密法 — 並非所有加密法都會自動為您載入。

我不認為 php5-openssl 模組在開啟 SSL 連線之前已更新過這個功能(截至 5.0.5 版)。

使用 openssl-0.9.7i 似乎可以運作;將 libcrypto.so.3 符號連結到 libcrypto.so.4 可以防止 php5-openssl 連接埠嘗試安裝 openssl-0.9.8a。因此,請先從 ports 安裝 openssl-stable (0.9.7i),接著建立符號連結,然後再安裝 php5-openssl,這樣就應該沒問題了。
To Top