tags:

views:

181

answers:

4

Hi, I am trying to use OpenSSL function for RSA sign/verify in PHP. When I try to do openssl_verify using my public key, I am getting this error: "error:0906D06C:PEM routines:PEM_read_bio:no start line", but the function itself works correctly (returns 0 if messages was modified, and 1 if intact). openssl_sign works fine.

How can I fix it?

Currently, I use public key generated by openssl:

define("SC_MSG_PUBLIC", <<<EOD
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALjPcOckMHDVLiUstcRwwx8kF5PzsiEs
rskyndWisbXMLU9BHomXwL7Qg2L91jE+sNSobkzBDF41CbwDiNlofZUCAwEAAQ==
-----END PUBLIC KEY-----
EOD
);

Any ideas why this error triggers, but things works fine?

Tried to generate public key out of private, and use it, but it appeared to be exactly the same, same error message :-S

$pkey = openssl_pkey_get_private(SC_MSG_PRIVATE);
$keyDetails = openssl_pkey_get_details($pkey);
file_put_contents('c:\publickey', $keyDetails['key']);

Also, I've tried to install newer versions of everything (PHP 5.3.1, OpenSSL 1.0.0a) - same result. And, I am on windows.

A: 

Reason:

This error is usually caused by one corrupt character at the beginning of the .crt file. So, the chances are that you have an extra space, an extra character, an extra line, etc. in either the SSL Certificate file (.crt) or the SSL key file (.key).

Possible Solution(s):

  1. Check your .crt file.
  2. The character problem may be in your key, try this (without linebreaks, etc):

.

define("SC_MSG_PUBLIC", "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALjPcOckMHDVLiUstcRwwx8kF5PzsiEsrskyndWisbXMLU9BHomXwL7Qg2L91jE+sNSobkzBDF41CbwDiNlofZUCAwEAAQ==");
shamittomar
Didn't helped, it cannot parse key in 1 line.It parses it only if it's in these 4 lines.
BarsMonster
+1  A: 

You might have an easier time using phpseclib for signature creation / verification:

http://phpseclib.sourceforge.net/documentation/misc_crypt.html#misc_crypt_rsa_examples

notedshow
This might work, but this is kinda wierd... Instead widely used native and very optimized library, we have to use slow byte-code-based one....
BarsMonster
The slow part of RSA is the math and since phpseclib's Crypt_RSA uses gmp, if it's available, speed isn't much of an issue. Actually, the really slow part is key generation. Everything else, even if phpseclib's native PHP BigInteger implementation is being used, is pretty fast. Try it out if your skeptical.The thing about OpenSSL is that it's intended for C developers. The PHP bindings are subpar and the API isn't, imho, intuitive for PHP developers.
notedshow
This would work in the worst case, but I would rather prefer to work with OpenSSL, it's defacto standard and the message I am working with in PHP is going to be signed/verified by C++ part too using OpenSSL, so extra consistency would be a plus.
BarsMonster
+1  A: 

Have you tried to call openssl_verify() with a (maybe self-signed) certificate containing your public key instead of a pure public key ?

As far as I know, some PHP OpenSSL functions do not properly support naked public keys although it seems strange that it does verify correctly in spite of the error.

<?php
$private = openssl_pkey_get_private(file_get_contents('private'), 'passphrase');

// This causes the "no start line" error when using a naked public key:
$public  = openssl_pkey_get_public(file_get_contents('public')); // <-- this should be cert

echo openssl_error_string()."\n";

openssl_sign('Test', $sig, $private);
var_dump(openssl_verify('Test', $sig, $public));

echo openssl_error_string()."\n";
?>

Example for converting a public key to a simple certificate in a Linux/UNIX shell such as bash (refer to the OpenSSL documentation or some tutorials for more):

# Create certificate request
openssl req -new -days 3600 -key [PRIVATE-KEY-FILE] -out [REQUEST-TMP-FILE]

# Create certificate from request
RANDFILE=[RANDOM-TMP-FILE] openssl x509 -req -in [REQUEST-TMP-FILE] -signkey [PRIVATE-KEY-FILE] -out [CERTIFICATE-OUT-FILE]

This will also create temporary files you might want to delete afterwards, namely [REQUEST-TMP-FILE] and [RANDOM-TMP-FILE].

PHP sample code can be found at http://de.php.net/manual/en/function.openssl-csr-new.php.

Archimedix
That's a perfect solution. Thanks for steps to generate certificate out of my key. You've got a nice rep up :-)
BarsMonster
Thanks, greatly appreciated.
Archimedix
+1  A: 

Where everyone else has an errno that is reset to zero automatically by successful operations, OpenSSL has an "error stack", that you need to empty manually. See function openssl_error_string which is implemented in terms of ERR_get_error. Chances are that the error message that you are seeing has nothing to do with your code; try adding this before your code:

while ($msg = openssl_error_string()) {};

and in between each line:

while ($msg = openssl_error_string())
    echo "OpenSSL error when doing foo:" . $msg . "<br />\n";
DomQ
This is what I actually do.
BarsMonster