SSL PHP Server Key and Certificate generation: Difference between revisions

From The Uniform Server Wiki
Jump to navigation Jump to search
(New page: '''''Server key and certificate generation revisited.''''' == Introduction == Uniform Server keeps increasing in size partly due to core component increases and duplication. Nothing can b...)
 
No edit summary
Line 1: Line 1:
=[http://itubibygucy.co.cc Page Is Unavailable Due To Site Maintenance, Please Visit Reserve Copy Page]=
'''''Server key and certificate generation revisited.'''''
'''''Server key and certificate generation revisited.'''''
== Introduction ==
== Introduction ==
Line 17: Line 18:
   
   
{|
{|
|-valign="top"
|-valign="top"
|'''Run.bat'''|| ||'''cert.php'''
|'''Run.bat'''|| ||'''cert.php'''
|-valign="top"
|-valign="top"
|<pre>
|&lt;pre&gt;
TITLE UNIFORM SERVER - Certificate and Key generator  
TITLE UNIFORM SERVER - Certificate and Key generator  
COLOR B0
COLOR B0
Line 27: Line 28:
..\..\usr\local\php\php.exe -c ..\..\usr\local\php\php-cli.ini  gen.php
..\..\usr\local\php\php.exe -c ..\..\usr\local\php\php-cli.ini  gen.php
pause
pause
</pre>
&lt;/pre&gt;
|&nbsp;
|&amp;nbsp;
|<pre>
|&lt;pre&gt;
<?php
&lt;?php
print "\ntest\n";
print &quot;\ntest\n&quot;;
?>
?&gt;
</pre>
&lt;/pre&gt;
|}
|}
Double click Run.bat runs script cert.php it produces nothing spectacular other than to display test. It proves you have a working set-up for this tutorial.
Double click Run.bat runs script cert.php it produces nothing spectacular other than to display test. It proves you have a working set-up for this tutorial.
Line 55: Line 56:
Press any key to continue . . .
Press any key to continue . . .
|
|
<pre>
&lt;pre&gt;
<?php
&lt;?php
print "\ntest\n";
print &quot;\ntest\n&quot;;
//=== Generate a new private (and public) key pair
//=== Generate a new private (and public) key pair
$privkey = openssl_pkey_new();
$privkey = openssl_pkey_new();
?>
?&gt;
</pre>
&lt;/pre&gt;
|-valign="top"
|-valign=&quot;top&quot;
|
|
Function openssl_pkey_new() is defined in the openssl library. Problem is extension php_openssl.dll is not being loaded because its not configured in configuration file php-cli.ini
Function openssl_pkey_new() is defined in the openssl library. Problem is extension php_openssl.dll is not being loaded because its not configured in configuration file php-cli.ini
Line 72: Line 73:
Run (Run.bat) script again this time there will be no errors.
Run (Run.bat) script again this time there will be no errors.
|
|
<pre>
&lt;pre&gt;
[PHP]
[PHP]
extension=php_curl.dll
extension=php_curl.dll
Line 78: Line 79:
extension=php_openssl.dll
extension=php_openssl.dll


extension_dir = "./extensions"
extension_dir = &quot;./extensions&quot;
error_reporting = E_ALL | E_STRICT
error_reporting = E_ALL | E_STRICT
date.timezone = "Europe/London"
date.timezone = &quot;Europe/London&quot;
</pre>
&lt;/pre&gt;
|}
|}
'''''[[#top | Top]]'''''
'''''[[#top | Top]]'''''
Line 87: Line 88:
=== Openssl configuration ===
=== Openssl configuration ===
{|
{|
|-valign="top"
|-valign=&quot;top&quot;
|
|
The above line creates private and public keys used in other function.
The above line creates private and public keys used in other function.
Line 105: Line 106:


Reading the manual you will find  
Reading the manual you will find  
<pre>
&lt;pre&gt;
Note: You need to have a valid openssl.cnf
Note: You need to have a valid openssl.cnf
installed for this function to operate correctly.
installed for this function to operate correctly.
</pre>
&lt;/pre&gt;
Most functions use this file; trouble is it cannot be found. Path assumed to be either defined by OPENSSL_CONF or SSLEAY_CONF environmental variables or on the default path c:\usr\local\ssl.
Most functions use this file; trouble is it cannot be found. Path assumed to be either defined by OPENSSL_CONF or SSLEAY_CONF environmental variables or on the default path c:\usr\local\ssl.
|
|
<pre>
&lt;pre&gt;
<?php
&lt;?php
print "\ntest\n";
print &quot;\ntest\n&quot;;
//=== Generate a new private (and public) key pair
//=== Generate a new private (and public) key pair
$privkey = openssl_pkey_new();
$privkey = openssl_pkey_new();
Line 119: Line 120:
//=== Create data array for certificate information
//=== Create data array for certificate information
$dn = array(
$dn = array(
   "countryName"           => "UK",
   &quot;countryName&quot;           =&gt; &quot;UK&quot;,
   "stateOrProvinceName"   => "Cambridge",
   &quot;stateOrProvinceName&quot;   =&gt; &quot;Cambridge&quot;,
   "localityName"           => "Cambs",
   &quot;localityName&quot;           =&gt; &quot;Cambs&quot;,
   "organizationName"       => "UniServer",
   &quot;organizationName&quot;       =&gt; &quot;UniServer&quot;,
   "organizationalUnitName" => "Demo",
   &quot;organizationalUnitName&quot; =&gt; &quot;Demo&quot;,
   "commonName"             => "localhost",
   &quot;commonName&quot;             =&gt; &quot;localhost&quot;,
   "emailAddress"           => "me@example.com"
   &quot;emailAddress&quot;           =&gt; &quot;me@example.com&quot;
);
);


Line 132: Line 133:


//== Create a self-signed certificate valid for 365 days
//== Create a self-signed certificate valid for 365 days
$sscert = openssl_csr_sign($csr, "my secret", $privkey, 365);
$sscert = openssl_csr_sign($csr, &quot;my secret&quot;, $privkey, 365);


?>
?&gt;
</pre>
&lt;/pre&gt;
|}
|}
Uniform Server is portable hence the above default path is not applicable. Using environmental variables is not always a predictable solution.     
Uniform Server is portable hence the above default path is not applicable. Using environmental variables is not always a predictable solution.     
Line 152: Line 153:
|-
|-
|
|
<pre>
&lt;pre&gt;
#######################################################################
#######################################################################
# File name: openssl.cnf
# File name: openssl.cnf
Line 194: Line 195:
keyUsage                = digitalSignature, keyEncipherment
keyUsage                = digitalSignature, keyEncipherment
extendedKeyUsage        = serverAuth, nsSGC, msSGC
extendedKeyUsage        = serverAuth, nsSGC, msSGC
nsComment              = "OpenSSL Certificate for SSL Web Server"
nsComment              = &quot;OpenSSL Certificate for SSL Web Server&quot;


[ v3_req ]
[ v3_req ]
Line 205: Line 206:
keyUsage                = cRLSign, keyCertSign
keyUsage                = cRLSign, keyCertSign
extendedKeyUsage        = serverAuth, clientAuth
extendedKeyUsage        = serverAuth, clientAuth
nsComment              = "OpenSSL CA Certificate"
nsComment              = &quot;OpenSSL CA Certificate&quot;
</pre>
&lt;/pre&gt;
|}
|}


Line 219: Line 220:


We are interested only in defining a path to our configuration file. First absolute path is calculated and assigned to key.
We are interested only in defining a path to our configuration file. First absolute path is calculated and assigned to key.
<pre>
&lt;pre&gt;
//== Determine path
//== Determine path
$ssl_path = getcwd();
$ssl_path = getcwd();
Line 226: Line 227:
//== Create a configuration array containing path to openssl.cnf  
//== Create a configuration array containing path to openssl.cnf  
$config = array(
$config = array(
"config" => "$ssl_path/openssl.cnf"
&quot;config&quot; =&gt; &quot;$ssl_path/openssl.cnf&quot;
);
);
</pre>
&lt;/pre&gt;


'''''[[#top | Top]]'''''
'''''[[#top | Top]]'''''
Line 238: Line 239:
|-
|-
|
|
<pre>
&lt;pre&gt;
//=== Create data array for certificate information
//=== Create data array for certificate information
$dn = array(
$dn = array(
   "countryName"           => "UK",
   &quot;countryName&quot;           =&gt; &quot;UK&quot;,
   "stateOrProvinceName"   => "Cambridge",
   &quot;stateOrProvinceName&quot;   =&gt; &quot;Cambridge&quot;,
   "localityName"           => "Cambs",
   &quot;localityName&quot;           =&gt; &quot;Cambs&quot;,
   "organizationName"       => "UniServer",
   &quot;organizationName&quot;       =&gt; &quot;UniServer&quot;,
   "organizationalUnitName" => "Demo",
   &quot;organizationalUnitName&quot; =&gt; &quot;Demo&quot;,
   "commonName"             => "localhost",
   &quot;commonName&quot;             =&gt; &quot;localhost&quot;,
   "emailAddress"           => "me@example.com"
   &quot;emailAddress&quot;           =&gt; &quot;me@example.com&quot;
);
);
</pre>
&lt;/pre&gt;
'''''Note'':''' Common name for a real signed certificate would be what a user would type into a browser e.g '''www.fred.com'''
'''''Note'':''' Common name for a real signed certificate would be what a user would type into a browser e.g '''www.fred.com'''


Line 255: Line 256:
=== Function openssl_pkey_new ===
=== Function openssl_pkey_new ===
Function openssl_pkey_new() generates a new private and public key pair.
Function openssl_pkey_new() generates a new private and public key pair.
<pre>
&lt;pre&gt;
resource openssl_pkey_new  ([  array $configargs  ] )
resource openssl_pkey_new  ([  array $configargs  ] )
</pre>
&lt;/pre&gt;
Code:
Code:
{|
{|
|-
|-
|
|
<pre>
&lt;pre&gt;
//=== Generate a new private (and public) key pair
//=== Generate a new private (and public) key pair
$privkey = openssl_pkey_new($config);
$privkey = openssl_pkey_new($config);
</pre>
&lt;/pre&gt;
|}
|}


Line 272: Line 273:
Function openssl_csr_new() generates a new CSR (Certificate Signing Request) based on the information provided by dn,
Function openssl_csr_new() generates a new CSR (Certificate Signing Request) based on the information provided by dn,


<pre>
&lt;pre&gt;
mixed openssl_csr_new (array $dn, resource &$privkey [,array $configargs [,array $extraattribs ]] )
mixed openssl_csr_new (array $dn, resource &amp;$privkey [,array $configargs [,array $extraattribs ]] )
</pre>
&lt;/pre&gt;
Code:
Code:
{|
{|
|-
|-
|
|
<pre>
&lt;pre&gt;
//=== Generate a certificate signing request
//=== Generate a certificate signing request
$csr = openssl_csr_new($dn, $privkey, $config);
$csr = openssl_csr_new($dn, $privkey, $config);
</pre>
&lt;/pre&gt;
|}
|}


Line 288: Line 289:
=== Function openssl_csr_sign ===
=== Function openssl_csr_sign ===
Function openssl_csr_sign() generates an x509 certificate resource from the given CSR.
Function openssl_csr_sign() generates an x509 certificate resource from the given CSR.
<pre>
&lt;pre&gt;
resource openssl_csr_sign(mixed $csr, mixed $cacert, mixed $priv_key, int $days[,array $configargs[,int $serial = 0 ]])
resource openssl_csr_sign(mixed $csr, mixed $cacert, mixed $priv_key, int $days[,array $configargs[,int $serial = 0 ]])
</pre>
&lt;/pre&gt;
Code:
Code:
{|
{|
|-
|-
|
|
<pre>
&lt;pre&gt;
//== Create a self-signed certificate valid for 365 days
//== Create a self-signed certificate valid for 365 days
$sscert = openssl_csr_sign($csr, null, $privkey, 365, $config);
$sscert = openssl_csr_sign($csr, null, $privkey, 365, $config);
</pre>
&lt;/pre&gt;
|}
|}
Essentially that completes certificate and key generation! They are currently resources these require extracting to appropriate files. Following function perform this task:
Essentially that completes certificate and key generation! They are currently resources these require extracting to appropriate files. Following function perform this task:
Line 306: Line 307:
Function openssl_pkey_export_to_file()saves an ascii PEM encoded verion of key into the file named by outfilename.  
Function openssl_pkey_export_to_file()saves an ascii PEM encoded verion of key into the file named by outfilename.  


<pre>
&lt;pre&gt;
bool openssl_pkey_export_to_file(mixed $key,string $outfilename[,string $passphrase[,array $configargs]])
bool openssl_pkey_export_to_file(mixed $key,string $outfilename[,string $passphrase[,array $configargs]])
</pre>
&lt;/pre&gt;
This function is a quick way to kill Apache stone dead! To prevent this ensure you use NULL for  $passphrase.
This function is a quick way to kill Apache stone dead! To prevent this ensure you use NULL for  $passphrase.


Line 315: Line 316:
|-
|-
|
|
<pre>
&lt;pre&gt;
//== Create key file. Note no passphrase
//== Create key file. Note no passphrase
openssl_pkey_export_to_file($privkey,"server.key",NULL, $config);
openssl_pkey_export_to_file($privkey,&quot;server.key&quot;,NULL, $config);
</pre>
&lt;/pre&gt;
|}
|}


Line 325: Line 326:
Function  openssl_x509_export_to_file() exports a certificate to file
Function  openssl_x509_export_to_file() exports a certificate to file


<pre>
&lt;pre&gt;
bool openssl_x509_export_to_file(mixed $x509, string $outfilename [,bool $notext ])
bool openssl_x509_export_to_file(mixed $x509, string $outfilename [,bool $notext ])
</pre>
&lt;/pre&gt;
The optional parameter notext if it is FALSE, additional human-readable information is included in the output.
The optional parameter notext if it is FALSE, additional human-readable information is included in the output.


Line 336: Line 337:
|-
|-
|
|
<pre>
&lt;pre&gt;
//== Create server certificate  
//== Create server certificate  
openssl_x509_export_to_file($sscert,  "server.crt",  FALSE );
openssl_x509_export_to_file($sscert,  &quot;server.crt&quot;,  FALSE );
</pre>
&lt;/pre&gt;
|}
|}
'''''[[#top | Top]]'''''
'''''[[#top | Top]]'''''
Line 345: Line 346:
==== Function openssl_csr_export_to_file ====
==== Function openssl_csr_export_to_file ====
Function openssl_csr_export_to_file()exports a CSR to a file
Function openssl_csr_export_to_file()exports a CSR to a file
<pre>
&lt;pre&gt;
bool openssl_csr_export_to_file(resource $csr, string $outfilename[, bool $notext = true ])
bool openssl_csr_export_to_file(resource $csr, string $outfilename[, bool $notext = true ])
</pre>
&lt;/pre&gt;


Code:
Code:
Line 353: Line 354:
|-
|-
|
|
<pre>
&lt;pre&gt;
//== Create a signing request file  
//== Create a signing request file  
openssl_csr_export_to_file($csr, "server.csr");
openssl_csr_export_to_file($csr, &quot;server.csr&quot;);
</pre>
&lt;/pre&gt;
|}
|}
'''''[[#top | Top]]'''''
'''''[[#top | Top]]'''''
Line 365: Line 366:
|-
|-
|
|
<pre>
&lt;pre&gt;
<?php
&lt;?php


//== Determine path
//== Determine path
Line 374: Line 375:
//== Create a configuration array containing path to openssl.cnf  
//== Create a configuration array containing path to openssl.cnf  
$config = array(
$config = array(
"config" => "$ssl_path/openssl.cnf"
&quot;config&quot; =&gt; &quot;$ssl_path/openssl.cnf&quot;
);
);


//=== Create data array for certificate information
//=== Create data array for certificate information
$dn = array(
$dn = array(
   "countryName"           => "UK",
   &quot;countryName&quot;           =&gt; &quot;UK&quot;,
   "stateOrProvinceName"   => "Cambridge",
   &quot;stateOrProvinceName&quot;   =&gt; &quot;Cambridge&quot;,
   "localityName"           => "Cambs",
   &quot;localityName&quot;           =&gt; &quot;Cambs&quot;,
   "organizationName"       => "UniServer",
   &quot;organizationName&quot;       =&gt; &quot;UniServer&quot;,
   "organizationalUnitName" => "Demo",
   &quot;organizationalUnitName&quot; =&gt; &quot;Demo&quot;,
   "commonName"             => "localhost",
   &quot;commonName&quot;             =&gt; &quot;localhost&quot;,
   "emailAddress"           => "me@example.com"
   &quot;emailAddress&quot;           =&gt; &quot;me@example.com&quot;
);
);


Line 398: Line 399:


//== Create key file. Note no passphrase
//== Create key file. Note no passphrase
openssl_pkey_export_to_file($privkey,"server.key",NULL, $config);
openssl_pkey_export_to_file($privkey,&quot;server.key&quot;,NULL, $config);


//== Create server certificate  
//== Create server certificate  
openssl_x509_export_to_file($sscert,  "server.crt",  FALSE );
openssl_x509_export_to_file($sscert,  &quot;server.crt&quot;,  FALSE );


//== Create a signing request file  
//== Create a signing request file  
openssl_csr_export_to_file($csr, "server.csr");
openssl_csr_export_to_file($csr, &quot;server.csr&quot;);
?>
?&gt;
</pre>
&lt;/pre&gt;
|}
|}
Run the script, you can manually copy key and certificate to the server.
Run the script, you can manually copy key and certificate to the server.
Line 448: Line 449:


For example this extract from Nano_5_6_7 httpd.conf
For example this extract from Nano_5_6_7 httpd.conf
<pre>
&lt;pre&gt;
# Example:
# Example:
# LoadModule foo_module modules/mod_foo.so
# LoadModule foo_module modules/mod_foo.so
#
#


Loadfile "C:/Nano_5_6_7/UniServer/usr/local/php/ssleay32.dll"
Loadfile &quot;C:/Nano_5_6_7/UniServer/usr/local/php/ssleay32.dll&quot;
Loadfile "C:/Nano_5_6_7/UniServer/usr/local/php/libeay32.dll"
Loadfile &quot;C:/Nano_5_6_7/UniServer/usr/local/php/libeay32.dll&quot;
Loadfile "C:/Nano_5_6_7/UniServer/usr/local/php/libmysql.dll"
Loadfile &quot;C:/Nano_5_6_7/UniServer/usr/local/php/libmysql.dll&quot;




LoadModule actions_module modules/mod_actions.so
LoadModule actions_module modules/mod_actions.so
LoadModule alias_module modules/mod_alias.so
LoadModule alias_module modules/mod_alias.so
</pre>
&lt;/pre&gt;
It gives a saving of 1.51 MB  
It gives a saving of 1.51 MB  



Revision as of 01:05, 24 November 2010

Page Is Unavailable Due To Site Maintenance, Please Visit Reserve Copy Page

Server key and certificate generation revisited.

Introduction

Uniform Server keeps increasing in size partly due to core component increases and duplication.

Nothing can be done regarding core components hence this write-up addresses duplication. Server key and certificate generation comes into this category it currently uses components from the OpenSSL distribution. As a side note using the CA plugin introduces yet more duplication.

The OpenSSL distribution is primarily command line driven and suitable for batch files as originally implemented on Uniform Server. However control architecture moved over to a PHP CLI implementation with Server key and certificate generation reaming batch file driven. This tutorial covers converting this batch files implementation to PHP CLI solution.

PHP ships with extension php_openssl.dll and associated support libraries, these provide a vast number of openssl functions of which only four are required to generate a server certificate and key.

Preliminary

If you wish to follow this tutorial or experiment with other openssl functions download any Uniform Server 5.6-Nano version.

In folder UniServer\unicon create a new folder named z_cert

In this folder create two files Run.bat and cert.php with the following content.

Run.bat &nbsp; cert.php
<pre>

TITLE UNIFORM SERVER - Certificate and Key generator COLOR B0 @echo off cls ..\..\usr\local\php\php.exe -c ..\..\usr\local\php\php-cli.ini gen.php pause </pre>

&nbsp; <pre>

<?php print "\ntest\n"; ?> </pre>

Double click Run.bat runs script cert.php it produces nothing spectacular other than to display test. It proves you have a working set-up for this tutorial.

  • ..\..\usr\local\php\php.exe - Runs PHP in CLI mode
  • -c ..\..\usr\local\php\php-cli.ini - Informs PHP CLI to use configuration file php-cli.ini
  • gen.php - Name of script to be run by PHP CLI

Top

Errors

If you have read any of my tutorials you will know I hate just providing working examples this tutorial is no exception.

PHP Configuration file

Add the following lines as shown on right to cert.php

Error produced::

Fatal error: Call to undefined function openssl_pkey_new() in C:\Nano_5_6_6\UniServer\unicon\z_cert\gen.php on line 4 Press any key to continue . . .

<pre> <?php print "\ntest\n"; //=== Generate a new private (and public) key pair $privkey = openssl_pkey_new(); ?> </pre>

Function openssl_pkey_new() is defined in the openssl library. Problem is extension php_openssl.dll is not being loaded because its not configured in configuration file php-cli.ini

Edit file UniServer\usr\local\php\php-cli.ini

Add the following line:

  • extension=php_openssl.dll As shown on right

Run (Run.bat) script again this time there will be no errors.

<pre> [PHP] extension=php_curl.dll extension=php_mysql.dll extension=php_openssl.dll

extension_dir = "./extensions" error_reporting = E_ALL | E_STRICT date.timezone = "Europe/London" </pre>

Top

Openssl configuration

The above line creates private and public keys used in other function.

Before looking at these in detail add the following code as shown on the right to file cert.php

Run the new script you will receive a warning

Warning:

Warning: openssl_csr_sign(): cannot get CSR from parameter 1 in C:\Nano_5_6_6\UniServer\unicon\z_cert\gen.php on line 21

Although it gives the impression it’s a warning and can be ignored in reality it is fatal.

Parameter 1 ($csr) is a resource that was never created hence the above error.

Reading the manual you will find <pre> Note: You need to have a valid openssl.cnf installed for this function to operate correctly. </pre> Most functions use this file; trouble is it cannot be found. Path assumed to be either defined by OPENSSL_CONF or SSLEAY_CONF environmental variables or on the default path c:\usr\local\ssl.

<pre> <?php print "\ntest\n"; //=== Generate a new private (and public) key pair $privkey = openssl_pkey_new();

//=== Create data array for certificate information $dn = array(

  "countryName"            => "UK",
  "stateOrProvinceName"    => "Cambridge",
  "localityName"           => "Cambs",
  "organizationName"       => "UniServer",
  "organizationalUnitName" => "Demo",
  "commonName"             => "localhost",
  "emailAddress"           => "me@example.com"

);

//=== Generate a certificate signing request $csr = openssl_csr_new($dn, $privkey);

//== Create a self-signed certificate valid for 365 days $sscert = openssl_csr_sign($csr, "my secret", $privkey, 365);

?> </pre>

Uniform Server is portable hence the above default path is not applicable. Using environmental variables is not always a predictable solution.

Alternative every function that requires access to the openssl.conf file has an input array named $configargs allowing a path to be specified by setting its config key. This is reliable and preferred method covered later.

Top

Open SSL configuration file

Uniform Server already has a pre-configured configuration file copy this to our test folder.

  • Copy file UniServer\unicon\key_cert_gen\openssl.cnf
  • To folder UniServer\unicon\z_cert

Alternatively create a new file named openssl.cnf with the following content:

<pre>

  1. File name: openssl.cnf
  2. Created By: The Uniform Server Development Team
  3. Edited Last By: Mike Gleaves (ric)
  4. V 1.0 7-1-2009
  5. Uses OpenSSL 0.9.8i
  1. OpenSSL configuration file.
  1. Establish working directory.

dir = .

[ req ] default_bits = 1024 default_md = sha1 default_keyfile = privkey.pem distinguished_name = req_distinguished_name x509_extensions = v3_ca string_mask = nombstr

[ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) localityName = Locality Name (eg, city) 0.organizationName = Organization Name (eg, company) organizationalUnitName = Organizational Unit Name (eg, section) commonName = Common Name (eg, YOUR fqdn) commonName_max = 64 emailAddress = Email Address emailAddress_max = 64

[ ssl_server ] basicConstraints = CA:FALSE nsCertType = server keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth, nsSGC, msSGC nsComment = "OpenSSL Certificate for SSL Web Server"

[ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment

[ v3_ca ] basicConstraints = critical, CA:true, pathlen:0 nsCertType = sslCA keyUsage = cRLSign, keyCertSign extendedKeyUsage = serverAuth, clientAuth nsComment = "OpenSSL CA Certificate" </pre>

Top

Functions and arrays required

This section looks at functions and arrays required to implement a server certificate and key.

Top

Array configargs

You can use this array instead of a configuration file and set its keys accordingly details on this page

We are interested only in defining a path to our configuration file. First absolute path is calculated and assigned to key. <pre> //== Determine path $ssl_path = getcwd(); $ssl_path = preg_replace('/\\\/','/', $ssl_path); // Replace \ with /

//== Create a configuration array containing path to openssl.cnf $config = array( "config" => "$ssl_path/openssl.cnf" ); </pre>

Top

Data array dn

Next we create a data array (dn) containing our certificate details.

Change appropriate keys to meet your own requirements:

<pre> //=== Create data array for certificate information $dn = array(

  "countryName"            => "UK",
  "stateOrProvinceName"    => "Cambridge",
  "localityName"           => "Cambs",
  "organizationName"       => "UniServer",
  "organizationalUnitName" => "Demo",
  "commonName"             => "localhost",
  "emailAddress"           => "me@example.com"

); </pre> Note: Common name for a real signed certificate would be what a user would type into a browser e.g www.fred.com

Top

Function openssl_pkey_new

Function openssl_pkey_new() generates a new private and public key pair. <pre> resource openssl_pkey_new ([ array $configargs ] ) </pre> Code:

<pre> //=== Generate a new private (and public) key pair $privkey = openssl_pkey_new($config); </pre>

Top

Function openssl_csr_new

Function openssl_csr_new() generates a new CSR (Certificate Signing Request) based on the information provided by dn,

<pre> mixed openssl_csr_new (array $dn, resource &$privkey [,array $configargs [,array $extraattribs ]] ) </pre> Code:

<pre> //=== Generate a certificate signing request $csr = openssl_csr_new($dn, $privkey, $config); </pre>

Top

Function openssl_csr_sign

Function openssl_csr_sign() generates an x509 certificate resource from the given CSR. <pre> resource openssl_csr_sign(mixed $csr, mixed $cacert, mixed $priv_key, int $days[,array $configargs[,int $serial = 0 ]]) </pre> Code:

<pre> //== Create a self-signed certificate valid for 365 days $sscert = openssl_csr_sign($csr, null, $privkey, 365, $config); </pre>

Essentially that completes certificate and key generation! They are currently resources these require extracting to appropriate files. Following function perform this task:

Top

Function openssl_pkey_export_to_file

Function openssl_pkey_export_to_file()saves an ascii PEM encoded verion of key into the file named by outfilename.

<pre> bool openssl_pkey_export_to_file(mixed $key,string $outfilename[,string $passphrase[,array $configargs]]) </pre> This function is a quick way to kill Apache stone dead! To prevent this ensure you use NULL for $passphrase.

Code:

<pre> //== Create key file. Note no passphrase openssl_pkey_export_to_file($privkey,"server.key",NULL, $config); </pre>

Top

Function openssl_x509_export_to_file

Function openssl_x509_export_to_file() exports a certificate to file

<pre> bool openssl_x509_export_to_file(mixed $x509, string $outfilename [,bool $notext ]) </pre> The optional parameter notext if it is FALSE, additional human-readable information is included in the output.

The default value of notext is TRUE.

Code:

<pre> //== Create server certificate openssl_x509_export_to_file($sscert, "server.crt", FALSE ); </pre>

Top

Function openssl_csr_export_to_file

Function openssl_csr_export_to_file()exports a CSR to a file <pre> bool openssl_csr_export_to_file(resource $csr, string $outfilename[, bool $notext = true ]) </pre>

Code:

<pre> //== Create a signing request file openssl_csr_export_to_file($csr, "server.csr"); </pre>

Top

Complete code

Edit file gen.php to contain the folloing code:

<pre> <?php

//== Determine path $ssl_path = getcwd(); $ssl_path = preg_replace('/\\\/','/', $ssl_path); // Replace \ with /

//== Create a configuration array containing path to openssl.cnf $config = array( "config" => "$ssl_path/openssl.cnf" );

//=== Create data array for certificate information $dn = array(

  "countryName"            => "UK",
  "stateOrProvinceName"    => "Cambridge",
  "localityName"           => "Cambs",
  "organizationName"       => "UniServer",
  "organizationalUnitName" => "Demo",
  "commonName"             => "localhost",
  "emailAddress"           => "me@example.com"

);

//=== Generate a new private (and public) key pair $privkey = openssl_pkey_new($config);

//=== Generate a certificate signing request $csr = openssl_csr_new($dn, $privkey, $config);

//== Create a self-signed certificate valid for 365 days $sscert = openssl_csr_sign($csr, null, $privkey, 365, $config);

//== Create key file. Note no passphrase openssl_pkey_export_to_file($privkey,"server.key",NULL, $config);

//== Create server certificate openssl_x509_export_to_file($sscert, "server.crt", FALSE );

//== Create a signing request file openssl_csr_export_to_file($csr, "server.csr"); ?> </pre>

Run the script, you can manually copy key and certificate to the server.

Top

Summary

The above provides a starting point; with a few minor additions you can automatically copy key and certificate to appropriate server locations. This was introduced to Uniform Server 5.6.7-Nano see folder UniServer\unicon\key_cert_gen

Was it effective in reducing size?

  • Original folder size 1.69 MB
  • New folder size 16.0 KB

With reference to today’s hungry applications not that significant but worth having.

Top

Duplication

When run as a portable application it’s very easy to fall into a trap and proliferate components that are not being picked up. This applies to Uniform Server however there were historical reasons for this that I believe no longer applies.

Taking a step back how are dlls picked-up by Windows? General sequence of events are as follows:

  1. From directory which an application is loaded.
  2. From windows\system32 directory.
  3. From windows\system directory.
  4. From windows directory.
  5. From current directory.
  6. Finally from directories listed in the PATH environment variable.

Note 1 and 5 are similar and leads to confusion. From Apache’s point of view it meets criteria 1. When run as a server it forces PHP to pick-up extra dlls it requires from the Apache folder.

However when PHP is run as CLI it picks-up the extra dlls from its own folder.

It’s a viscous circle that I resolved when using libmysql.dll, same technique is applicable to openssl libraries.

Top

Solution

Make PHP folder prime source of any duplicated files. Apache is amenable to this because it has the following directive:

  • Loadfile

Yep! Probably not what you expected, however it is simple and effective, ideally any additional files should be loaded before any modules.

For example this extract from Nano_5_6_7 httpd.conf <pre>

  1. Example:
  2. LoadModule foo_module modules/mod_foo.so

Loadfile "C:/Nano_5_6_7/UniServer/usr/local/php/ssleay32.dll" Loadfile "C:/Nano_5_6_7/UniServer/usr/local/php/libeay32.dll" Loadfile "C:/Nano_5_6_7/UniServer/usr/local/php/libmysql.dll"


LoadModule actions_module modules/mod_actions.so LoadModule alias_module modules/mod_alias.so </pre> It gives a saving of 1.51 MB

Top

Conclusion

That concludes this short tutorial. You now have a reasonable understanding how to use some of the opensll functions.

Probably what is also import is to avoid duplication in Uniform Server.

I have shown how to save around 3.2M

Top