OpenSSL 函数

目录

添加说明

用户贡献说明 24 条说明

25
dan -AT- NOSPAM danschafer DOT netTT
17 年前
目前,PHP 中定义的所有 OpenSSL 函数仅使用 PEM 格式。使用以下代码将 DER 转换为 PEM,并将 PEM 转换为 DER。

<?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;
}
?>
9
skippy zuavra net
19 年前
如果您想知道用于 cainfo 的“正确哈希”目录是什么:它只是一个包含 PEM/X.509 格式的 CA 公钥证书的目录。您可以从 CA 的网站(他们在显眼的地方宣传它)或从您的浏览器获取这些证书。例如,在 Explorer 中,您可以单击黄色挂锁,转到 CA 条目并导出它。

目录的唯一技巧是文件名必须采用“hash.#”格式。“hash”部分是证书的 8 位十六进制哈希值,而 # 部分是一个数字,用于区分具有相同哈希值的证书(是的,证书来自同一个 CA 时可能会发生这种情况)。通常 # 为 0,但如果有多个具有相同哈希值的证书,也可以使用 1、2 等。

为了获取证书的哈希值,可以使用 openssl 命令行工具,如下所示

openssl x509 -hash -in certfile.cer | head -1
5
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
3
kraven at kraven dot org
11 年前
如果要验证 csr 是否从您的私钥正确生成,可以执行以下操作

<?php
$countryName
= "UK";
$stateOrProvinceName = "London";
$localityName = "Blah";
$organizationName = "Blah1";
$organizationalUnitName = "Blah2";
$commonName = "Joe Bloggs";
$emailAddress = "[email protected]";

$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
"\nDoes not match\n";
echo
md5($privDetails['rsa']['n']);
echo
"\nMatches\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
2
jts
16 年前
Win32 用户在使用 php_openssl 时遇到问题,应该确保他们用 PHP 附带的版本替换所有版本的 libeay32.dll 和 ssleay32.dll。这在使用 Apache2 和 OpenSSL 协同工作时尤其重要,因为某些 OpenSSL win32 包包含这些文件的旧版本。
2
greensweater
18 年前
“您需要安装一个有效的 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);
1
rahuul at yours dot com
14 年前
更改证书的序列号,解决方案如下

<?php
$sscert
= openssl_csr_sign($csr, $cacert, $privkey, $days,$config,$serial);
?>
1
yabba dabba
18 年前
适用于 Windows/IIS 的 php4 发行版有一个 README-SSL.txt,其中强烈暗示只需要将路径添加到服务器环境变量中的 OPENSLL_CONF 变量即可。请确保也添加文件名和扩展名。

例如:c:\php-4.3.11\openssl\openssl.cnf
1
web at mburda dot com
16 年前
Matt Alexander 下面的代码存在一个小问题。
公钥和私钥都在内部生成并保存到 OpenSSL 类对象属性中,但只使用私钥。
公钥来自外部文件,如果它与内部存储的公钥不同,OpenSSL 将无法解密文本。
1
stephen_at_liberty-irm_dot_com
16 年前
此说明主要针对将加密内容存储在 MySQL 中的人员,因为我不熟悉其他数据库设置。例如,如果您存储使用 openssl_public_encrypt 加密的信用卡号码,则存储该号码的列类型必须为 blob。这是因为“结果可能包含任意字节值”(MySQL 参考手册)。基本上,如果您尝试将其存储在 VARCHAR、LONGTEXT 等中,则加密数据的某些部分可能会被丢弃、截断等。这当然会使数据无法解密。希望这能帮到某人,因为这让我困惑了大约一个小时!
2
karel dot wintersky at gmail dot com
6 年前
可能对密码执行速度有用。

<?php
// 需要 PHP 7.0+ 版本!
// 查看结果请访问 https://gist.github.com/KarelWintersky/fe29dcad75de515e5a468894e7c070e6

const TEST_COUNT = 100000;
const
SOURCE = '注意,帖子中不允许使用 HTML 标签,但笔记格式将保留。';
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), " 耗时 ", str_pad($time, 8, STR_PAD_LEFT), ' 秒。 ', 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
"总测试次数: ", count($timings), PHP_EOL;
echo
"最大耗时: "{$max_time} 秒,使用 `{$max_cypher}` 算法。", PHP_EOL;
echo
"最小耗时: "{$min_time} 秒,使用 `{$min_cypher}` 算法。", PHP_EOL;

echo
'详细信息: ', PHP_EOL;

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

echo
PHP_EOL;
2
kurian at net4ideas dot com
16 年前
为了使 openssl 在 Windows 平台的 IIS Web 服务器上正常工作,您需要在 php.ini 文件中启用它,并将 libeay32.dll 和 ssleay32.dll 文件复制到 php 文件夹(或 Windows 的 system32 文件夹)中,并将这两个 DLL 的路径添加到 Windows 的 PATH 环境变量中。在我的操作完成之后,它似乎可以正常工作了。
1
matt at NOSPAMopenflowsPLEASE dot org
18 年前
在 Debian 3.0(woody)版本中,openssl 函数被禁用了,但从 3.1(sarge)版本开始,它们再次可用。
1
greensweater
18 年前
抱歉,我之前笔记中的代码不能工作……最后一行应该改成

$csr = openssl_csr_new(array('commonName'=>'MyCSR'),$pkey,$config);
-1
Anonymous
3 years ago
对第一个评论的改进,此函数将在从 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);
}
1
jaz at ensn dot net
19 年前
对于新手(像我一样)
如果您想在 win32 上尝试,您可以从以下 URL 了解如何安装 apache+ssl:http://tud.at/programm/apache-ssl-win32-howto.php3

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

我读过并安装,运行完美。
1
norman at rasmussen dot org
20 years ago
Debian 维护者禁用了 openssl 支持,因为它似乎会导致 Apache 启动失败。(http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=193343http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=165699

- Norman
0
daevid at daevid dot com
16 年前
这里似乎没有函数可以测试证书是否有效(即,是否损坏)……这个 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
0
Richard Ablewhite
17 年前
Windows 用户请注意,您需要在 system32 中有以下文件

msvcr71.dll

它必须放在 system32 中,不会从 php/dlls 中获取。
-1
ChronoFish
16 年前
下面有一个注释,说明在 Win32 系统上需要将 BOTH ssleay32.dll AND libeay32.dll 复制到系统 PATH 中的文件夹。

这是绝对正确的。还应该注意,Windows 会在搜索 PATH 之前搜索 Windows 系统目录。如果这些目录中存在现有 .dll 文件 - 重命名它们(而不是删除它们,以防您需要撤消更改),然后将这些文件的最新版本复制过来。

关键位置可能包括 /i386、/windows/system32 和 ~/apache/.../modules 目录。

我还更新了我的 ~/subversion/bin 目录。

-CF
-1
igor dot gorshkov at gmail dot com
17 年前
我以这种方式生成证书。

$config = array("config" => "d:/sslcert/openssl.cnf");
$dn = array(
"countryName" => "RU",
"stateOrProvinceName" => "俄罗斯",
"localityName" => "圣彼得堡",
"organizationName" => "temp",
"organizationalUnitName" => "temp",
"commonName" => "temp",
"emailAddress" => "[email protected]"
);
$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)。但它不应该这样!如何避免这种情况?
-3
mattalexx at gmail dot com
16 年前
将此用于简单的公钥/私钥加密。

<?php

/**
* 指向你的配置文件
*
*/
define("OPEN_SSL_CONF_PATH", "/usr/share/ssl/openssl.cnf");
/**
* 证书有效期(以天为单位)
*
*/
define("OPEN_SSL_CERT_DAYS_VALID", 365);
/**
* 私钥所需的密码
*
*/
define("OPEN_SSL_PASSPHRASE", "lkdfjbjeyrasdfvkajwdeblsolkdkdjfbvzslalsmdbfvksb");
/**
* 在这里输入描述...
*
*/
define("OPEN_SSL_PUBKEY_PATH", "/docs/domains/mywebsite.com/docs/key.pem"); // 公钥路径

/**
* PHP OpenSSL 函数的简单子集的包装类。用于公钥加密作业。
*
* <code>
*
* // 配置
* // 1. 将 OPEN_SSL_CONF_PATH 设置为 openssl.cnf 文件的路径。
* // 2. 将 OPEN_SSL_PASSPHRASE 设置为任何密码。
* // 3. 使用 OpenSSL::do_csr 方法生成你的私钥和公钥(见下一节)。
* // 4. 将私钥保存在离线某个地方,并将公钥保存在这台机器上的某个地方。
* // 5. 将 OPEN_SSL_PUBKEY_PATH 设置为公钥的路径。
*
* // 生成密钥
* $ossl = new OpenSSL;
* $ossl->do_csr();
* $privatekey = $ossl->privatekey;
* $publickey = $ossl->publickey;
* unset($ossl);
*
* // 加密
* $text = "Secret text";
* $ossl = new OpenSSL;
* $ossl->encrypt($text);
* $encrypted_text = $ossl->crypttext;
* $ekey = $ossl->ekey;
* unset($ossl);
*
* // 解密
* $ossl = new OpenSSL;
* $decrypted_text = $ossl->decrypt($encrypted_text, $privatekey, $ekey);
* unset($ossl);
*
* @author Matt Alexander ([email protected]) [基于 Alex Poole ([email protected]) 的代码]
* @copyright 2007
*
*/
class OpenSSL {

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

public function
encrypt($plain) {

// 将公钥转换为资源
$publickey = openssl_get_publickey(is_file(OPEN_SSL_PUBKEY_PATH)? file_get_contents(OPEN_SSL_PUBKEY_PATH) : OPEN_SSL_PUBKEY_PATH);

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

// 设置值
$this->crypttext = $crypttext;
$this->ekey = $ekey[0];
}

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

// 将私钥转换为资源
$privatekey = openssl_get_privatekey((is_file($privatekey)? file_get_contents($privatekey) : $privatekey), OPEN_SSL_PASSPHRASE);

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

// 返回值
return $plaintext;
}

public function
do_csr(
$countryName = "UK",
$stateOrProvinceName = "London",
$localityName = "Blah",
$organizationName = "Blah1",
$organizationalUnitName = "Blah2",
$commonName = "Joe Bloggs",
$emailAddress = "[email protected]"
) {
$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);
}

}

?>
-3
php ~at~ wwwcrm dot komm
18 年前
如果你想在不需要了解 Open SSL 扩展的来龙去脉的情况下使用 PHP 进行公钥/私钥加密作业,以下内容可能对你感兴趣

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

这个类有一段时间不可用(服务器问题),但现在已经恢复了。对于那些点击了但得到 404 错误的人,我表示歉意。

希望它对你有用...

Alex
-3
beckman at purplecow dot com
18 年前
FreeBSD Ports 树 php5-openssl 使用 openssl-0.9.8a。这是一个问题,因为如果你安装了这两个端口并试图在 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。所以首先从端口安装 openssl-stable (0.9.7i),然后进行符号链接,最后安装 php5-openssl,这样你就应该没问题了。
To Top