php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #38917 OpenSSL: signing function for spkac
Submitted: 2006-09-21 23:45 UTC Modified: 2013-07-17 23:28 UTC
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: zeph at purotesto dot it Assigned: kaplan
Status: Closed Package: OpenSSL related
PHP Version: trunk OS: Irrilevant
Private report: No CVE-ID:
 [2006-09-21 23:45 UTC] zeph at purotesto dot it
Description:
------------
i need openssl api support for spkac

now there's the possibility to sign a pkcs10 csr (created by explorer) but not an spkac created by firefox/mozilla/netscape/safary ...

check www.openca.org for more information... i need that api to create something similar but more usable on the GOsa project http://gosa.gonicus.de

by
Guido Serra

http://dev.purotesto.it/support/gosa
GOsa CA Management plugin


Patches

spki.patch (last revision 2011-12-22 10:41 UTC) by jason dot gerfen at gmail dot com)

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-02-21 21:18 UTC] jani@php.net
-Package: Feature/Change Request +Package: OpenSSL related
 [2011-12-03 02:55 UTC] jason dot gerfen at gmail dot com
Not sure how to go about submitting a patch I am working on to address this.
 [2011-12-06 11:28 UTC] jason dot gerfen at gmail dot com
Here is a patch to implement three new functions to help with verification of the SPKAC HTML keygen element.

To patch:

1. Download PHP-5.3.8
2. Download patch from here (spki.patch)
3. Apply patch
%> patch -p0 < spki.patch
4. Configure and compiled PHP
%> ./configure --with-openssl=/path/to/openssl
%> make && make install

Test script:
$key = openssl_pkey_new(array('digest_alg' => 'sha1',
                              'private_key_type' => OPENSSL_KEYTYPE_RSA,
                              'private_key_bits' => 2048));

if (function_exists('openssl_spki_new')){
 $spki = openssl_spki_new($key, 'password');
 echo $spki.'\n\r';
}

if (function_exists('openssl_spki_verify')){
 echo openssl_spki_verify(preg_replace('/SPKAC=/', '', $spki)).'\n\r';
}

if (function_exists('openssl_spki_export')){
 echo openssl_spki_export(preg_replace('/SPKAC=/', '', $spki)).'\n\r';
}
 [2011-12-08 10:57 UTC] jason dot gerfen at gmail dot com
I modified the test case and fixed a slight memory problem that would occasionally take place when allocating memory for the openssl_spki_new() return value.

echo "Generating private key...";
$key = openssl_pkey_new(array('digest_alg' => 'sha1',
                              'private_key_type' => OPENSSL_KEYTYPE_RSA,
                              'private_key_bits' => 2048));
echo "done\n";
echo "============================\n";

echo "Creating SPKAC...\n";
if (function_exists('openssl_spki_new')){
 $spki = openssl_spki_new($key, 'wtfd00d');
 echo $spki;
}
echo "done\n";
echo "============================\n";

echo "SPKAC details...\n";
if (function_exists('openssl_spki_details')){
 $x = (empty($_POST['spki-key'])) ?
  openssl_spki_details(preg_replace('/SPKAC=/', '', $spki)) :
  openssl_spki_details($_POST['spki-key']);
 var_dump($x);
}
echo "done\n";
echo "============================\n";

echo "Verifying SPKAC...\n";
if (function_exists('openssl_spki_verify')){
 $y = (empty($_POST['spki-key'])) ?
  openssl_spki_verify(preg_replace('/SPKAC=/', '', $spki)) :
  openssl_spki_verify($_POST['spki-key']);
 var_dump($y);
}
echo "\n============================\n";

echo "Exporting public key from SPKAC...\n";
if (function_exists('openssl_spki_export')){
 $z = (empty($_POST['spki-key'])) ?
  openssl_spki_export(preg_replace('/SPKAC=/', '', $spki)) :
  openssl_spki_export($_POST['spki-key']);
 var_dump($z);
}
 [2011-12-13 16:56 UTC] jason dot gerfen at gmail dot com
Since I have not seen any changes on this I am going to post the patch to php-
internals list.
 [2011-12-13 17:04 UTC] pajoye@php.net
-PHP Version: 4.4.4 +PHP Version: trunk
 [2011-12-13 17:04 UTC] pajoye@php.net
Hi!

Thanks for the patch, please add some test cases as well (phpt format) so we can 
easily valid the new functions.

Also be sure that the patched ssl can still be built against older openssl version 
as we still support them (0.9.x serie for trunk and 5.4).
 [2011-12-14 11:40 UTC] jason dot gerfen at gmail dot com
<form id="spkac" name="spkac" method="post" action="openssl-spki.php">
 <keygen name="spki-key" keytype="rsa" challenge="testing"></keygen>
 <input type="submit">
</form>

<?php

if (!empty($_POST['spki-key'])) {
 echo '<pre>'; print_r($_POST['spki-key']); echo '</pre>';


}

if (empty($_POST['spki-key'])){

 echo "Generating private key...";

 $key = openssl_pkey_new(array('digest_alg' => 'sha1',

                               'private_key_type' => OPENSSL_KEYTYPE_RSA,

                               'private_key_bits' => 2048));

 echo "done<br/>";

 echo "============================<br/>";

}



if (empty($_POST['spki-key'])){

 echo "Creating SPKAC...<br/>";

 if (function_exists('openssl_spki_new')){

  $spki = openssl_spki_new($key, 'wtfd00d');

  echo "<pre>".$spki."</pre>";

 }

 echo "<br/>done<br/>";

 echo "============================<br/>";

}



echo "Verifying SPKAC...<br/>";

if (function_exists('openssl_spki_verify')){

 $y = (empty($_POST['spki-key'])) ?

  openssl_spki_verify(preg_replace('/SPKAC=/', '', $spki)) :

  openssl_spki_verify($_POST['spki-key']);

 var_dump($y);

}

echo "<br/>============================<br/>";



echo "Exporting challenge from SPKAC...<br/>";

if (function_exists('openssl_spki_export_challenge')){

 $x = (empty($_POST['spki-key'])) ?

  openssl_spki_export_challenge(preg_replace('/SPKAC=/', '', $spki)) :

  openssl_spki_export_challenge($_POST['spki-key']);

 echo $x;

}

echo "<br/>done<br/>";

echo "============================<br/>";



echo "Exporting public key from SPKAC...<br/>";

if (function_exists('openssl_spki_export')){

 $z = (empty($_POST['spki-key'])) ?

  openssl_spki_export(preg_replace('/SPKAC=/', '', $spki)) :

  openssl_spki_export($_POST['spki-key']);

 echo '<pre>'; print_r($z); echo '</pre>';

}

echo "<br/>============================<br/>";



echo "SPKAC details...<br/>";

if (function_exists('openssl_spki_details')){

 $w = (empty($_POST['spki-key'])) ?

  openssl_spki_details(preg_replace('/SPKAC=/', '', $spki)) :

  openssl_spki_details($_POST['spki-key']);

 echo '<pre>'; print_r($w); echo '</pre>';

}

echo "done<br/>";

echo "============================<br/>";



if (empty($_POST['spki-key'])){

 openssl_free_key($key);

}



?>
 [2011-12-14 12:02 UTC] pajoye@php.net
Please see the phpt files in ext/openssl/tests/

this is how tests should be written.

Further explanations are available here: http://qa.php.net/

Thanks!
 [2011-12-14 12:02 UTC] pajoye@php.net
-Status: Open +Status: Feedback
 [2011-12-14 13:51 UTC] jason dot gerfen at gmail dot com
This will test all five new functions unless you would like one test case per function?

--TEST--
openssl_spki_new(), openssl_spki_verify(), openssl_spki_export(), openssl_spki_export_challenge(), openssl_spki_details()
--SKIPIF--
<?php
if (!extension_loaded("openssl")) die("skip");
if (!@openssl_pkey_new()) die("skip cannot create private key");
?>
--FILE--
<?php

echo "Creating private key\n";
$key = openssl_pkey_new();
if ($key === false)
 die("failed to create private key\n");

echo "Creating new SPKAC\n";
if (!function_exists("openssl_spki_new"))
 die("openssl_spki_new() does not exist\n");

$spki = openssl_spki_new($key, "sample_challenge_string");
if ($spki === false)
 die("could not create spkac\n");

echo "Verifying SPKAC\n";
if (!function_exists("openssl_spki_verify"))
 die("openssl_spki_verify() does not exist\n");

$x = openssl_spki_verify(preg_replace("/SPKAC=/", "", $spki));
if ($x === false)
 die("could not verify spkac\n");

echo "Exporting challenge\n";
if (!function_exists("openssl_spki_export_challenge"))
 die("openssl_spki_export_challenge() does not exist\n");

$y = openssl_spki_export_challenge(preg_replace("/SPKAC=/", "", $spki));
if ($y !== "sample_challenge_string")
 die("could not verify challenge string from spkac\n");

echo "Exporting public key from SPKAC\n";
if (!function_exists("openssl_spki_export"))
 die("openssl_spki_export() does not exist\n");

$z = openssl_spki_export(preg_replace("/SPKAC=/", '', $spki));
if ($z === "")
 die("could not export public key from spkac\n");

echo "Generating details of SPKAC structure\n";
if (!function_exists("openssl_spki_details"))
 die("openssl_spki_details() does not exist\n");

$w = openssl_spki_details(preg_replace('/SPKAC=/', '', $spki));
if ($w === "")
 die("could not obtain details from spkac\n");

echo "OK!\n";

openssl_free_key($key);
?>
--EXPECT--
Creating private key
Creating new SPKAC
Verifying SPKAC
Exporting challenge
Exporting public key from SPKAC
Generating details of SPKAC structure
OK!
 [2011-12-14 19:40 UTC] jason dot gerfen at gmail dot com
One other question about using SPKAC's when creating a x509. It seems the current method using openssl_csr_new() which in turn calls the php_openssl_make_REQ() to assign the specified DN attributes has no method of adding the SPKAC field.

After digging around it seems logical to use the OBJ_create() and OBJ_* family of functions to add NID. Please forgive me if I am way off here but any direction you could point me in using the existing functions to output and sign a certificate similar to the following command?

openssl ca -config /path/to/openssl.conf -days 180 -notext -batch \
  -spkac /path/to/cert.pem -out /path/to/signed.pem -passin pass:'random'

My assumption is that I will need to create one specifically for this purpose but would like your insight.
 [2011-12-14 22:10 UTC] jason dot gerfen at gmail dot com
Please disregard my previous comment. I did a little more digging and am under the impression that adding the following to php_openssl_make_REQ() function should allow me to create a self signed certificate using the SPKAC NID like so?

if (strcmp(strindex, "SPKAC") == 0) {
 if (!X509_NAME_add_entry_by_txt(subj, strindex, MBSTRING_ASC, (unsigned char*)Z_STRVAL_PP(item), -1, -1, 0)){
  php_error_docref(NULL TSRMLS_CC, E_WARNING, "dn: add_entry_by_txt %s -> %s (failed)", strindex, Z_STRVAL_PP(item));
  return FAILURE;
 }
}

Would you recommend another method? Please advise.
 [2011-12-21 10:49 UTC] jason dot gerfen at gmail dot com
Once again, please disregard the last message. After researching the documentation I found that where I had been using NULL with the openssl_csr_sign() function allows for a CA option as well as the SPKAC addition to the configargs optional array.

The patch was updated last night to include the 026.phpt test script, as well as the five new functions to work with the SPKI provided by keygen tags.

How do patch inclusions work besides posting them to the php internals list?
 [2012-01-10 10:38 UTC] jason dot gerfen at gmail dot com
I have added the requested test case and it is included in the patch
as 026.phpt. I have also performed the required testing against the
Openssl 0.9.8x and 1.0.0x. It is attached to the original bug report
#38917. In addition to attaching the proposed patch I have created a
github repo to make maintenance on the patch simple for myself. The
URL is https://github.com/jas-/SPKAC-PHP-OpenSSL.
 [2012-12-19 15:14 UTC] queenzeal at gmail dot com
If you want SPKAC support in PHP without having to recompile it, try the latest 
Git version of phpseclib (http://phpseclib.sourceforge.net/). An example of how to 
use it:

http://www.frostjedi.com/phpbb3/viewtopic.php?p=389618#p389618
 [2013-02-18 00:33 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Open". Thank you.
 [2013-03-03 06:04 UTC] stas@php.net
-Status: No Feedback +Status: Open
 [2013-07-17 23:28 UTC] kaplan@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: kaplan
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Fri Apr 18 23:01:58 2014 UTC