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