2012-04-05 11 views
5

Czy można wyeksportować certyfikat i klucz prywatny do .pfx wzdłuż z łańcuchem certyfikatów (certyfikat główny i/lub półprodukt), używając PHP openssl_pkcs12_export()?łańcuch eksportu z openssl_pkcs12_export w PHP

UPDATE: Wziąłem spojrzeć na źródło dla php przedłużenie openssl i stwierdzili, że openssl_pkcs12_export() obsługuje 2 argumenty inne niż te, które w dokumentacji friendly_name i extracerts. To z ext/openssl/openssl.c, sprawdź linie 1914-1920 (PHP-5.4.0):

1878 /* {{{ proto bool openssl_pkcs12_export(mixed x509, string &out, mixed priv_key, string pass[, array args]) 
1879 Creates and exports a PKCS12 to a var */ 
1880 PHP_FUNCTION(openssl_pkcs12_export) 
1881 { 
1882   X509 * cert = NULL;                                     
1883   BIO * bio_out; 
1884   PKCS12 * p12 = NULL; 
1885   zval * zcert = NULL, *zout = NULL, *zpkey, *args = NULL; 
1886   EVP_PKEY *priv_key = NULL; 
1887   long certresource, keyresource; 
1888   char * pass; 
1889   int pass_len; 
1890   char * friendly_name = NULL; 
1891   zval ** item; 
1892   STACK_OF(X509) *ca = NULL; 
1893 
1894   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzzs|a", &zcert, &zout, &zpkey, &pass, &pass_len, &args) == FAILURE) 
1895     return; 
1896 
1897   RETVAL_FALSE; 
1898 
1899   cert = php_openssl_x509_from_zval(&zcert, 0, &certresource TSRMLS_CC); 
1900   if (cert == NULL) { 
1901     php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get cert from parameter 1"); 
1902     return; 
1903   } 
1904   priv_key = php_openssl_evp_from_zval(&zpkey, 0, "", 1, &keyresource TSRMLS_CC); 
1905   if (priv_key == NULL) { 
1906     php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get private key from parameter 3"); 
1907     goto cleanup; 
1908   } 
1909   if (cert && !X509_check_private_key(cert, priv_key)) { 
1910     php_error_docref(NULL TSRMLS_CC, E_WARNING, "private key does not correspond to cert"); 
1911     goto cleanup; 
1912   } 
1913 
1914   /* parse extra config from args array, promote this to an extra function */ 
1915   if (args && zend_hash_find(Z_ARRVAL_P(args), "friendly_name", sizeof("friendly_name"), (void**)&item) == SUCCESS) 
1916     friendly_name = Z_STRVAL_PP(item); 
1917 
1918   if (args && zend_hash_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts"), (void**)&item) == SUCCESS) 
1919     ca = php_array_to_X509_sk(item TSRMLS_CC); 
1920   /* end parse extra config */ 
1921 
1922   p12 = PKCS12_create(pass, friendly_name, priv_key, cert, ca, 0, 0, 0, 0, 0); 
1923 
1924   bio_out = BIO_new(BIO_s_mem()); 
1925   if (i2d_PKCS12_bio(bio_out, p12)) { 
1926     BUF_MEM *bio_buf; 
1927 
1928     zval_dtor(zout); 
1929     BIO_get_mem_ptr(bio_out, &bio_buf); 
1930     ZVAL_STRINGL(zout, bio_buf->data, bio_buf->length, 1); 
1931 
1932     RETVAL_TRUE; 
1933   } 
1934 
1935   BIO_free(bio_out); 
1936   PKCS12_free(p12); 
1937   php_sk_X509_free(ca); 
1938 
1939 cleanup: 
1940 
1941   if (keyresource == -1 && priv_key) { 
1942     EVP_PKEY_free(priv_key); 
1943   } 
1944   if (certresource == -1 && cert) { 
1945     X509_free(cert); 
1946   } 
1947 } 
1948 /* }}} */ 

jednak nie jestem pewien, w jaki sposób przekazać dodatkowe certyfikaty jako argumenty ... żadnych wskazówek?

Daj mi znać, jeśli łatwiej czytelny bez numerów linii

Odpowiedz

5

To jest a bug that has been brought up prawie dwa miesiące temu.

szczęście on dostarcza poprawkę przykładowy docs:

$args = array(
       'extracerts' => $CAcert, 
       'friendly_name' => 'My signed cert by CA certificate' 
      ); 
openssl_pkcs12_export($signed_csr, $cerificate_out, $private_key_resource, $passphrase, $args); 

Co jest $CAcert? Wewnętrznie zostaje przekazana do funkcji, która jest takes an array and turns it into a x509 i ta funkcja wykrywa również, czy jest to tablica certyfikatów lub pojedynczy certyfikat. Każdy element powinien być zasobem x509, jeśli przekazujesz tablicę, lub $ CAcert powinien być pojedynczym zasobem, jeśli nie przekazujesz tablicy. openssl_x509_read jest prawdopodobnie tym, czego chcesz użyć tutaj, ponieważ zwraca typ zasobów x509, który jest oczekiwany w $CAcert.

Niektórzy twierdzą, że aktualizacja dokumentacji jest jedną z najtrudniejszych części projektu PHP. Jeśli nie jesteś świetny w C i chcesz pomóc PHP lepiej, to jest dobre miejsce na rozpoczęcie.

+0

Fajnie, dzięki. Który typ zmiennej miałby wartość $ CAcert w tym kontekście? Tylko ciąg znaków lub dane wyjściowe z PEM odczytane za pomocą openssl_x509_read() lub co? Podaj przykład, jeśli możesz –

+0

@ MathiasR.Jessen Wewnętrznie '$ CAcert' zostaje przekazany do http://lxr.php.net/opengrok/xref/PHP_5_4/ext/openssl/openssl.c#1741 i to wykrywa, czy jest tablicę certyfikatów lub pojedynczy certyfikat, każdy element powinien być zasobem 'x509". Nie zaimplementowałem tego wcześniej, ale bardzo podejrzewam, że twoje założenie o 'openssl_x509_read' jest poprawne, ponieważ zwraca ten typ zasobu. – Incognito

+1

Fajnie, spróbuję zastosować to podejście i wrócić, dziękuję –