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

  • Error 0xc1900101 when updating to Windows 11 22H2
  • Apply changes to all member accounts in an AWS organization
  • RPI4 under voltage
  • Upgrade RockyLinux 8 to 9
  • Terraform and segregated permissions
  • aws (9)
  • coffee (1)
  • headfi (1)
  • linux (8)
  • others (57)
  • security (2)
  • tech (39)
  • wordpress (2)

Loading

apache apigateway aws awscli azure backup cloud coffee docker ec2 EL8 ElasticBeanstalk enpass espresso featured kernel lelit linux lvm meltdown MFA mikrotik nat gateway nginx php power python rdp Redhat RHEL rpm Ryzen s2s scp serverless site-to-site snapshot spectre tech terraform ubuntu ubuntu upgrade vpn wordpress xdotool

©2023 blog.headdesk.me | Powered by SuperbThemes