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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
// }}}
|
||||
|
||||
Reference in New Issue
Block a user