openssl_csr_new
(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)
openssl_csr_new — CSR を作成する
説明
array
$distinguished_names
,#[\SensitiveParameter] ?OpenSSLAsymmetricKey
&$private_key
,?array
$options
= null
,?array
$extra_attributes
= null
): OpenSSLCertificateSigningRequest|bool
openssl_csr_new() は、新しい CSR
を distinguished_names
の情報に基づいて作成します。
注意: この関数を正しく動作させるには、正しい形式の openssl.cnf をインストールしておく必要があります。 詳細な情報は、インストールについてのセクション を参照ください。
パラメータ
distinguished_names
-
証明書で使用される識別名、またはsubjectフィールド。
private_key
-
private_key
には、事前に openssl_pkey_new() (あるいはその他の openssl_pkey 系の関数)で作成した秘密鍵を設定します。null
も指定できます。null
を指定した場合、 新しい秘密鍵がoptions
の指定に基づいて生成され、指定された変数に代入されます。 これに対応する公開鍵が、CSR への署名に使用されます。 options
-
デフォルトでは、システムの
openssl.conf
の設定に したがってリクエストが初期化されます。options
のキーconfig_section_section
を設定することで、この デフォルト項目を変更することが可能です。また、キーconfig
に別の openssl 設定ファイルを指定することで別の設定を使用することも可能です。 もしoptions
に以下の表のキーが存在すれば、それらはopenssl.conf
の対応する項目と同じ働きをします。設定の上書き options
のキー型 openssl.conf
で同等の意味を持つ項目説明 digest_alg string default_md ダイジェストメソッド、または署名のハッシュ。 通常は openssl_get_md_methods() 関数のリストのうちのひとつです。 x509_extensions string x509_extensions x509 証明書を作成する際に使用する拡張モジュールを選択します req_extensions string req_extensions CSR を作成する際に使用する拡張モジュールを選択します private_key_bits int default_bits 秘密鍵を作成する際に使用するビット数を指定します private_key_type int none 作成する秘密鍵の型を指定します。以下の定数 OPENSSL_KEYTYPE_DSA
,OPENSSL_KEYTYPE_DH
OPENSSL_KEYTYPE_RSA
あるいはOPENSSL_KEYTYPE_EC
からひとつ選択します。 デフォルト値はOPENSSL_KEYTYPE_RSA
です。encrypt_key bool encrypt_key (パスフレーズとともに)エクスポートされるキーを暗号化するか? encrypt_key_cipher int none 暗号定数のうちの一つ。 curve_name string none openssl_get_curve_names() のうちの一つ。 config string N/A 代替の openssl.conf ファイルのパス extra_attributes
-
extra_attributes
は、CSR に関する追加の設定情報を 設定するために使用します。distinguished_names
およびextra_attributes
はどちらも連想配列で、それらの キーが OID に変換されたうえでリクエストの関連する部分に適用されます。
変更履歴
バージョン | 説明 |
---|---|
8.0.0 |
成功した場合に、この関数は
OpenSSLCertificateSigningRequest クラスのインスタンスを返すようになりました。
これより前のバージョンでは、
OpenSSL X.509 CSR 型のリソースが返されていました。
|
8.0.0 |
private_key は、
OpenSSLAsymmetricKey クラスのインスタンスを受け入れるようになりました。
これより前のバージョンでは、
OpenSSL key 型のリソースを受け入れていました。
|
7.1.0 |
options が、新たに curve_name をサポートしました。
|
例
例1 自己署名証明書の作成
<?php
// SSLサーバー証明書では、commonName はセキュアにするドメインです。
// S/MIME 電子メール証明書では、 commonName は電子メールアドレスのオーナーです。
// location と identification フィールドは、セキュアにするドメイン
// または電子メールのオーナーを参照します。
$dn = array(
"countryName" => "GB",
"stateOrProvinceName" => "Somerset",
"localityName" => "Glastonbury",
"organizationName" => "The Brain Room Limited",
"organizationalUnitName" => "PHP Documentation Team",
"commonName" => "Wez Furlong",
"emailAddress" => "wez@example.com"
);
// 新しい 秘密鍵(と公開鍵の) キーペアを生成します
$privkey = openssl_pkey_new(array(
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
));
// CSR を生成します
$csr = openssl_csr_new($dn, $privkey, array('digest_alg' => 'sha256'));
// 自己署名の証明書を生成します。365日有効です
$x509 = openssl_csr_sign($csr, null, $privkey, $days=365, array('digest_alg' => 'sha256'));
// 秘密鍵、CSR と自己署名証明書をあとで使うために保存します。
openssl_csr_export($csr, $csrout) and var_dump($csrout);
openssl_x509_export($x509, $certout) and var_dump($certout);
openssl_pkey_export($privkey, $pkeyout, "mypassword") and var_dump($pkeyout);
// 起きたエラーを表示します。
while (($e = openssl_error_string()) !== false) {
echo $e . "\n";
}
?>
例2 自己署名の ECC 証明書を作成する (PHP 7.1.0 以降)
<?php
$subject = array(
"commonName" => "docs.php.net",
);
// 新しい 秘密鍵(と公開鍵の) キーペアを生成します
$private_key = openssl_pkey_new(array(
"private_key_type" => OPENSSL_KEYTYPE_EC,
"curve_name" => 'prime256v1',
));
// CSR を生成します
$csr = openssl_csr_new($subject, $private_key, array('digest_alg' => 'sha384'));
// 自己署名のEC証明書を生成します。
$x509 = openssl_csr_sign($csr, null, $private_key, $days=365, array('digest_alg' => 'sha384'));
openssl_x509_export_to_file($x509, 'ecc-cert.pem');
openssl_pkey_export_to_file($private_key, 'ecc-private.key');
?>
User Contributed Notes 10 notes
Not sure whether the "bug" (undocumented behavior) I encountered is common to other people, but this comment might save hours of painful debug:
If you can't generate a new private key using openssl_pkey_new() or openssl_csr_new(), your script hangs during the call of these functions and in case you specified a "private_key_bits" parameter, ensure that you cast the variable to an int. Took me ages to notice that.
<?php
$SSLcnf = array('config' => '/usr/local/nessy2/share/ssl/openssl.cnf',
'encrypt_key' => true,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
'digest_alg' => 'sha1',
'x509_extensions' => 'v3_ca',
'private_key_bits' => $someVariable // ---> bad
'private_key_bits' => (int)$someVariable // ---> good
'private_key_bits' => 512 // ---> obviously good
);
?>
When in doubt, read the source code to PHP!
$configargs is fairly opaque as to what is going on behind the scenes. That is, until you actually look at php_openssl_parse_config() in '/ext/openssl/openssl.c':
SET_OPTIONAL_STRING_ARG("digest_alg", req->digest_name,
CONF_get_string(req->req_config, req->section_name, "default_md"));
SET_OPTIONAL_STRING_ARG("x509_extensions", req->extensions_section,
CONF_get_string(req->req_config, req->section_name, "x509_extensions"));
SET_OPTIONAL_STRING_ARG("req_extensions", req->request_extensions_section,
CONF_get_string(req->req_config, req->section_name, "req_extensions"));
SET_OPTIONAL_LONG_ARG("private_key_bits", req->priv_key_bits,
CONF_get_number(req->req_config, req->section_name, "default_bits"));
SET_OPTIONAL_LONG_ARG("private_key_type", req->priv_key_type, OPENSSL_KEYTYPE_DEFAULT);
Here we can see that SET_OPTIONAL_STRING_ARG() is called for most inputs but for 'private_key_bits' SET_OPTIONAL_LONG_ARG() is called. Both calls are C macros that expand to code that enforces the expected input type. The generated code ignores the input without warning/notice if an unexpected type is used and just uses the default from the configuration file. This is why using a string with 'private_key_bits' will result in unexpected behavior.
Further inspection of the earlier initialization in the same function:
SET_OPTIONAL_STRING_ARG("config", req->config_filename, default_ssl_conf_filename);
SET_OPTIONAL_STRING_ARG("config_section_name", req->section_name, "req");
req->global_config = CONF_load(NULL, default_ssl_conf_filename, NULL);
req->req_config = CONF_load(NULL, req->config_filename, NULL);
if (req->req_config == NULL) {
return FAILURE;
}
And elsewhere in another function:
/* default to 'openssl.cnf' if no environment variable is set */
if (config_filename == NULL) {
snprintf(default_ssl_conf_filename, sizeof(default_ssl_conf_filename), "%s/%s",
X509_get_default_cert_area(),
"openssl.cnf");
} else {
strlcpy(default_ssl_conf_filename, config_filename, sizeof(default_ssl_conf_filename));
}
Reveals that 'config' in $configargs is an override for any default setting elsewhere. This actually negates the comment in the documentation that says "Note: You need to have a valid openssl.cnf installed for this function to operate correctly. See the notes under the installation section for more information." A more correct sentence would be "Note: You need to either have a valid openssl.cnf set up or use $configargs to point at a valid openssl.cnf file for this function to operate correctly."
All of that goes to show that looking at the PHP source code is the only real way to figure out what is actually happening. Doing so saves time and effort.
For those of you using Debian-based systems, the openssl configuration file is at: /etc/ssl/openssl.cnf
To set the "basicConstraints" to "critical,CA:TRUE", you have to define configargs, but in the openssl_csr_sign() function !
That's my example of code to sign a "child" certificate :
$CAcrt = "file://ca.crt";
$CAkey = array("file://ca.key", "myPassWord");
$clientKeys = openssl_pkey_new();
$dn = array(
"countryName" => "FR",
"stateOrProvinceName" => "Finistere",
"localityName" => "Plouzane",
"organizationName" => "Ecole Nationale d'Ingenieurs de Brest",
"organizationalUnitName" => "Enib Students",
"commonName" => "www.enib.fr",
"emailAddress" => "ilovessl@php.net"
);
$csr = openssl_csr_new($dn, $clientPrivKey);
$configArgs = array("x509_extensions" => "v3_req");
$cert = openssl_csr_sign($csr, $CAcrt, $CAkey, 100, $configArgs);
openssl_x509_export_to_file($cert, "childCert.crt");
Then if you want to add some more options, you can edit the "/etc/ssl/openssl.cnf" ssl config' file (debian path), and add these after the [ v3_req ] tag.
There appears to be no openssl_csr_free function.
At least not here.
If it's in the source, one might be able to just call it.
If it's not in the source, it probably should be.
In the PHP example above it uses "UK" as the country name which is incorrect, the country name must be "GB"
If you get the error:
error:0D11A086:asn1 encoding routines:ASN1_mbstring_copy:string too short
then look at your key:value pairs in the $dn (distinguished name) array.
If you have one value (like "organizationalUnitName" = "") set to an empty string, it will throw the above error.
Fix the error by either eliminating that array element from $dn completely, or using a space " " instead of an empty string.
I am using PHP-4.3.11.
The type of configargs--private_key_bits is a INTEGER, not a string.
An example of configration:
<?php
$config = array(
"digest_alg" => "sha1",
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_DSA,
"encrypt_key" => false
);
?>
As you probably guessed from the example, the documentation is misinforming. openssl_csr_new returns a CSR resource or FALSE on failure.
mixed openssl_csr_new (assoc_array dn, resource_privkey, [...])