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"); unlink ("/tmp/test_signCSR_5");
$this->assertSame ($res, 1); $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 class certificationauthority
{ {
// PROPERTIES // PROPERTIES
// {{{
/** The opensslCnfPath file /** The opensslCnfPath file
*/ */
private $opensslCnfPath; private $opensslCnfPath;
@@ -28,16 +29,9 @@ class certificationauthority
*/ */
private $configargs = array (); private $configargs = array ();
/** Check if /usr/bin/openssl is available */ /** The basic openssl.cnf configuration
public function __construct () */
// {{{ private $opensslConf = 'HOME = .
{
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 = .
RANDFILE = $ENV::HOME/.rnd RANDFILE = $ENV::HOME/.rnd
[ req ] [ req ]
@@ -45,17 +39,29 @@ distinguished_name = req_distinguished_name
[ req_distinguished_name ] [ req_distinguished_name ]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
[ v3_ca ] [ v3_ca ]
subjectKeyIdentifier=hash subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true basicConstraints = critical,CA:true
keyUsage = cRLSign, keyCertSign 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 ( $this->configargs = array (
"config" => $this->opensslCnfPath, "config" => $this->opensslCnfPath,
"digest_alg" => "sha256WithRSAEncryption", "digest_alg" => "sha256WithRSAEncryption",
@@ -64,6 +70,8 @@ keyUsage = cRLSign, keyCertSign
} }
// }}} // }}}
/** Remove the temporary files when destroying the object
*/
public function __destruct () public function __destruct ()
// {{{ // {{{
{ {
@@ -99,6 +107,9 @@ keyUsage = cRLSign, keyCertSign
$req_csr = openssl_csr_new ($dn, $req_key, $this->configargs); $req_csr = openssl_csr_new ($dn, $req_key, $this->configargs);
$req_cert = openssl_csr_sign ($req_csr, NULL, $req_key, $days, $req_cert = openssl_csr_sign ($req_csr, NULL, $req_key, $days,
$this->configargs); $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_x509_export ($req_cert, $this->caCert);
openssl_pkey_export ($req_key, $this->caKey); openssl_pkey_export ($req_key, $this->caKey);
return $this; return $this;
@@ -106,7 +117,7 @@ keyUsage = cRLSign, keyCertSign
// }}} // }}}
/** Get/Set the ca cert /** 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 * @return the CA if get in PEM, $this if set
*/ */
public function caCert ($caCert = null) public function caCert ($caCert = null)
@@ -122,7 +133,7 @@ keyUsage = cRLSign, keyCertSign
// }}} // }}}
/** Get/Set the ca key /** 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 * @return the CA if get, $this if set
*/ */
public function caKey ($caKey = null) public function caKey ($caKey = null)
@@ -153,7 +164,7 @@ keyUsage = cRLSign, keyCertSign
// }}} // }}}
/** Get in PEM/Set the private key /** 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 * @return the privatekey if get in PEM, $this if set
*/ */
public function privateKey ($privateKey = null) public function privateKey ($privateKey = null)
@@ -191,24 +202,46 @@ keyUsage = cRLSign, keyCertSign
$this->configargs["x509_extensions"] = "v3_req"; $this->configargs["x509_extensions"] = "v3_req";
$req_csr = openssl_csr_new ($dn, $this->privateKey, $this->configargs); $req_csr = openssl_csr_new ($dn, $this->privateKey, $this->configargs);
if ($req_csr === false) 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); openssl_csr_export ($req_csr, $out);
return $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 * PEM mode
* The caCert and caKey must be defined * The caCert and caKey must be defined
* @param string $csr The CSR to sign * @param string $csr The CSR to sign
* @param string $caCert The CA Certificate * @param string $caCert The CA Certificate
* @param string $caKey The CA private key * @param string $caKey The CA private key
* @param integer|null $days The number of days of validity (365 by default) * @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 * @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"; $this->configargs["x509_extensions"] = "v3_req";
$usercert = openssl_csr_sign ($csr, $caCert, $caKey, $days, $usercert = openssl_csr_sign ($csr, $caCert, $caKey, $days,
$this->configargs, date ("YmdHis")); $this->configargs, date ("YmdHis"));
@@ -216,6 +249,7 @@ keyUsage = cRLSign, keyCertSign
throw new \Exception ("Can not create certificate : " . throw new \Exception ("Can not create certificate : " .
openssl_error_string (), 500); openssl_error_string (), 500);
openssl_x509_export($usercert, $certout); openssl_x509_export($usercert, $certout);
file_put_contents ($this->opensslCnfPath, $this->opensslConf);
return $certout; return $certout;
} }
// }}} // }}}