Difference between revisions of "SSL PHP Server Key and Certificate generation"

From The Uniform Server Wiki
Jump to navigation Jump to search
m (Reverted edits by Upazixorys (Talk); changed back to last version by Ric)
 
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 18: Line 17:
   
   
{|
{|
|-valign="top"
|-valign="top"
|'''Run.bat'''|| ||'''cert.php'''
|'''Run.bat'''|| ||'''cert.php'''
|-valign="top"
|-valign="top"
|<pre>
|<pre>
TITLE UNIFORM SERVER - Certificate and Key generator  
TITLE UNIFORM SERVER - Certificate and Key generator  
COLOR B0
COLOR B0
Line 28: Line 27:
..\..\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
&lt;/pre&gt;
</pre>
|&amp;nbsp;
|&nbsp;
|&lt;pre&gt;
|<pre>
&lt;?php
<?php
print &quot;\ntest\n&quot;;
print "\ntest\n";
?&gt;
?>
&lt;/pre&gt;
</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.
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 56: Line 55:
Press any key to continue . . .
Press any key to continue . . .
|
|
&lt;pre&gt;
<pre>
&lt;?php
<?php
print &quot;\ntest\n&quot;;
print "\ntest\n";
//=== 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;
?>
&lt;/pre&gt;
</pre>
|-valign=&quot;top&quot;
|-valign="top"
|
|
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 73: Line 72:
Run (Run.bat) script again this time there will be no errors.
Run (Run.bat) script again this time there will be no errors.
|
|
&lt;pre&gt;
<pre>
[PHP]
[PHP]
extension=php_curl.dll
extension=php_curl.dll
Line 79: Line 78:
extension=php_openssl.dll
extension=php_openssl.dll


extension_dir = &quot;./extensions&quot;
extension_dir = "./extensions"
error_reporting = E_ALL | E_STRICT
error_reporting = E_ALL | E_STRICT
date.timezone = &quot;Europe/London&quot;
date.timezone = "Europe/London"
&lt;/pre&gt;
</pre>
|}
|}
'''''[[#top | Top]]'''''
'''''[[#top | Top]]'''''
Line 88: Line 87:
=== Openssl configuration ===
=== Openssl configuration ===
{|
{|
|-valign=&quot;top&quot;
|-valign="top"
|
|
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 106: Line 105:


Reading the manual you will find  
Reading the manual you will find  
&lt;pre&gt;
<pre>
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.
&lt;/pre&gt;
</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.
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.
|
|
&lt;pre&gt;
<pre>
&lt;?php
<?php
print &quot;\ntest\n&quot;;
print "\ntest\n";
//=== 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 120: Line 119:
//=== Create data array for certificate information
//=== Create data array for certificate information
$dn = array(
$dn = array(
   &quot;countryName&quot;           =&gt; &quot;UK&quot;,
   "countryName"           => "UK",
   &quot;stateOrProvinceName&quot;   =&gt; &quot;Cambridge&quot;,
   "stateOrProvinceName"   => "Cambridge",
   &quot;localityName&quot;           =&gt; &quot;Cambs&quot;,
   "localityName"           => "Cambs",
   &quot;organizationName&quot;       =&gt; &quot;UniServer&quot;,
   "organizationName"       => "UniServer",
   &quot;organizationalUnitName&quot; =&gt; &quot;Demo&quot;,
   "organizationalUnitName" => "Demo",
   &quot;commonName&quot;             =&gt; &quot;localhost&quot;,
   "commonName"             => "localhost",
   &quot;emailAddress&quot;           =&gt; &quot;me@example.com&quot;
   "emailAddress"           => "me@example.com"
);
);


Line 133: Line 132:


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


?&gt;
?>
&lt;/pre&gt;
</pre>
|}
|}
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 153: Line 152:
|-
|-
|
|
&lt;pre&gt;
<pre>
#######################################################################
#######################################################################
# File name: openssl.cnf
# File name: openssl.cnf
Line 195: Line 194:
keyUsage                = digitalSignature, keyEncipherment
keyUsage                = digitalSignature, keyEncipherment
extendedKeyUsage        = serverAuth, nsSGC, msSGC
extendedKeyUsage        = serverAuth, nsSGC, msSGC
nsComment              = &quot;OpenSSL Certificate for SSL Web Server&quot;
nsComment              = "OpenSSL Certificate for SSL Web Server"


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


Line 220: Line 219:


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.
&lt;pre&gt;
<pre>
//== Determine path
//== Determine path
$ssl_path = getcwd();
$ssl_path = getcwd();
Line 227: Line 226:
//== Create a configuration array containing path to openssl.cnf  
//== Create a configuration array containing path to openssl.cnf  
$config = array(
$config = array(
&quot;config&quot; =&gt; &quot;$ssl_path/openssl.cnf&quot;
"config" => "$ssl_path/openssl.cnf"
);
);
&lt;/pre&gt;
</pre>


'''''[[#top | Top]]'''''
'''''[[#top | Top]]'''''
Line 239: Line 238:
|-
|-
|
|
&lt;pre&gt;
<pre>
//=== Create data array for certificate information
//=== Create data array for certificate information
$dn = array(
$dn = array(
   &quot;countryName&quot;           =&gt; &quot;UK&quot;,
   "countryName"           => "UK",
   &quot;stateOrProvinceName&quot;   =&gt; &quot;Cambridge&quot;,
   "stateOrProvinceName"   => "Cambridge",
   &quot;localityName&quot;           =&gt; &quot;Cambs&quot;,
   "localityName"           => "Cambs",
   &quot;organizationName&quot;       =&gt; &quot;UniServer&quot;,
   "organizationName"       => "UniServer",
   &quot;organizationalUnitName&quot; =&gt; &quot;Demo&quot;,
   "organizationalUnitName" => "Demo",
   &quot;commonName&quot;             =&gt; &quot;localhost&quot;,
   "commonName"             => "localhost",
   &quot;emailAddress&quot;           =&gt; &quot;me@example.com&quot;
   "emailAddress"           => "me@example.com"
);
);
&lt;/pre&gt;
</pre>
'''''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 256: Line 255:
=== 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.
&lt;pre&gt;
<pre>
resource openssl_pkey_new  ([  array $configargs  ] )
resource openssl_pkey_new  ([  array $configargs  ] )
&lt;/pre&gt;
</pre>
Code:
Code:
{|
{|
|-
|-
|
|
&lt;pre&gt;
<pre>
//=== 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);
&lt;/pre&gt;
</pre>
|}
|}


Line 273: Line 272:
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,


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


Line 289: Line 288:
=== 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.
&lt;pre&gt;
<pre>
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 ]])
&lt;/pre&gt;
</pre>
Code:
Code:
{|
{|
|-
|-
|
|
&lt;pre&gt;
<pre>
//== 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);
&lt;/pre&gt;
</pre>
|}
|}
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 307: Line 306:
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.  


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


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


&lt;pre&gt;
<pre>
bool openssl_x509_export_to_file(mixed $x509, string $outfilename [,bool $notext ])
bool openssl_x509_export_to_file(mixed $x509, string $outfilename [,bool $notext ])
&lt;/pre&gt;
</pre>
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 337: Line 336:
|-
|-
|
|
&lt;pre&gt;
<pre>
//== Create server certificate  
//== Create server certificate  
openssl_x509_export_to_file($sscert,  &quot;server.crt&quot;,  FALSE );
openssl_x509_export_to_file($sscert,  "server.crt",  FALSE );
&lt;/pre&gt;
</pre>
|}
|}
'''''[[#top | Top]]'''''
'''''[[#top | Top]]'''''
Line 346: Line 345:
==== 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
&lt;pre&gt;
<pre>
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 ])
&lt;/pre&gt;
</pre>


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


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


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


Line 399: Line 398:


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


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


//== Create a signing request file  
//== Create a signing request file  
openssl_csr_export_to_file($csr, &quot;server.csr&quot;);
openssl_csr_export_to_file($csr, "server.csr");
?&gt;
?>
&lt;/pre&gt;
</pre>
|}
|}
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 449: Line 448:


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


Loadfile &quot;C:/Nano_5_6_7/UniServer/usr/local/php/ssleay32.dll&quot;
Loadfile "C:/Nano_5_6_7/UniServer/usr/local/php/ssleay32.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/libeay32.dll"
Loadfile &quot;C:/Nano_5_6_7/UniServer/usr/local/php/libmysql.dll&quot;
Loadfile "C:/Nano_5_6_7/UniServer/usr/local/php/libmysql.dll"




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
&lt;/pre&gt;
</pre>
It gives a saving of 1.51 MB  
It gives a saving of 1.51 MB  



Latest revision as of 08:33, 24 November 2010

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   cert.php
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
 
<?php
print "\ntest\n";
?>

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 . . .

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

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.

[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"

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

Note: You need to have a valid openssl.cnf
installed for this function to operate correctly.

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.

<?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);

?>

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:

#######################################################################
# File name: openssl.cnf
# Created By: The Uniform Server Development Team
# Edited Last By: Mike Gleaves (ric) 
# V 1.0 7-1-2009
# Uses OpenSSL 0.9.8i
########################################################################

#
# OpenSSL configuration file.
#

# 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"

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.

//== 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"
);

Top

Data array dn

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

Change appropriate keys to meet your own requirements:

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

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.

resource openssl_pkey_new  ([  array $configargs  ] )

Code:

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

Top

Function openssl_csr_new

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

mixed openssl_csr_new (array $dn, resource &$privkey [,array $configargs [,array $extraattribs ]] )

Code:

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

Top

Function openssl_csr_sign

Function openssl_csr_sign() generates an x509 certificate resource from the given CSR.

resource openssl_csr_sign(mixed $csr, mixed $cacert, mixed $priv_key, int $days[,array $configargs[,int $serial = 0 ]])

Code:

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

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.

bool openssl_pkey_export_to_file(mixed $key,string $outfilename[,string $passphrase[,array $configargs]])

This function is a quick way to kill Apache stone dead! To prevent this ensure you use NULL for $passphrase.

Code:

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

Top

Function openssl_x509_export_to_file

Function openssl_x509_export_to_file() exports a certificate to file

bool openssl_x509_export_to_file(mixed $x509, string $outfilename [,bool $notext ])

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:

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

Top

Function openssl_csr_export_to_file

Function openssl_csr_export_to_file()exports a CSR to a file

bool openssl_csr_export_to_file(resource $csr, string $outfilename[, bool $notext = true ])

Code:

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

Top

Complete code

Edit file gen.php to contain the folloing code:

<?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");
?>

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

# Example:
# 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

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