2012-04-05 31 views
5

Có thể xuất chứng chỉ và khóa cá nhân sang .pfx dọc theo bằng chuỗi chứng chỉ (root cert và/hoặc trung gian), sử dụng PHP openssl_pkcs12_export()?chuỗi xuất khẩu với openssl_pkcs12_export trong PHP

CẬP NHẬT: Tôi đã lấy một cái nhìn tại nguồn cho phần mở rộng openssl php, và thấy rằng openssl_pkcs12_export() hỗ trợ 2 args khác hơn so với những người trong tài liệu, friendly_nameextracerts. Đây là từ ext/openssl/openssl.c, hãy kiểm tra dòng 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 /* }}} */ 

Tuy nhiên, tôi không hoàn toàn chắc chắn làm thế nào để vượt qua các chứng chỉ bổ sung đối số ... bất kỳ manh mối?

Hãy cho tôi biết nếu nó dễ đọc hơn nếu không có số dòng

Trả lời

5

Đây là a bug that has been brought up gần hai tháng trước.

Rất may ông cung cấp một bản vá mẫu cho các tài liệu:

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

$CAcert là gì? Nội bộ nó được chuyển đến một hàm takes an array and turns it into a x509 và chức năng đó cũng phát hiện nếu đó là một mảng của các chứng chỉ hoặc một chứng chỉ đơn. Mỗi phần tử phải là một tài nguyên x509 nếu bạn đang truyền một mảng hoặc $ CAcert phải là một tài nguyên duy nhất nếu bạn không truyền mảng. openssl_x509_read có thể là những gì bạn muốn sử dụng ở đây vì nó trả về loại tài nguyên x509 được mong đợi trong $CAcert.

Một số người nói rằng việc cập nhật tài liệu là một trong những phần khó nhất của dự án PHP. Nếu bạn không tuyệt vời với C và muốn giúp PHP trở nên tốt hơn, đó là một nơi tốt để bắt đầu.

+0

Rất tốt, cảm ơn. Loại biến nào sẽ là $ CAcert trong ngữ cảnh này? Chỉ cần một chuỗi hoặc đầu ra từ một PEM đọc với openssl_x509_read() hoặc cái gì? Vui lòng cung cấp ví dụ nếu bạn có thể –

+0

@ MathiasR.Jessen Nội bộ '$ CAcert' được chuyển đến http://lxr.php.net/opengrok/xref/PHP_5_4/ext/openssl/openssl.c#1741 và điều này sẽ phát hiện nếu nó một mảng các certs hoặc một cert duy nhất, mỗi phần tử phải là một 'x509 Resource'. Tôi đã không thực hiện điều này trước nhưng tôi rất nghi ngờ giả định của bạn 'openssl_x509_read' là chính xác khi nó trả về loại tài nguyên đó. – Incognito

+1

Tuyệt, tôi sẽ cố gắng triển khai bằng cách sử dụng phương pháp này và quay lại, cảm ơn –

Các vấn đề liên quan