I'm currently using the following code to generate CSRs with subjectAltName
for additional domains.
$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",
]);
But when I use openssl req -text -noout -verify -in csr.pem
to verify the generated CSR, the subjectAltName
is not listed under the Requested Extensions
section. Instead, subjectAltName
is added to the subject.
subjectAltName
is recognized in the first array, other arbitrary values result in an error. But how can I create a CSR in PHP with OpenSSL that really includes the subjectAltName
as requested extension?
This question is specifically about the bundled openssl_*
functions, not any third party library like phpseclib
.
I've been messing with this since the upvote and can't find an elegant solution, but I did find a workaround that might work for you. As you probably know, you can specify the alt names in the openssl config file. You can also specify your own config file in the configArgs
to openssl_csr_new
Combining these two, you could create/modify an openssl config file in a writable directory at runtime, like /tmp/, and then tell use it.
The relevant bit of code in your openssl_csr_new call looks like:
"digest_alg" => "sha256",
"req_extensions" => "v3_req",
"config" => "/path/to/config/file" // <-- new line
In the config file, you'll need to set the v3_req section up to use the alt names that will be in the file, e.g.
subjectAltName = @test_req
Then (re)create the test_req section, and populate it with your DNS names, e.g.
[ test_req ]
DNS.1 = foo.bar
DNS.2 = foo.baz
If you need more information, let me know. Maybe someone else can figure out how to shoehorn it into the php function directly, but this might be an openssl limitation.