For those of you using Debian-based systems, the openssl configuration file is at: /etc/ssl/openssl.cnf
(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)
openssl_csr_new — Genera una CSR
$dn
,&$privkey
,$configargs
= ?,$extraattribs
= ?
openssl_csr_new() genera una nueva CSR (Certificate Signing Request - Petición
de Firma de Certificado) basada en la información proporcionada por dn
, el
cuál representa el Nombre Distinguido que se va a usar en el certificado.
Nota: Necesita tener instalado un openssl.cnf válido para que esta función opere correctamente. Vea las notas sobre la sección de instalación para más información.
dn
El Nombre Distinguido que se va a usar en el certificado.
privkey
privkey
podría estar establecida a una clave privada que fue
generada previamente por openssl_pkey_new() (o
de otro modo, obtenida desde la otra familia de funciones openssl_pkey).
La parte pública correspondiente de la clave será usada para firmar la
CSR.
configargs
Por defecto, la información de su sistema openssl.conf
se usa para inicializar la petición; puede especificar una sección del archivo de
configuración estableciendo la clave config_sección_sección
de
configargs
. También puede especificar un archivo de configuración
de openssl alternativo estableciendo el valor de la clave
config
a la ruta del archivo que quiere utilizar.
Las siguientes claves, si están presentes en configargs
,
se comportan como sus equivalentes en el archivo openssl.conf
, como
está listado en la tabla de abajo.
clave configargs |
tipo | equivalente openssl.conf |
descripción |
---|---|---|---|
digest_alg | string | default_md | Selecciona qué método de resumen (digest) se va a usar |
x509_extensions | string | x509_extensions | Selecciona qué extensiones debería usarse cuando se crea un certificado x509 |
req_extensions | string | req_extensions | Selecciona qué extensiones debería usarse cuando se crea una CSR |
private_key_bits | integer | default_bits | Specifica cuántos bits deberían usarse para generar una clave privada |
private_key_type | integer | ninguno | Especifica el tipo de clave privada a crear. Ésta puede ser
OPENSSL_KEYTYPE_DSA ,
OPENSSL_KEYTYPE_DH o
OPENSSL_KEYTYPE_RSA .
El valor por defecto es OPENSSL_KEYTYPE_RSA el cuál
es el úncio tipo de clave soportado actualmente.
|
encrypt_key | boolean | encrypt_key | ¿Debería ser encriptada una clave exportada (con frase de contraseña)? |
encrypt_key_cipher | integer | none | Una de las constantes de cipher. |
extraattribs
extraattribs
se usa para especificar opciones de
configuración adicionales para la CSR. Ambos, dn
y
extraattribs
, son matrices asociativas cuyas claves son
convertidas a identificadores de objetos y aplicadas a las partes relevantes de la petición.
Devuelve la CSR.
Ejemplo #1 Crear un certificado autofirmado
<?php
// Rellenar la información del nombre distinguido que se va a usar en el certificado
// Debe cambiar los valores de estas claves para que coincidan con su nombre y
// compañía, o para se más exactos, el nombre y la compañía de la persona/sitio
// para el que va a generar el certificado.
// Para los certificados SSL, el nombre común (commonName) normalmente es el nombre de
// dominio que va a usar el certificado, pero para certificados S/MIME,
// el nombre común será el nombre de la persona que usará el
// certificado.
$dn = array(
"countryName" => "UK",
"stateOrProvinceName" => "Somerset",
"localityName" => "Glastonbury",
"organizationName" => "The Brain Room Limited",
"organizationalUnitName" => "PHP Documentation Team",
"commonName" => "Wez Furlong",
"emailAddress" => "wez@example.com"
);
// Generar una nueva pareja de clave privada (y pública)
$privkey = openssl_pkey_new();
// Generar una petición de firma de certificado
$csr = openssl_csr_new($dn, $privkey);
// Normalmente querrá crear un certificado autofirmado en este
// punto hasta que su AC satisfaga su petición.
// Esto crea un certificado autofirmado que es válido por 365 días
$sscert = openssl_csr_sign($csr, null, $privkey, 365);
// Ahora querrá preservar su clave privada, CSR y certificado
// autofirmado por lo que pueden ser instalados en su servidor web, servidor de correo
// o cliente de correo (dependiendo del uso previsto para el certificado).
// Este ejemplo muestra cómo obtener estas cosas con variables, pero
// también puede almacenarlas directamente en archivos.
// Normalmente, enviará la CSR a su AC, la cuál se la emitirá después
// con el certificado "real".
openssl_csr_export($csr, $csrout) and var_dump($csrout);
openssl_x509_export($sscert, $certout) and var_dump($certout);
openssl_pkey_export($privkey, $pkeyout, "mypassword") and var_dump($pkeyout);
// Mostrar cualquier error que ocurra
while (($e = openssl_error_string()) !== false) {
echo $e . "\n";
}
?>
For those of you using Debian-based systems, the openssl configuration file is at: /etc/ssl/openssl.cnf
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.
In the PHP example above it uses "UK" as the country name which is incorrect, the country name must be "GB"
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.
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, [...])
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