PHP 8.4.2 Released!

openssl_csr_new

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

openssl_csr_newGera um CSR

Descrição

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

openssl_csr_new() gera um novo CSR com base na informação fornecida por distinguished_names.

Nota: É preciso ter um arquivo openssl.cnf válido instalado para que esta função funcione corretamente. Consulte as notas na seção de instalação para obter mais informações.

Parâmetros

distinguished_names

O Nome Distinto (DN) ou campos de assunto a serem usados no certificado. O parâmetro distinguished_names é um array associativo onde as chaves representam os nomes de atributo dos Nomes Distintos e os valores podem ser strings (para valores simples) ou arrays (se for necessário definir múltiplos valores).

private_key

private_key deve ser definido par uma chave privada que tenha sido gerada anteriormente por openssl_pkey_new() (ou de outra forma obtida pelas outras funções da família openssl_pkey), ou uma variável null. Se o valor for uma variável null, uma nova chave primária será gerada com base no parâmetro options fornecido e será atribuída à variável informada. A parte pública correspondente da chave será usada para assinar o CSR.

options

Por padrão, a informação no openssl.conf do sistema é utilizada para inicializar a requisição; uma seção do arquivo de configuração pode ser especificada configurando a chave config_section_section no parâmetro options. Um arquivo de configuração Openssl alternativo pode ser especificado configurando o valor da chave config para o caminho do arquivo a ser usado. As chaves a seguir, se estiverem presentes em options, comportam-se como suas equivalentes no openssl.conf, como listadas na tabela abaixo.

Subsituição de configuração
Chave options Tipo Equivalente no openssl.conf Descrição
digest_alg string default_md Método de resumo ou de hash de assinatura, normalmente um dos métodos informados por openssl_get_md_methods()
x509_extensions string x509_extensions Seleciona quais extensões devem ser usadas ao criar um certificado x509
req_extensions string req_extensions Seleciona quais extensões devem ser usadas ao criar um CSR
private_key_bits int default_bits Especifica quantos bits devem ser usados para gerar uma chave privada
private_key_type int none Especifica o tipo de chave privada a ser criada. Pode ser uma das constantes OPENSSL_KEYTYPE_DSA, OPENSSL_KEYTYPE_DH, OPENSSL_KEYTYPE_RSA ou OPENSSL_KEYTYPE_EC. O valor padrão é OPENSSL_KEYTYPE_RSA.
encrypt_key bool encrypt_key Uma chave exportada (com senha) deve ser criptografada?
encrypt_key_cipher int none Uma das constantes de cifra.
curve_name string none Um dos nomes de curva informados por openssl_get_curve_names().
config string N/A Caminho para o arquivo alternativo openssl.conf.

extra_attributes

extra_attributes é usado para especificar atributos adicionais para o CSR. É um array associativo cujas chaves são convertidas para OIDs e aplicadas como atributos CSR.

Valor Retornado

Retorna o CSR em caso de sucesso, true se a criação do CSR for bem sucedida mas a assintura falhar ou false em caso de falha.

Registro de Alterações

Versão Descrição
8.4.0 O array associativo do parâmetro distinguished_names agora suporta arrays como valores, permitindo que múltiplos sejam especificados para um único atributo.
8.4.0 O parâmetro extra_attributes agora define corretamente os atributos CSR, ao invés de modificar o Nome Distinto do assunto como fazia antes incorretamente.
8.0.0 Em caso de sucesso, esta função agora retorna uma instância de OpenSSLCertificateSigningRequest; anteriormente, retornava um resource do tipo OpenSSL X.509 CSR.
8.0.0 private_key agora aceita uma instância de OpenSSLAsymmetricKey; anteriormente, aceitava um resource do tipo OpenSSL key.
7.1.0 options agora também suporta curve_name.

Exemplos

Exemplo #1 Criando um certificado autoassinado

<?php
// para certificados SSL de servidor, o commonName é o domínio a ser protegido
// para certificados de e-mail S/MIME, o commonName é o proprietário do endereço de e-mail
// campos de localização e identificação referem-se ao proprietário do domínio ou do e-mail a serem protegidos
$dn = array(
"countryName" => "GB",
"stateOrProvinceName" => "Somerset",
"localityName" => "Glastonbury",
"organizationName" => "The Brain Room Limited",
"organizationalUnitName" => "PHP Documentation Team",
"commonName" => "Wez Furlong",
"emailAddress" => "wez@example.com"
);

// Gera um novo par de chaves privadas (e públicas)
$privkey = openssl_pkey_new(array(
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
));

// Gera uma requisição de assinatura de certificado
$csr = openssl_csr_new($dn, $privkey, array('digest_alg' => 'sha256'));

// Gera um certificado autoassinado, válido por 365 dias
$x509 = openssl_csr_sign($csr, null, $privkey, $days=365, array('digest_alg' => 'sha256'));

// Grava a chave provada, o CSR e o certificado autoassinado 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);

// Exibe erros que possam ter ocorrido
while (($e = openssl_error_string()) !== false) {
echo
$e . "\n";
}
?>

Exemplo #2 Criando um certificado ECC autoassinado (a partir do PHP 7.1.0)

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

// Gere um novo par de chaves privadas (e públicas)
$private_key = openssl_pkey_new(array(
"private_key_type" => OPENSSL_KEYTYPE_EC,
"curve_name" => 'prime256v1',
));

// Gera uma requisição de assinatura de certificado
$csr = openssl_csr_new($subject, $private_key, array('digest_alg' => 'sha384'));

// Gera um certificado EC autoassinado
$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');
?>

Veja Também

  • openssl_csr_sign() - Assina um CSR com outro certificado (ou ele mesmo) e gera um certificado

adicione uma nota

Notas Enviadas por Usuários (em inglês) 10 notes

up
12
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
9 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
9 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
1
Richard Lynch
11 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
2
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
Anonymous
19 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
19 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
19 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
-3
@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