[prev in list] [next in list] [prev in thread] [next in thread] 

List:       horde-doc
Subject:    [doc] Maybe one for the FAQ (openssl_pkcs7_decrypt problem)
From:       "Roger HÃ¥kansson" <hson () ludd ! luth ! se>
Date:       2003-04-21 0:05:12
[Download RAW message or body]

I don't recall seeing this problem on any of the mailinglists, but since I
ran into trouble because of it(and had a little hell finding it) I thought
I'll send a mail about it.

There is a problem with all PHP versions(up to and including 4.3.1, it is
fixed in 4.3.2RC1) if you have OpenSSL 0.9.7.
(more info at http://bugs.php.net/bug.php?id=22809 )
The problem is that if you try to use openssl_pkcs7_decrypt() or
openssl_get_privatekey() and pass the privatekey stored in a variable
instead of a filereference, PHP will fail to get the private key.

In your php_error.log you will see something like this if you try to open an
encrypted mail in IMP.
----
[18-Apr-2003 23:48:40] PHP Warning:  openssl_pkcs7_decrypt(): unable to get
private key in /var/apache/htdocs_8080/horde/lib/Crypt/smime.php on line 492
----

In order to determine if you have this problem you can use the attached
testprogram.
Change the path to the private and public key-files, the emailaddres and the
passphrase

If you get an output looking like this you have a problem:
----
PHP Warning:  openssl_pkcs7_decrypt()
[http://www.php.net/function.openssl-pkcs7-decrypt]: unable to get private
key in /tmp/openssl_test3.php on line 19
Source: The test string unencrypted
Error decrypting
Decrypted:
----
But if it looks like this your PHP works.
----
Source: The test string unencrypted
Decrypted: The test string unencrypted
----

Solution: You have three options
Downgrade OpenSSL to 0.9.6 (bad idea since it has a number of security
problems)
Upgrade to PHP-stable (or 4.3.2 when its relased)
http://snaps.php.net/php4-STABLE-latest.tar.gz
Patch your PHP: You need to patch $php_build_dirg/ext/openssl/openssl.c,
take a look at the attached files(one is for 4.3.1 and the other for 4.2.3)
and apply it to your openssl.c.

--
Roger Håkansson

["openssl_test3.php" (application/octet-stream)]

<?php
$email = "user@domain.com";
$passphrase = "private";
$text = "The test string unencrypted";
$pubkey = implode('',file("/path/to/certificate.crt"));  
$privkey_pem = implode('',file("/path/to/certificate.key"));  
//$privkey = openssl_get_privatekey("file:///path/to/certificate.key",$passphrase);
$privkey = openssl_get_privatekey($privkey_pem,$passphrase);
$input = tempnam('/tmp','openssl-test1-in');
$output1 = tempnam('/tmp','openssl-test1-out');
$fp1 = fopen($input, 'w+');
fputs($fp1, $text);
fclose($fp1);
echo "Source: $text\n";
$res = openssl_pkcs7_encrypt($input, $output1, $pubkey, array("To" => $email));
$result = file($output1);
if (!$res || empty($result)) echo "Error encrypting\n";
$output2 = tempnam('/tmp','openssl-test2-out');
$res = openssl_pkcs7_decrypt($output1, $output2, $pubkey, $privkey );
$result = file($output2);
if (!$res || empty($result)) echo "Error decrypting\n";
$result = file($output2);
$tmp_txt = implode('',file($output2));
echo "Decrypted: $tmp_txt\n";
unlink($input);
unlink($output1);
unlink($output2);
?>


["php-4.2.3_openssl.c.patch" (application/octet-stream)]

*** ext/openssl/openssl.c.orig	Fri Jul 12 23:47:33 2002
--- ext/openssl/openssl.c	Sat Apr 19 04:47:43 2003
***************
*** 1661,1686 ****
  			cert = php_openssl_x509_from_zval(val, 0, &cert_res TSRMLS_CC);
  			free_cert = (cert_res == -1);
  			/* actual extraction done later */
  		}
  		else	{
  			/* we want the private key */
  			if (filename)	{
! 				BIO *in = BIO_new_file(filename, "r");
! 				if (in == NULL)
! 					return NULL;
! 				key = PEM_read_bio_PrivateKey(in, NULL,NULL, passphrase);
! 				BIO_free(in);
  			}
  			else	{
! 				BIO *	b = BIO_new_mem_buf(Z_STRVAL_PP(val), Z_STRLEN_PP(val));
! 				if (b == NULL)
! 					return NULL;
! 
! 				key = (EVP_PKEY *) PEM_ASN1_read_bio((char *(*)())d2i_PrivateKey,
! 					      PEM_STRING_EVP_PKEY, b,
! 					      NULL, NULL, passphrase);
! 				BIO_free(b);
  			}
  		}
  	}
  
--- 1661,1701 ----
  			cert = php_openssl_x509_from_zval(val, 0, &cert_res TSRMLS_CC);
  			free_cert = (cert_res == -1);
  			/* actual extraction done later */
+ 			if (!cert) {
+ 				/* not a X509 certificate, try to retrieve public key */
+ 				BIO *in;
+ 
+ 				if (filename)	{
+ 					in = BIO_new_file(filename, "r");
+ 				}
+ 				else	{
+ 					in = BIO_new_mem_buf(Z_STRVAL_PP(val), Z_STRLEN_PP(val));
+ 				}
+ 				if (in == NULL)	{
+ 					return NULL;
+ 				}
+ 
+ 				key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL);
+ 				BIO_free(in);
+ 			}
+ 				
  		}
  		else	{
  			/* we want the private key */
+ 			BIO *in;
+ 
  			if (filename)	{
! 				in = BIO_new_file(filename, "r");
  			}
  			else	{
! 				in = BIO_new_mem_buf(Z_STRVAL_PP(val), Z_STRLEN_PP(val));
  			}
+ 			if (in == NULL)	{
+ 				return NULL;
+ 			}
+ 
+ 			key = PEM_read_bio_PrivateKey(in, NULL,NULL, passphrase);
+ 			BIO_free(in);
  		}
  	}
  

["php-4.3.1_openssl.c.patch" (application/octet-stream)]

*** ext/openssl/openssl.c.orig	Thu Dec 12 19:36:38 2002
--- ext/openssl/openssl.c	Mon Apr 21 01:19:38 2003
***************
*** 1728,1754 ****
  		}
  		else	{
  			/* we want the private key */
  			if (filename) {
- 				BIO *in;
  				if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) {
  					return NULL;
  				}
  				in = BIO_new_file(filename, "r");
- 				if (in == NULL)
- 					return NULL;
- 				key = PEM_read_bio_PrivateKey(in, NULL,NULL, passphrase);
- 				BIO_free(in);
  			}
  			else	{
! 				BIO *	b = BIO_new_mem_buf(Z_STRVAL_PP(val), Z_STRLEN_PP(val));
! 				if (b == NULL)
! 					return NULL;
! 
! 				key = (EVP_PKEY *) PEM_ASN1_read_bio((char *(*)())d2i_PrivateKey,
! 					      PEM_STRING_EVP_PKEY, b,
! 					      NULL, NULL, passphrase);
! 				BIO_free(b);
  			}
  		}
  	}
  
--- 1728,1747 ----
  		}
  		else	{
  			/* we want the private key */
+ 			BIO *in;
  			if (filename) {
  				if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) {
  					return NULL;
  				}
  				in = BIO_new_file(filename, "r");
  			}
  			else	{
! 				in = BIO_new_mem_buf(Z_STRVAL_PP(val), Z_STRLEN_PP(val));
  			}
+ 			if (in == NULL)
+ 				return NULL;
+ 			key = PEM_read_bio_PrivateKey(in, NULL,NULL, passphrase);
+ 			BIO_free(in);
  		}
  	}
  


-- 
Documentation mailing list
Frequently Asked Questions: http://horde.org/faq/
To unsubscribe, mail: doc-unsubscribe@lists.horde.org


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic