To generate, sign and verify certificates you need to have OpenSSL module installed and provide file with OpenSSL configuration.
Here is an example OpenSSL configuration file:
[ req ]
default_bits = 1024
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca
dirstring_type = nobmp
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2
localityName = Locality Name (eg, city)
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (eg, YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 40
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = CA:true
Name it as openssl.cnf and put in the same folder, where you want to work with certificates.
Here are some basic actions you can perform with X.509 certificates.
Create certificate with public key, private key and certificate's signature:
<?php
// Returns a cer encoded SSL certificate
function create_identity_cer(
$countryName, $stateOrProvinceName, $localityName, $organizationName,
$organizationalUnitName, $commonName, $emailAddress, $foafLocation)
{
// Create the DN array for the openssl function calls
if ($countryName)
$dn = array("countryName" => $countryName);
if ($stateOrProvinceName)
{
if ($dn)
$dn = array_merge($dn,
array("stateOrProvinceName" => $stateOrProvinceName));
else
$dn = array("stateOrProvinceName" => $stateOrProvinceName);
}
if ($localityName)
{
if ($dn)
$dn = array_merge($dn, array("localityName" => $localityName));
else
$dn = array("localityName" => $localityName);
}
if ($organizationName)
{
if ($dn)
$dn = array_merge($dn, array("organizationName" => $organizationName));
else
$dn = array("organizationName" => $organizationName);
}
if ($organizationalUnitName)
{
if ($dn)
$dn = array_merge($dn,
array("organizationalUnitName" => $organizationalUnitName));
else
$dn = array("organizationalUnitName" => $organizationalUnitName);
}
if ($commonName)
{
if ($dn)
$dn = array_merge($dn, array("commonName" => $commonName));
else
$dn = array("commonName" => $commonName);
}
if ($emailAddress)
{
if ($dn)
$dn = array_merge($dn, array("emailAddress" => $emailAddress));
else
$dn = array("emailAddress" => $emailAddress);
}
// if the $dn array is NULL at this point set country name to the default of GB
if (!$dn)
$dn = array("countryName" => "GB");
// Setup the contents of the subjectAltName
if ($foafLocation)
$SAN="URI:$foafLocation";
if ($emailAddress)
{
if ($SAN)
$SAN.=",email:$emailAddress";
else
$SAN="email:$emailAddress";
}
// Export the subjectAltName to be picked up by the openssl.cnf file
if ($SAN)
{
putenv("SAN=$SAN");
}
// Create the array to hold the configuration options for the openssl function calls
// You may need to change the slash "" (for windows) to "/" for linux
$config = array('config'=>dirname(__file__) . '\openssl.cnf');
if ($SAN)
{
// TODO - This should be more easily configured
//$config = array_merge($config, array('x509_extensions' => 'usr_cert'));
}
// Generate a new private (and public) key pair
$privkey = openssl_pkey_new($config);
if ($privkey==FALSE)
{
// Show any errors that occurred here
while (($e = openssl_error_string()) !== false)
{
echo $e . "n";
print "<br><br>";
}
}
// Generate a certificate signing request
$csr = openssl_csr_new($dn, $privkey, $config);
if (!$csr)
{
// Show any errors that occurred here
while (($e = openssl_error_string()) !== false)
{
echo $e . "n";
print "<br><br>";
}
}
// You will usually want to create a self-signed certificate at this
// point until your CA fulfills your request.
// This creates a self-signed cert that is valid for 365 days
$sscert = openssl_csr_sign($csr, null, $privkey, 365, $config);
if ($sscert==FALSE)
{
// Show any errors that occurred here
while (($e = openssl_error_string()) !== false)
{
echo $e . "n";
print "<br><br>";
}
}
if (openssl_x509_export($sscert, $certout)==FALSE)
{
// Show any errors that occurred here
while (($e = openssl_error_string()) !== false)
{
echo $e . "n";
print "<br><br>";
}
}
$pkout = "";
if (openssl_pkey_export($privkey, $pkout,"test123", $config)==FALSE)
{
// Show any errors that occurred here
while (($e = openssl_error_string()) !== false)
{
echo $e . "n";
print "<br><br>";
}
}
openssl_sign($certout, $signature, $privkey);
return array("cer" => $certout, "pem" => $pkout, "signature" => $signature);
}
/*******************************
* Modify these parameters
*******************************/
$foafLocation = "as07142";
$countryName = "LV";
$stateOrProvinceName = "Rigas rajons";
$localityName = "Riga";
$organizationName = "Latvian Unversity";
$organizationalUnitName = "LU";
$commonName = "Arturs Sosins";
$emailAddress = "youremail@domain.com";
$p12Password = "test123";
/*******************************
* End modifications
*******************************/
// Create a cer encoded SSL certificate
if ( $data = create_identity_cer(
$countryName, $stateOrProvinceName, $localityName, $organizationName,
$organizationalUnitName, $commonName, $emailAddress,
$foafLocation ) )
{
// Create files
file_put_contents("./".$foafLocation.".cer", $data["cer"]);
file_put_contents("./".$foafLocation.".pem", $data["pem"]);
file_put_contents("./".$foafLocation."_signature.txt", $data["signature"]);
echo "<p><a href='./".$foafLocation.".cer' target='_blank'>".
"Generated certificate</a></p>";
echo "<p><a href='./".$foafLocation.".pem' target='_blank'>".
"Generated Private Key</a></p>";
echo "<p><a href='./".$foafLocation."_signature.txt' target='_blank'>".
"Signature</a></p>";
}
?>
After this script, there should be 3 files generated, cer file, which is your certificate with public key, pem while, which stores your private key and simple txt file containing signature, by which we can verify your certificate.
So now let's verify certificate. Let's create php file with these contents:
<?php
/*******************************
* Modify these parameters
*******************************/
$foafLocation = "as07142";
/*******************************
* End modifications
*******************************/
//get certificate
$cert = file_get_contents('./'.$foafLocation.'.cer');
//get signature
$sig = file_get_contents('./'.$foafLocation.'_signature.txt');
//parse certificate
$data = openssl_x509_parse($cert);
//output issuer and subject
echo "<p>Subject: ".$data["subject"]["CN"]."</p>";
echo "<p>Issuer: ".$data["issuer"]["CN"]."</p>";
//comparing suject and issuer
if($data["subject"]["CN"] == $data["issuer"]["CN"])
{
echo "<p>Subject matches issuer</p>";
}
echo "<p>Verifying signature:</p>";
// fetch public key from certificate and ready it
$pubkeyid = openssl_pkey_get_public($cert);
// state whether signature is okay or not
$ok = openssl_verify($cert, $sig, $pubkeyid);
if ($ok == 1) {
echo "<p>Verified</p>";
} elseif ($ok == 0) {
echo "<p>Not Verified</p>";
} else {
echo "<p>Error cheking signature</p>";
}
// free the key from memory
openssl_free_key($pubkeyid);
?>
Verification verifies if subject and issuer is the same person, you can modify it to fit your needs. And then we verify if certificate itself using signature.
Next thing we can do is to encrypt any information using our public key in certificate and then decrypt it with our private key. Meaning anyone can take your certificate and encrypt information with it, and only you could decrypt it using your private key.
<?php
/*******************************
* Modify these parameters
*******************************/
$foafLocation = "as07142";
/*******************************
* End modifications
*******************************/
if(isset($_FILES["data"]) && trim($_FILES["data"]["name"]) != "")
{
//time for filename
$time = time();
//get contents of file
$_POST["data"] = file_get_contents($_FILES["data"]["tmp_name"]);
//encrypting
if($_POST["mode"] == "enc")
{
//get certificate
$cert = file_get_contents('./'.$foafLocation.'.cer');
//get public key
$pubkeyid = openssl_pkey_get_public($cert);
//encrypt
openssl_public_encrypt($_POST["data"] , $encrypted , $pubkeyid);
//store result in file
file_put_contents("./files/".$time."_encrypted.txt", $encrypted);
openssl_free_key($pubkeyid);
}
else
{
//get private key
$pem = file_get_contents('./'.$foafLocation.'.pem');
$privat_key = openssl_pkey_get_private(array($pem, "test123"));
//decrypt
openssl_private_decrypt ($_POST["data"] , $decrypted , $privat_key);
//store result in file
file_put_contents("./files/".$time."_decrypted.txt", $decrypted);
openssl_free_key($privat_key);
}
}
?>
<form method='post' action='' enctype='multipart/form-data'>
<p><select name='mode'>
<option value='enc'>Encrypt</option>
<option value='dec'>Decrypt</option>
</select></p>
<p>File: <input type='file' name='data'/></p>
<p><input type='submit' value='Submit'/></p>
</form>
<fieldset>
<legend>Existing files</legend>
<table>
<?php
$keys = "<tr><td><ul>";
$d = new DirectoryIterator("./files");
foreach($d as $f)
{
$name = $f->getFilename();
if($name != "." && $name != "..")
{
$keys .= "<li><a href='./files/".$name."' target='_blank'>".$name."</a></li>";
}
}
echo $keys."</ul></td></tr>";
?>
</table>
</fieldset>
No comments:
Post a Comment