PHP 8.5.0 Alpha 2 available for testing

openssl_csr_new

(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)

openssl_csr_newGenera una CSR

Descripción

openssl_csr_new(
    array $distinguished_names,
    #[\SensitiveParameter] ?OpenSSLAsymmetricKey &$private_key,
    ?array $options = null,
    ?array $extra_attributes = null
): OpenSSLCertificateSigningRequest|bool

openssl_csr_new() genera una nueva CSR (requisición de firma de certificado), basada en la información proporcionada por distinguished_names.

Nota: Debe existir un archivo openssl.cnf válido e instalado para que esta función opere correctamente. Ver las notas encontradas en la sección concerniente a la instalación para más información.

Parámetros

distinguished_names

El nombre distintivo (Distinguished Name) o los campos del sujeto a incluir en el certificado. El distinguished_names es un array asociativo cuyas claves representan los nombres de atributos de los Distinguished Names, y los valores pueden ser cadenas (para un valor único) o arrays (si se deben definir varios valores).

private_key

private_key debe ser una clave privada que haya sido generada por openssl_pkey_new() (u obtenida de otro modo mediante alguna de las funciones de la familia openssl_pkey), o la variable null. Si su valor es una variable null, se genera una nueva clave privada según las options proporcionadas y se asigna a la variable suministrada. La parte pública correspondiente de la clave se utilizará para firmar la CSR.

options

Por omisión, se utiliza el archivo openssl.conf del sistema para inicializar la requisición; puede especificarse una sección del archivo de configuración configurando la clave config_section_section en options. También puede especificarse un archivo de configuración alternativo de OpenSSL configurando el valor de config con la ruta del archivo a utilizar. Si las claves siguientes están presentes en options, se comportan como sus equivalentes en openssl.conf, según la lista siguiente.

Sobrescribir configuración
options tipo Equivalente de openssl.conf descripción
digest_alg string default_md Método de digest o firma de hash, generalmente uno de openssl_get_md_methods()
x509_extensions string x509_extensions Selecciona qué extensión utilizar al crear un certificado x509
req_extensions string req_extensions Selecciona qué extensión utilizar al crear una CSR
private_key_bits int default_bits Especifica la longitud en bits de la clave privada
private_key_type int none Especifica el tipo de clave privada a crear. Puede ser uno de OPENSSL_KEYTYPE_DSA, OPENSSL_KEYTYPE_DH, OPENSSL_KEYTYPE_RSA o OPENSSL_KEYTYPE_EC. El valor por omisión es OPENSSL_KEYTYPE_RSA.
encrypt_key bool encrypt_key ¿Debe estar cifrada la clave (con contraseña) exportada?
encrypt_key_cipher int none Una de las constantes cipher.
curve_name string none Uno de openssl_get_curve_names().
config string N/A Ruta hacia su archivo openssl.conf alternativo.

extra_attributes

extra_attributes se utiliza para especificar atributos adicionales para la CSR. Se trata de un array asociativo cuyas claves se convierten en OID y se aplican como atributos de CSR.

Valores devueltos

Devuelve la CSR en caso de éxito, true si la creación de la CSR tiene éxito pero falla la firma o false si ocurre un error.

Historial de cambios

Versión Descripción
8.4.0 El array asociativo distinguished_names ahora admite arrays como valores, permitiendo especificar varios valores para un mismo atributo.
8.4.0 El parámetro extra_attributes ahora define correctamente los atributos del CSR, en lugar de modificar el nombre distintivo del sujeto como hacía anteriormente de forma incorrecta.
8.0.0 csr ahora acepta una instancia de OpenSSLCertificateSigningRequest ; anteriormente, se aceptaba un resource de tipo OpenSSL X.509 CSR.
8.0.0 En caso de éxito, esta función ahora devuelve una instancia de OpenSSLAsymmetricKey ; anteriormente se devolvía una resource de tipo OpenSSL key.
7.1.0 options ahora admite curve_name.

Ejemplos

Ejemplo #1 Creación de un certificado autosignado

<?php
// para certificados SSL de servidor, el commonName es el nombre de dominio a proteger
// para certificados de correo electrónico S/MIME el commonName es el propietario de la dirección de correo
// los campos de ubicación e identificación hacen referencia al propietario del dominio o al objeto del correo a proteger
$dn = array(
"countryName" => "GB",
"stateOrProvinceName" => "Somerset",
"localityName" => "Glastonbury",
"organizationName" => "The Brain Room Limited",
"organizationalUnitName" => "PHP Documentation Team",
"commonName" => "Wez Furlong",
"emailAddress" => "wez@example.com"
);

// Genera un nuevo par de claves privada (y pública)
$privkey = openssl_pkey_new(array(
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
));

// Genera una requisición de firma de certificado
$csr = openssl_csr_new($dn, $privkey, array('digest_alg' => 'sha256'));

// Genera un certificado autosignado, válido durante 365 días
$x509 = openssl_csr_sign($csr, null, $privkey, $days=365, array('digest_alg' => 'sha256'));

// Guarde su clave privada, CSR y certificado autosignado para uso posterior
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);

// Muestra los errores que han ocurrido
while (($e = openssl_error_string()) !== false) {
echo
$e . "\n";
}
?>

Ejemplo #2 Crear un certificado ECC autosignado (a partir de PHP 7.1.0)

<?php
$subject
= array(
"commonName" => "docs.php.net",
);

// Genera un nuevo par de claves privada (y pública)
$private_key = openssl_pkey_new(array(
"private_key_type" => OPENSSL_KEYTYPE_EC,
"curve_name" => 'prime256v1',
));

// Genera una requisición de firma de certificado
$csr = openssl_csr_new($subject, $private_key, array('digest_alg' => 'sha384'));

// Genera un certificado EC autosignado
$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');
?>

Ver también

  • openssl_csr_sign() - Firma un CSR con otro certificado (o consigo mismo) y genera un certificado

add a note

User Contributed Notes 10 notes

up
11
The_Lost_One
15 years ago
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
);
?>
up
6
james at kirk dot com
10 years ago
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.
up
3
Anonymous
10 years ago
For those of you using Debian-based systems, the openssl configuration file is at: /etc/ssl/openssl.cnf
up
2
main ATT jokester DOTT fr
16 years ago
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.
up
3
alex at nodex dot co dot uk
10 years ago
In the PHP example above it uses "UK" as the country name which is incorrect, the country name must be "GB"
up
0
Richard Lynch
12 years ago
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.
up
0
Anonymous
20 years ago
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.
up
0
robertliu AT wiscore DOT com
20 years ago
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
);
?>
up
-1
dankybastard at hotmail
20 years ago
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, [...])
up
-1
@operator
8 years ago
One command to create modern certificate request with 4 SAN subdomain.
According to RFC you can change CN (common name) and subjectAltName. When cert validated searching in CN and subjectAltName.

openssl req -new -nodes -config <( cat <<-EOF
[req]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = re
distinguished_name = dn
[ dn ]
CN = my.tld
C = country
ST = state
L = location
O = ORGANISATION
[ re ]
subjectAltName = DNS.1: www.my.tld, DNS.2: www2.my.tld, DNS.3: www3.my.tld, DNS.4: www4.my.tld
EOF
) -keyout secret.key -out req.csr
To Top