certificationauthority : Add alternative names

git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@5109 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
2019-03-15 08:43:07 +00:00
parent 4ec1ca1440
commit 2ea8f73868
2 changed files with 76 additions and 22 deletions

View File

@@ -123,4 +123,24 @@ class test_certificationauthority extends PHPUnit_Framework_TestCase
unlink ("/tmp/test_signCSR_5");
$this->assertSame ($res, 1);
}
public function test_signCSR_6 ()
{
// Check if generated cert has Alternative Names
$certificationauthority = new certificationauthority ();
$certificationauthority->createCA ("FR", "FOURNIER38", "CATEST");
$caCert = $certificationauthority->caCert ();
$caKey = $certificationauthority->caKey ();
$csr = $certificationauthority->createCSR ("FR", "FOURNIER38",
"CSR.fournier38.fr");
$cert = $certificationauthority->signCSR ($csr, $caCert, $caKey, null,
["ALT1.example.com","ALT2.example.com"]);
file_put_contents ("/tmp/test_signCSR_6", $cert);
exec ("openssl x509 -in - -text -noout < /tmp/test_signCSR_6", $output);
$res = preg_match ("#DNS:CSR.fournier38.fr, DNS:ALT1.example.com, DNS:ALT#",
implode ("\n", $output));
print_r ($output);
unlink ("/tmp/test_signCSR_6");
$this->assertSame ($res, 1);
}
}

View File

@@ -9,6 +9,7 @@
class certificationauthority
{
// PROPERTIES
// {{{
/** The opensslCnfPath file
*/
private $opensslCnfPath;
@@ -28,16 +29,9 @@ class certificationauthority
*/
private $configargs = array ();
/** Check if /usr/bin/openssl is available */
public function __construct ()
// {{{
{
if (! function_exists ("openssl_csr_new"))
throw new \Exception (_("No openssl support in PHP"),
500);
$this->opensslCnfPath = tempnam ("/tmp", "openssl-");
file_put_contents ($this->opensslCnfPath,
'HOME = .
/** The basic openssl.cnf configuration
*/
private $opensslConf = 'HOME = .
RANDFILE = $ENV::HOME/.rnd
[ req ]
@@ -45,17 +39,29 @@ distinguished_name = req_distinguished_name
[ req_distinguished_name ]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true
keyUsage = cRLSign, keyCertSign
');
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
';
// }}}
/** Check if openssl support is available in PHP
*/
public function __construct ()
// {{{
{
if (! function_exists ("openssl_csr_new"))
throw new \Exception (_("No openssl support in PHP"),
500);
$this->opensslCnfPath = tempnam ("/tmp", "openssl-");
file_put_contents ($this->opensslCnfPath, $this->opensslConf);
$this->configargs = array (
"config" => $this->opensslCnfPath,
"digest_alg" => "sha256WithRSAEncryption",
@@ -64,6 +70,8 @@ keyUsage = cRLSign, keyCertSign
}
// }}}
/** Remove the temporary files when destroying the object
*/
public function __destruct ()
// {{{
{
@@ -99,6 +107,9 @@ keyUsage = cRLSign, keyCertSign
$req_csr = openssl_csr_new ($dn, $req_key, $this->configargs);
$req_cert = openssl_csr_sign ($req_csr, NULL, $req_key, $days,
$this->configargs);
if ($req_cert === false)
throw new \Exception ("Can not create CA certificate : " .
openssl_error_string (), 500);
openssl_x509_export ($req_cert, $this->caCert);
openssl_pkey_export ($req_key, $this->caKey);
return $this;
@@ -106,7 +117,7 @@ keyUsage = cRLSign, keyCertSign
// }}}
/** Get/Set the ca cert
* @param string|null The CA cert to get/set
* @param string|null $caCert The CA cert to get/set
* @return the CA if get in PEM, $this if set
*/
public function caCert ($caCert = null)
@@ -122,7 +133,7 @@ keyUsage = cRLSign, keyCertSign
// }}}
/** Get/Set the ca key
* @param string|null The CA key to get/set
* @param string|null $caKey The CA key to get/set
* @return the CA if get, $this if set
*/
public function caKey ($caKey = null)
@@ -153,7 +164,7 @@ keyUsage = cRLSign, keyCertSign
// }}}
/** Get in PEM/Set the private key
* @param string|null The private key to use
* @param string|null $privateKey The private key to use
* @return the privatekey if get in PEM, $this if set
*/
public function privateKey ($privateKey = null)
@@ -191,24 +202,46 @@ keyUsage = cRLSign, keyCertSign
$this->configargs["x509_extensions"] = "v3_req";
$req_csr = openssl_csr_new ($dn, $this->privateKey, $this->configargs);
if ($req_csr === false)
throw new \Exception ("CA : Can not generate a CSR", 500);
throw new \Exception ("CA : Can not generate a CSR : ".
openssl_error_string (), 500);
openssl_csr_export ($req_csr, $out);
return $out;
}
// }}}
/** Sign a CSR with an CA cert and key and return the signed certificate in
/** Sign a CSR with an CA cert/key pair and return the signed certificate in
* PEM mode
* The caCert and caKey must be defined
* @param string $csr The CSR to sign
* @param string $caCert The CA Certificate
* @param string $caKey The CA private key
* @param integer|null $days The number of days of validity (365 by default)
* @param array|null $altNames The alternative names allowed in cert
* @return the signed certificate in PEM
*/
public function signCSR ($csr, $caCert, $caKey, $days = 365)
public function signCSR ($csr, $caCert, $caKey, $days = 365,
$altNames = array ())
// {{{
{
$conf = $this->opensslConf;
if (! empty($altNames))
{
// Copy the commonName from CSR request into subjectAltName
$subject = openssl_csr_get_subject($csr);
if (key_exists ("CN", $subject))
$commonName = $subject["CN"];
else
throw new \Exception ("Can not get the CN from CSR", 500);
// Add all the alternateNames
$conf .=
"subjectAltName = @san\n\n[ san ]\n";
$conf .= "DNS.0 = $commonName\n";
foreach ($altNames as $nb => $name)
{
$conf .= "DNS.".($nb+1)." = $name\n";
}
file_put_contents ($this->opensslCnfPath, $conf);
}
$this->configargs["x509_extensions"] = "v3_req";
$usercert = openssl_csr_sign ($csr, $caCert, $caKey, $days,
$this->configargs, date ("YmdHis"));
@@ -216,6 +249,7 @@ keyUsage = cRLSign, keyCertSign
throw new \Exception ("Can not create certificate : " .
openssl_error_string (), 500);
openssl_x509_export($usercert, $certout);
file_put_contents ($this->opensslCnfPath, $this->opensslConf);
return $certout;
}
// }}}