Menu
blog.headdesk.me
blog.headdesk.me

Create CSR with SANs on php

Posted on 2017/04/112017/04/15

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.

Loading

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Full text search

Recent Posts

  • Generate secure password
  • AWS Compute Savings Plans
  • AWS Zonal Shift
  • Coffee break…
  • Prevent private key from being committed to git
  • aws (14)
  • coffee (2)
  • headfi (1)
  • linux (9)
  • others (61)
  • security (2)
  • tech (41)
  • terraform (3)
  • wordpress (2)

Loading

apache aws awscli azure backup boot cloud coffee docker ec2 EL8 ElasticBeanstalk espresso featured git kernel lelit linux lvm meltdown MFA nat gateway php power proliant python rdp Redhat RHEL rpm Ryzen scp security smartarray smart switch snapshot spectre tech terraform ubuntu ubuntu upgrade vpn windows wordpress workspace

©2026 blog.headdesk.me | Powered by SuperbThemes