Ever tried generating CSR with SANs? It is tedious work. It involves populating an openssl config file with the additional domain names. Put it on a webapp, it does not eliminate the work, but only require minimal coding once.
SANs certificate is an extension to X.509, which allows additional domain names to be added to a certificate. As people starts to put more and more domains in a certificate, the work to generate a CSR becomes cumbersome. Maybe the future version of openssl will simplify the process. Until then, the domain names need to be put in a config file for openssl to read.
Building a webapp, or more like a couple of php pages make life easier. First, check that the openssl extension is enabled on php. Then here comes the php code.
Generate a RSA key, export the private key to a string variable
$keypair = openssl_pkey_new(array('private_key_bits' => 2048));
openssl_pkey_export($keypair, $privKey);
Create a form, get the usual inputs
$dn = array(
"countryName" => $_POST["country"],
"stateOrProvinceName" => $_POST["state"],
"localityName" => $_POST["city"],
"organizationName" => $_POST["orgname"],
"commonName" => $_POST["cn"],
"emailAddress" => $_POST["email"]
);
Use a textarea to gather the SANs, then put it in an array
$sansRaw = $_POST["sans"];
$sansArr = explode("\n", $sansRaw);
$sansArr = array_filter($sansArr, 'trim');
Write that to a temp openssl config file
$sslConfig = file_get_contents("/data/sites/x/csr/ssl-template.cnf");
$counter = 1;
foreach ($sansArr as $line) {
$fqdn = tidyFqdn($line);
$sslConfig = $sslConfig . "\nDNS." . $counter . "=" . $fqdn;
$counter++;
}
$sslConfigFile = "/data/sites/x/csr/tmp/ssl.cnf-" . rand();
file_put_contents($sslConfigFile, $sslConfig);
The template config looks like this
[ req ] distinguished_name = req_distinguished_name [ req_distinguished_name ] countryName = Country Name (2 letter code) stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Some-State localityName = Locality Name (eg, city) 0.organizationName = Organization Name (eg, company) organizationalUnitName = Organizational Unit Name (eg, section) commonName = Common Name (e.g. server FQDN or YOUR name) emailAddress = Email Address [ v3_req ] subjectAltName = @req_sans [ req_sans ]
Create a config array and generate the CSR
$csrConfig = array(
"digest_alg" => "sha256",
"req_extensions" => "v3_req",
"config" => $sslConfigFile
);
$csrRes = openssl_csr_new($dn, $privKey, $csrConfig);
openssl_csr_export($csrRes, $csr);
The CSR is now in the $csr variable. The private key that goes with it is in $privKey.
![]()