生成带有 subjectAltName 扩展名的 CSR

Generate CSR with subjectAltName extension

我目前正在使用以下代码为其他域生成带有 subjectAltName 的 CSR。

$domains = ["example.com", "www.example.com"];

$san = implode(",", array_map(function ($dns) {
        return "DNS:" . $dns;
}, $domains));

$csr = openssl_csr_new([
    "CN" => reset($domains),
    "ST" => "Germany",
    "C" => "DE",
    "O" => "Unknown",
    "subjectAltName" => $san,
], $privateKey, [
    "digest_alg" => "sha256",
    "req_extensions" => "v3_req",
]);

但是当我使用openssl req -text -noout -verify -in csr.pem验证生成的CSR时,subjectAltName没有列在Requested Extensions部分。相反,subjectAltName 被添加到主题中。

subjectAltName在第一个数组中识别,其他任意值导致错误。但是我如何使用 OpenSSL 在 PHP 中创建一个真正包含 subjectAltName 作为请求扩展的 CSR?

这个问题专门针对捆绑的 openssl_* 函数,而不是 phpseclib 等任何第三方库。

自投票以来我一直在搞乱这个问题,找不到一个优雅的解决方案,但我确实找到了一个可能适合你的解决方法。您可能知道,您可以在 openssl 配置文件中指定替代名称。您也可以在 configArgsopenssl_csr_new

中指定您自己的配置文件

结合这两者,你可以create/modify在运行时可写目录中的 openssl 配置文件,如 /tmp/,然后告诉使用它。

您的 openssl_csr_new 调用中的相关代码如下所示:

"digest_alg" => "sha256",
"req_extensions" => "v3_req",
"config" => "/path/to/config/file" // <-- new line

在配置文件中,您需要设置 v3_req 部分以使用文件中的替代名称,例如

subjectAltName = @test_req

然后(重新)创建 test_req 部分,并用您的 DNS 名称填充它,例如

[ test_req ]
DNS.1 = foo.bar
DNS.2 = foo.baz

如果您需要更多信息,请告诉我。也许其他人可以弄清楚如何将它直接塞进 php 函数,但这可能是 openssl 的限制。