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.

facebookShare on Facebook
TwitterTweet

Leave a Reply Cancel reply

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

Full text search

Recent Posts

  • Terraform and segregated permissions
  • LVM Compression and Deduplication
  • Edit gpg encrypted file with vim
  • Lelit Elizabeth PL92T Pressure Tuning
  • jq transformation
  • aws (8)
  • coffee (1)
  • headfi (1)
  • linux (6)
  • others (58)
  • security (2)
  • tech (36)
  • wordpress (2)

apache aws awscli azure backup clearlinux cloud coffee docker DOCP ec2 EL8 epyc espresso featured gpg jenkins kernel lelit linux lvm meltdown memory MFA mikrotik php python rdp Redhat RHEL roasting rpm Ryzen site-to-site snapshot spectre tech terraform tuning ubuntu ubuntu upgrade vim vpn wordpress xdotool

©2023 blog.headdesk.me | Powered by SuperbThemes & WordPress